import type * as shxInterfaces from '@smarthome.exchange/interfaces';
import { BaseIntegration } from '../../core/classes.baseintegration.js';
import type { IIntegrationEntity, IIntegrationRuntime, IIntegrationSetupContext, IServiceCallRequest, IServiceCallResult } from '../../core/types.js';
import { BrotherClient } from './brother.classes.client.js';
import { BrotherConfigFlow } from './brother.classes.configflow.js';
import { brotherDefaultCommunity, brotherDefaultPort, brotherDomain } from './brother.constants.js';
import { createBrotherDiscoveryDescriptor } from './brother.discovery.js';
import { BrotherMapper } from './brother.mapper.js';
import type { IBrotherConfig } from './brother.types.js';

export class BrotherIntegration extends BaseIntegration<IBrotherConfig> {
  public readonly domain = brotherDomain;
  public readonly displayName = 'Brother Printer';
  public readonly status = 'read-only-runtime' as const;
  public readonly discoveryDescriptor = createBrotherDiscoveryDescriptor();
  public readonly configFlow = new BrotherConfigFlow();
  public readonly metadata = {
    source: 'home-assistant/core',
    upstreamPath: 'homeassistant/components/brother',
    upstreamDomain: brotherDomain,
    integrationType: 'device',
    iotClass: 'local_polling',
    qualityScale: 'platinum',
    requirements: ['brother==6.1.0'],
    dependencies: [] as string[],
    afterDependencies: ['snmp'],
    codeowners: ['@bieniu'],
    configFlow: true,
    documentation: 'https://www.home-assistant.io/integrations/brother',
    zeroconf: [{ name: 'brother*', type: '_printer._tcp.local.' }],
    defaults: {
      port: brotherDefaultPort,
      community: brotherDefaultCommunity,
      printerType: 'laser',
    },
    runtime: {
      type: 'read-only-runtime',
      polling: 'snapshot/manual data and injected SNMP-style clients; native UDP SNMP transport is not implemented',
      services: ['snapshot', 'status', 'refresh'],
      controls: false,
    },
    localApi: {
      implemented: [
        'Home Assistant Brother zeroconf shape (_printer._tcp.local. with brother* service name)',
        'Brother Python library raw SNMP OID snapshot parsing for counters, maintenance, nextcare, status, model, serial, MAC, firmware, and uptime',
        'manual sensor snapshots and injected clients exposing getSnapshot(), getRawData(), getSensors(), or asyncUpdate()',
      ],
      explicitUnsupported: [
        'native live UDP SNMP transport without an injected client',
        'SNMP writes such as setting printer datetime',
        'claiming command success for any read-only Brother printer operation',
      ],
    },
  };

  public async setup(configArg: IBrotherConfig, contextArg: IIntegrationSetupContext): Promise<IIntegrationRuntime> {
    void contextArg;
    return new BrotherRuntime(new BrotherClient(configArg));
  }

  public async destroy(): Promise<void> {}
}

export class HomeAssistantBrotherIntegration extends BrotherIntegration {}

class BrotherRuntime implements IIntegrationRuntime {
  public domain = brotherDomain;

  constructor(private readonly client: BrotherClient) {}

  public async devices(): Promise<shxInterfaces.data.IDeviceDefinition[]> {
    return BrotherMapper.toDevices(await this.client.getSnapshot());
  }

  public async entities(): Promise<IIntegrationEntity[]> {
    return BrotherMapper.toEntities(await this.client.getSnapshot());
  }

  public async callService(requestArg: IServiceCallRequest): Promise<IServiceCallResult> {
    try {
      if (requestArg.domain !== brotherDomain) {
        return { success: false, error: `Unsupported Brother service domain: ${requestArg.domain}` };
      }
      if (requestArg.service === 'snapshot' || requestArg.service === 'status') {
        return { success: true, data: await this.client.getSnapshot() };
      }
      if (requestArg.service === 'refresh') {
        const result = await this.client.refresh();
        return result.success ? { success: true, data: result.snapshot } : { success: false, error: result.error || 'Brother refresh requires snapshot, sensors, rawData, or an injected client.', data: result.snapshot };
      }
      return { success: false, error: `Unsupported Brother service: ${requestArg.service}. This integration is read-only.` };
    } catch (errorArg) {
      return { success: false, error: errorArg instanceof Error ? errorArg.message : String(errorArg) };
    }
  }

  public async destroy(): Promise<void> {
    await this.client.destroy();
  }
}
