import type { IConfigFlow, IConfigFlowContext, IConfigFlowStep, IDiscoveryCandidate } from '../../core/types.js';
import type { IAdguardConfig, IAdguardSnapshot } from './adguard.types.js';
import { adguardDefaultPort } from './adguard.types.js';

export class AdguardConfigFlow implements IConfigFlow<IAdguardConfig> {
  public async start(candidateArg: IDiscoveryCandidate, contextArg: IConfigFlowContext): Promise<IConfigFlowStep<IAdguardConfig>> {
    void contextArg;
    return {
      kind: 'form',
      title: 'Set up AdGuard Home',
      description: 'Connect to a local AdGuard Home HTTP API. This flow validates configuration shape and keeps live command success tied to a real HTTP client or command executor.',
      fields: [
        { name: 'host', label: 'Host or URL', type: 'text', required: true },
        { name: 'port', label: 'Port', type: 'number' },
        { name: 'ssl', label: 'Use HTTPS', type: 'boolean' },
        { name: 'verifySsl', label: 'Verify TLS certificate', type: 'boolean' },
        { name: 'basePath', label: 'Base path', type: 'text' },
        { name: 'username', label: 'Username', type: 'text' },
        { name: 'password', label: 'Password', type: 'password' },
      ],
      submit: async (valuesArg) => {
        const parsed = parseHostInput(stringValue(valuesArg.host) || candidateArg.host || '');
        if (!parsed.host) {
          return { kind: 'error', title: 'Invalid AdGuard Home host', error: 'AdGuard Home setup requires a hostname, IP address, or URL.' };
        }

        const port = numberValue(valuesArg.port) || parsed.port || candidateArg.port || adguardDefaultPort;
        if (!Number.isInteger(port) || port < 1 || port > 65535) {
          return { kind: 'error', title: 'Invalid AdGuard Home port', error: 'AdGuard Home port must be an integer between 1 and 65535.' };
        }

        const username = stringValue(valuesArg.username);
        const password = stringValue(valuesArg.password);
        if (Boolean(username) !== Boolean(password)) {
          return { kind: 'error', title: 'Incomplete AdGuard Home credentials', error: 'AdGuard Home username and password must be provided together.' };
        }

        const ssl = booleanValue(valuesArg.ssl) ?? parsed.ssl ?? booleanValue(candidateArg.metadata?.ssl) ?? false;
        const verifySsl = booleanValue(valuesArg.verifySsl) ?? booleanValue(candidateArg.metadata?.verifySsl) ?? true;
        const basePath = stringValue(valuesArg.basePath) || parsed.basePath || stringValue(candidateArg.metadata?.basePath);

        return {
          kind: 'done',
          title: 'AdGuard Home configured',
          config: {
            host: parsed.host,
            port,
            ssl,
            verifySsl,
            basePath,
            username,
            password,
            name: candidateArg.name || 'AdGuard Home',
            uniqueId: candidateArg.id,
            snapshot: isAdguardSnapshot(candidateArg.metadata?.snapshot) ? candidateArg.metadata.snapshot : undefined,
          },
        };
      },
    };
  }
}

const parseHostInput = (valueArg: string): { host?: string; port?: number; ssl?: boolean; basePath?: string } => {
  const value = valueArg.trim();
  if (!value) {
    return {};
  }
  if (!value.includes('://')) {
    return { host: value };
  }
  try {
    const parsed = new URL(value);
    return {
      host: parsed.hostname,
      port: parsed.port ? Number(parsed.port) : undefined,
      ssl: parsed.protocol === 'https:',
      basePath: parsed.pathname && parsed.pathname !== '/' ? parsed.pathname : undefined,
    };
  } catch {
    return {};
  }
};

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

const numberValue = (valueArg: unknown): number | undefined => {
  if (typeof valueArg === 'number' && Number.isFinite(valueArg)) return valueArg;
  if (typeof valueArg === 'string' && valueArg.trim() && Number.isFinite(Number(valueArg))) return Number(valueArg);
  return undefined;
};

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

const isAdguardSnapshot = (valueArg: unknown): valueArg is IAdguardSnapshot => {
  return typeof valueArg === 'object' && valueArg !== null && 'status' in valueArg && 'online' in valueArg;
};
