import { BaseMigration } from './base-migration.ts';
import type { TQueryFunction } from '../types.ts';

export class Migration003DomainManagement extends BaseMigration {
  readonly version = 3;
  readonly description = 'Domain management tables';

  up(query: TQueryFunction): void {
    query(`
      CREATE TABLE domains (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        domain TEXT NOT NULL UNIQUE,
        dns_provider TEXT,
        cloudflare_zone_id TEXT,
        is_obsolete INTEGER NOT NULL DEFAULT 0,
        default_wildcard INTEGER NOT NULL DEFAULT 1,
        created_at REAL NOT NULL,
        updated_at REAL NOT NULL
      )
    `);

    query(`
      CREATE TABLE certificates (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        domain_id INTEGER NOT NULL,
        cert_domain TEXT NOT NULL,
        is_wildcard INTEGER NOT NULL DEFAULT 0,
        cert_path TEXT NOT NULL,
        key_path TEXT NOT NULL,
        full_chain_path TEXT NOT NULL,
        expiry_date REAL NOT NULL,
        issuer TEXT NOT NULL,
        is_valid INTEGER NOT NULL DEFAULT 1,
        created_at REAL NOT NULL,
        updated_at REAL NOT NULL,
        FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE
      )
    `);

    query(`
      CREATE TABLE cert_requirements (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        service_id INTEGER NOT NULL,
        domain_id INTEGER NOT NULL,
        subdomain TEXT NOT NULL,
        certificate_id INTEGER,
        status TEXT NOT NULL DEFAULT 'pending',
        created_at REAL NOT NULL,
        updated_at REAL NOT NULL,
        FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE,
        FOREIGN KEY (domain_id) REFERENCES domains(id) ON DELETE CASCADE,
        FOREIGN KEY (certificate_id) REFERENCES certificates(id) ON DELETE SET NULL
      )
    `);

    // Migrate data from old ssl_certificates table
    interface OldSslCert {
      id?: number;
      domain?: string;
      cert_path?: string;
      key_path?: string;
      full_chain_path?: string;
      expiry_date?: number;
      issuer?: string;
      created_at?: number;
      updated_at?: number;
      [key: number]: unknown;
    }
    const existingCerts = query<OldSslCert>('SELECT * FROM ssl_certificates');

    const now = Date.now();
    const domainMap = new Map<string, number>();

    for (const cert of existingCerts) {
      const domain = String(cert.domain ?? (cert as Record<number, unknown>)[1]);
      if (!domainMap.has(domain)) {
        query(
          'INSERT INTO domains (domain, dns_provider, is_obsolete, default_wildcard, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)',
          [domain, null, 0, 1, now, now],
        );
        const result = query<{ id?: number; [key: number]: unknown }>(
          'SELECT last_insert_rowid() as id',
        );
        const domainId = result[0].id ?? (result[0] as Record<number, unknown>)[0];
        domainMap.set(domain, Number(domainId));
      }
    }

    for (const cert of existingCerts) {
      const domain = String(cert.domain ?? (cert as Record<number, unknown>)[1]);
      const domainId = domainMap.get(domain);

      query(
        `INSERT INTO certificates (
          domain_id, cert_domain, is_wildcard, cert_path, key_path, full_chain_path,
          expiry_date, issuer, is_valid, created_at, updated_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          domainId,
          domain,
          0,
          String(cert.cert_path ?? (cert as Record<number, unknown>)[2]),
          String(cert.key_path ?? (cert as Record<number, unknown>)[3]),
          String(cert.full_chain_path ?? (cert as Record<number, unknown>)[4]),
          Number(cert.expiry_date ?? (cert as Record<number, unknown>)[5]),
          String(cert.issuer ?? (cert as Record<number, unknown>)[6]),
          1,
          Number(cert.created_at ?? (cert as Record<number, unknown>)[7]),
          Number(cert.updated_at ?? (cert as Record<number, unknown>)[8]),
        ],
      );
    }

    query('DROP TABLE ssl_certificates');
    query('CREATE INDEX IF NOT EXISTS idx_domains_cloudflare_zone ON domains(cloudflare_zone_id)');
    query('CREATE INDEX IF NOT EXISTS idx_certificates_domain ON certificates(domain_id)');
    query('CREATE INDEX IF NOT EXISTS idx_certificates_expiry ON certificates(expiry_date)');
    query(
      'CREATE INDEX IF NOT EXISTS idx_cert_requirements_service ON cert_requirements(service_id)',
    );
    query(
      'CREATE INDEX IF NOT EXISTS idx_cert_requirements_domain ON cert_requirements(domain_id)',
    );
  }
}
