import type { IConfigFlow, IConfigFlowContext, IConfigFlowStep, IDiscoveryCandidate } from '../../core/types.js';
import type { IKnxConfig, TKnxConnectionType } from './knx.types.js';

export class KnxConfigFlow implements IConfigFlow<IKnxConfig> {
  public async start(candidateArg: IDiscoveryCandidate, contextArg: IConfigFlowContext): Promise<IConfigFlowStep<IKnxConfig>> {
    void contextArg;
    return {
      kind: 'form',
      title: 'Connect KNX/IP interface',
      description: 'Configure KNXnet/IP automatic, routing, or tunneling metadata. Live bus transport is intentionally not implemented in this dependency-free TypeScript port.',
      fields: [
        { name: 'connectionType', label: 'Connection type', type: 'select', required: true, options: [
          { label: 'Automatic', value: 'automatic' },
          { label: 'Routing', value: 'routing' },
          { label: 'Secure routing', value: 'routing_secure' },
          { label: 'Tunneling UDP', value: 'tunneling' },
          { label: 'Tunneling TCP', value: 'tunneling_tcp' },
          { label: 'Secure tunneling TCP', value: 'tunneling_tcp_secure' },
        ] },
        { name: 'host', label: 'Gateway host', type: 'text' },
        { name: 'port', label: 'Gateway port', type: 'number' },
        { name: 'individualAddress', label: 'Individual address', type: 'text' },
        { name: 'localIp', label: 'Local IP', type: 'text' },
        { name: 'routeBack', label: 'Route back', type: 'boolean' },
        { name: 'multicastGroup', label: 'Routing multicast group', type: 'text' },
        { name: 'multicastPort', label: 'Routing multicast port', type: 'number' },
        { name: 'stateUpdater', label: 'Enable state updater', type: 'boolean' },
        { name: 'rateLimit', label: 'Telegram rate limit', type: 'number' },
      ],
      submit: async (valuesArg) => ({
        kind: 'done',
        title: 'KNX configured',
        config: this.configFromValues(candidateArg, valuesArg),
      }),
    };
  }

  private configFromValues(candidateArg: IDiscoveryCandidate, valuesArg: Record<string, unknown>): IKnxConfig {
    const metadata = candidateArg.metadata || {};
    const connectionType = this.stringValue(valuesArg.connectionType)
      || this.stringValue(metadata.connectionType || metadata.connection_type)
      || (candidateArg.host ? 'tunneling' : 'automatic');
    return {
      connectionType: connectionType as TKnxConnectionType,
      host: this.stringValue(valuesArg.host) || candidateArg.host,
      port: this.numberValue(valuesArg.port) || candidateArg.port || 3671,
      individualAddress: this.stringValue(valuesArg.individualAddress) || this.stringValue(metadata.individualAddress || metadata.individual_address) || '0.0.240',
      localIp: this.stringValue(valuesArg.localIp) || this.stringValue(metadata.localIp || metadata.local_ip),
      routeBack: this.booleanValue(valuesArg.routeBack) ?? this.booleanValue(metadata.routeBack || metadata.route_back) ?? false,
      multicastGroup: this.stringValue(valuesArg.multicastGroup) || this.stringValue(metadata.multicastGroup || metadata.multicast_group) || '224.0.23.12',
      multicastPort: this.numberValue(valuesArg.multicastPort) || this.numberValue(metadata.multicastPort || metadata.multicast_port) || 3671,
      stateUpdater: this.booleanValue(valuesArg.stateUpdater) ?? true,
      rateLimit: this.numberValue(valuesArg.rateLimit) || 0,
      gateway: metadata.descriptor as IKnxConfig['gateway'],
    };
  }

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

  private numberValue(valueArg: unknown): number | undefined {
    return typeof valueArg === 'number' && Number.isFinite(valueArg) ? valueArg : undefined;
  }

  private booleanValue(valueArg: unknown): boolean | undefined {
    return typeof valueArg === 'boolean' ? valueArg : undefined;
  }
}
