import type { IConfigFlow, IConfigFlowContext, IConfigFlowStep, IDiscoveryCandidate } from '../../core/types.js';
import type { IBoschShcConfig, IBoschShcSnapshot } from './bosch_shc.types.js';

export class BoschShcConfigFlow implements IConfigFlow<IBoschShcConfig> {
  public async start(candidateArg: IDiscoveryCandidate, contextArg: IConfigFlowContext): Promise<IConfigFlowStep<IBoschShcConfig>> {
    void contextArg;
    return {
      kind: 'form',
      title: 'Set up Bosch SHC',
      description: 'Configure a local Bosch Smart Home Controller. Use an existing certificate/key or a snapshot; native pairing and live TLS transport require an injected executor.',
      fields: [
        { name: 'host', label: 'Host', type: 'text', required: true },
        { name: 'sslCertificate', label: 'Client certificate path or PEM', type: 'text' },
        { name: 'sslKey', label: 'Client key path or PEM', type: 'password' },
        { name: 'token', label: 'Registration token', type: 'text' },
        { name: 'hostname', label: 'Controller hostname from token', type: 'text' },
        { name: 'password', label: 'System password for executor-based pairing', type: 'password' },
        { name: 'snapshotJson', label: 'Controller snapshot JSON', type: 'text' },
      ],
      submit: async (valuesArg) => this.finish(valuesArg, candidateArg),
    };
  }

  private async finish(valuesArg: Record<string, unknown>, candidateArg: IDiscoveryCandidate): Promise<IConfigFlowStep<IBoschShcConfig>> {
    const host = this.stringValue(valuesArg.host) || candidateArg.host;
    if (!host || host.includes('://')) {
      return { kind: 'error', title: 'Invalid Bosch SHC host', error: 'Bosch SHC host must be a hostname or IP address without a URL scheme.' };
    }

    const sslCertificate = this.stringValue(valuesArg.sslCertificate);
    const sslKey = this.stringValue(valuesArg.sslKey);
    if (Boolean(sslCertificate) !== Boolean(sslKey)) {
      return { kind: 'error', title: 'Incomplete Bosch SHC TLS credentials', error: 'Bosch SHC certificate and key must be provided together.' };
    }

    const snapshot = this.jsonValue<IBoschShcSnapshot>(valuesArg.snapshotJson)
      || this.objectValue<IBoschShcSnapshot>(candidateArg.metadata?.snapshot);
    const password = this.stringValue(valuesArg.password);
    if (password && !sslCertificate && !snapshot) {
      return {
        kind: 'error',
        title: 'Bosch SHC pairing requires an executor',
        error: 'Native Bosch SHC pairing/certificate generation is not implemented here. Inject an executor/client or provide existing certificate/key credentials.',
      };
    }

    return {
      kind: 'done',
      title: 'Bosch SHC configured',
      config: {
        host,
        sslCertificate,
        sslKey,
        token: this.stringValue(valuesArg.token),
        hostname: this.stringValue(valuesArg.hostname),
        uniqueId: candidateArg.id || snapshot?.uniqueId || snapshot?.information?.macAddress,
        name: candidateArg.name || snapshot?.name,
        snapshot: snapshot ? { ...snapshot, host: snapshot.host || host } : undefined,
      },
    };
  }

  private jsonValue<TValue>(valueArg: unknown): TValue | undefined {
    if (typeof valueArg !== 'string' || !valueArg.trim()) return undefined;
    try {
      const parsed = JSON.parse(valueArg) as unknown;
      return this.isRecord(parsed) ? parsed as TValue : undefined;
    } catch {
      return undefined;
    }
  }

  private objectValue<TValue>(valueArg: unknown): TValue | undefined {
    return this.isRecord(valueArg) ? valueArg as TValue : undefined;
  }

  private stringValue(valueArg: unknown): string | undefined {
    return typeof valueArg === 'string' && valueArg.trim() ? valueArg.trim() : undefined;
  }

  private isRecord(valueArg: unknown): valueArg is Record<string, unknown> {
    return typeof valueArg === 'object' && valueArg !== null && !Array.isArray(valueArg);
  }
}
