import {
  DeesElement,
  html,
  customElement,
  type TemplateResult,
  css,
  state,
  cssManager,
} from '@design.estate/dees-element';
import * as appstate from '../../appstate.js';
import * as interfaces from '../../../dist_ts_interfaces/index.js';
import { viewHostCss } from '../shared/css.js';
import { type IStatsTile } from '@design.estate/dees-catalog';

declare global {
  interface HTMLElementTagNameMap {
    'ops-view-email-domains': OpsViewEmailDomains;
  }
}

@customElement('ops-view-email-domains')
export class OpsViewEmailDomains extends DeesElement {
  @state()
  accessor emailDomainsState: appstate.IEmailDomainsState =
    appstate.emailDomainsStatePart.getState()!;

  @state()
  accessor domainsState: appstate.IDomainsState = appstate.domainsStatePart.getState()!;

  constructor() {
    super();
    const sub = appstate.emailDomainsStatePart.select().subscribe((s) => {
      this.emailDomainsState = s;
    });
    this.rxSubscriptions.push(sub);
    const domSub = appstate.domainsStatePart.select().subscribe((s) => {
      this.domainsState = s;
    });
    this.rxSubscriptions.push(domSub);
  }

  async connectedCallback() {
    await super.connectedCallback();
    await appstate.emailDomainsStatePart.dispatchAction(appstate.fetchEmailDomainsAction, null);
    await appstate.domainsStatePart.dispatchAction(appstate.fetchDomainsAndProvidersAction, null);
  }

  public static styles = [
    cssManager.defaultStyles,
    viewHostCss,
    css`
      .emailDomainsContainer {
        display: flex;
        flex-direction: column;
        gap: 24px;
      }

      .statusBadge {
        display: inline-flex;
        align-items: center;
        padding: 3px 10px;
        border-radius: 12px;
        font-size: 12px;
        font-weight: 600;
        letter-spacing: 0.02em;
        text-transform: uppercase;
      }

      .statusBadge.valid {
        background: ${cssManager.bdTheme('#dcfce7', '#14532d')};
        color: ${cssManager.bdTheme('#166534', '#4ade80')};
      }

      .statusBadge.missing {
        background: ${cssManager.bdTheme('#fef2f2', '#450a0a')};
        color: ${cssManager.bdTheme('#991b1b', '#f87171')};
      }

      .statusBadge.invalid {
        background: ${cssManager.bdTheme('#fff7ed', '#431407')};
        color: ${cssManager.bdTheme('#9a3412', '#fb923c')};
      }

      .statusBadge.unchecked {
        background: ${cssManager.bdTheme('#f3f4f6', '#1f2937')};
        color: ${cssManager.bdTheme('#4b5563', '#9ca3af')};
      }

      .sourceBadge {
        display: inline-flex;
        align-items: center;
        padding: 3px 8px;
        border-radius: 4px;
        font-size: 11px;
        font-weight: 500;
        background: ${cssManager.bdTheme('#f3f4f6', '#1f2937')};
        color: ${cssManager.bdTheme('#374151', '#d1d5db')};
      }
    `,
  ];

  public render(): TemplateResult {
    const domains = this.emailDomainsState.domains;
    const settings = this.emailDomainsState.settings;
    const validCount = domains.filter(
      (d) =>
        d.dnsStatus.mx === 'valid' &&
        d.dnsStatus.spf === 'valid' &&
        d.dnsStatus.dkim === 'valid' &&
        d.dnsStatus.dmarc === 'valid',
    ).length;
    const issueCount = domains.length - validCount;

    const tiles: IStatsTile[] = [
      {
        id: 'total',
        title: 'Total Domains',
        value: domains.length,
        type: 'number',
        icon: 'lucide:globe',
        color: '#3b82f6',
      },
      {
        id: 'valid',
        title: 'Valid DNS',
        value: validCount,
        type: 'number',
        icon: 'lucide:Check',
        color: '#22c55e',
      },
      {
        id: 'server',
        title: 'Server',
        value: settings?.enabled ? 'enabled' : 'disabled',
        type: 'text',
        icon: 'lucide:mail-check',
        color: settings?.enabled ? '#22c55e' : '#6b7280',
      },
      {
        id: 'ports',
        title: 'SMTP Ports',
        value: settings?.ports?.join(', ') || 'none',
        type: 'text',
        icon: 'lucide:plug',
        color: '#0ea5e9',
      },
      {
        id: 'issues',
        title: 'Issues',
        value: issueCount,
        type: 'number',
        icon: 'lucide:TriangleAlert',
        color: issueCount > 0 ? '#ef4444' : '#22c55e',
      },
      {
        id: 'dkim',
        title: 'DKIM Active',
        value: domains.filter((d) => d.dkim.publicKey).length,
        type: 'number',
        icon: 'lucide:KeyRound',
        color: '#8b5cf6',
      },
    ];

    return html`
      <dees-heading level="3">Email Domains</dees-heading>

      <div class="emailDomainsContainer">
        <dees-statsgrid
          .tiles=${tiles}
          .minTileWidth=${200}
          .gridActions=${[
            {
              name: 'Refresh',
              iconName: 'lucide:RefreshCw',
              action: async () => {
                await appstate.emailDomainsStatePart.dispatchAction(
                  appstate.fetchEmailDomainsAction,
                  null,
                );
              },
            },
            {
              name: 'Settings',
              iconName: 'lucide:settings',
              action: async () => {
                await this.showSettingsDialog();
              },
            },
          ]}
        ></dees-statsgrid>

        <dees-table
          .heading1=${'Email Domains'}
          .heading2=${'DKIM, SPF, DMARC and MX management'}
          .data=${domains}
          .showColumnFilters=${true}
          .displayFunction=${(d: interfaces.data.IEmailDomain) => ({
            Domain: d.domain,
            Source: this.renderSourceBadge(d.linkedDomainId),
            MX: this.renderDnsStatus(d.dnsStatus.mx),
            SPF: this.renderDnsStatus(d.dnsStatus.spf),
            DKIM: this.renderDnsStatus(d.dnsStatus.dkim),
            DMARC: this.renderDnsStatus(d.dnsStatus.dmarc),
          })}
          .dataActions=${[
            {
              name: 'Add Email Domain',
              iconName: 'lucide:plus',
              type: ['header'] as any,
              actionFunc: async () => {
                await this.showCreateDialog();
              },
            },
            {
              name: 'Validate DNS',
              iconName: 'lucide:search-check',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const d = actionData.item as interfaces.data.IEmailDomain;
                await appstate.emailDomainsStatePart.dispatchAction(
                  appstate.validateEmailDomainAction,
                  d.id,
                );
                const { DeesToast } = await import('@design.estate/dees-catalog');
                DeesToast.show({ message: `DNS validated for ${d.domain}`, type: 'success', duration: 2500 });
              },
            },
            {
              name: 'Provision DNS',
              iconName: 'lucide:wand-sparkles',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const d = actionData.item as interfaces.data.IEmailDomain;
                await appstate.emailDomainsStatePart.dispatchAction(
                  appstate.provisionEmailDomainDnsAction,
                  d.id,
                );
                const { DeesToast } = await import('@design.estate/dees-catalog');
                DeesToast.show({ message: `DNS records provisioned for ${d.domain}`, type: 'success', duration: 2500 });
              },
            },
            {
              name: 'View DNS Records',
              iconName: 'lucide:list',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const d = actionData.item as interfaces.data.IEmailDomain;
                await this.showDnsRecordsDialog(d);
              },
            },
            {
              name: 'Delete',
              iconName: 'lucide:trash2',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const d = actionData.item as interfaces.data.IEmailDomain;
                await appstate.emailDomainsStatePart.dispatchAction(
                  appstate.deleteEmailDomainAction,
                  d.id,
                );
              },
            },
          ]}
          dataName="email domain"
        ></dees-table>
      </div>
    `;
  }

  private renderDnsStatus(status: interfaces.data.TDnsRecordStatus): TemplateResult {
    return html`<span class="statusBadge ${status}">${status}</span>`;
  }

  private renderSourceBadge(linkedDomainId: string): TemplateResult {
    const domain = this.domainsState.domains.find((d) => d.id === linkedDomainId);
    if (!domain) return html`<span class="sourceBadge">unknown</span>`;
    const label =
      domain.source === 'dcrouter'
        ? 'dcrouter'
        : this.domainsState.providers.find((p) => p.id === domain.providerId)?.name || 'provider';
    return html`<span class="sourceBadge">${label}</span>`;
  }

  private parsePortList(value: string): number[] {
    return value
      .split(',')
      .map((part) => Number.parseInt(part.trim(), 10))
      .filter((port) => Number.isInteger(port));
  }

  private parsePortMapping(value: string): Record<number, number> | null {
    const trimmed = value.trim();
    if (!trimmed) return null;
    const mapping: Record<number, number> = {};
    for (const pair of trimmed.split(',')) {
      const [externalPort, internalPort] = pair
        .split(':')
        .map((part) => Number.parseInt(part.trim(), 10));
      if (Number.isInteger(externalPort) && Number.isInteger(internalPort)) {
        mapping[externalPort] = internalPort;
      }
    }
    return Object.keys(mapping).length > 0 ? mapping : null;
  }

  private formatPortMapping(mapping: Record<number, number> | null | undefined): string {
    if (!mapping) return '';
    return Object.entries(mapping)
      .map(([externalPort, internalPort]) => `${externalPort}:${internalPort}`)
      .join(', ');
  }

  private async showSettingsDialog() {
    const { DeesModal, DeesToast } = await import('@design.estate/dees-catalog');
    const settings = this.emailDomainsState.settings;

    DeesModal.createAndShow({
      heading: 'Email Server Settings',
      content: html`
        <dees-form>
          <dees-input-checkbox
            .key=${'enabled'}
            .label=${'Enable email server'}
            .value=${settings?.enabled ?? false}
          ></dees-input-checkbox>
          <dees-input-text
            .key=${'hostname'}
            .label=${'SMTP hostname'}
            .description=${'Public hostname used in SMTP banners and DNS records'}
            .value=${settings?.hostname || ''}
          ></dees-input-text>
          <dees-input-text
            .key=${'ports'}
            .label=${'Public ports'}
            .description=${'Comma-separated SMTP ingress ports, e.g. 25, 587, 465'}
            .value=${settings?.ports?.join(', ') || '25, 587, 465'}
          ></dees-input-text>
          <dees-input-text
            .key=${'portMapping'}
            .label=${'Port mapping'}
            .description=${'Optional external:internal pairs, e.g. 25:10025, 587:10587'}
            .value=${this.formatPortMapping(settings?.portMapping)}
          ></dees-input-text>
          <dees-input-text
            .key=${'maxMessageSize'}
            .label=${'Max message size'}
            .description=${'Bytes; leave empty for smartmta default'}
            .value=${settings?.maxMessageSize ? String(settings.maxMessageSize) : ''}
          ></dees-input-text>
          <dees-input-text
            .key=${'receivedEmailsPath'}
            .label=${'Received emails path'}
            .description=${'Optional storage path for received email artifacts'}
            .value=${settings?.receivedEmailsPath || ''}
          ></dees-input-text>
        </dees-form>
      `,
      menuOptions: [
        { name: 'Cancel', action: async (m: any) => m.destroy() },
        {
          name: 'Save',
          action: async (m: any) => {
            const form = m.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
            if (!form) return;
            const data = await form.collectFormData();
            const maxMessageSizeRaw = String(data.maxMessageSize || '').trim();
            await appstate.emailDomainsStatePart.dispatchAction(
              appstate.updateEmailServerSettingsAction,
              {
                enabled: Boolean(data.enabled),
                hostname: String(data.hostname || '').trim() || null,
                ports: this.parsePortList(String(data.ports || '')),
                portMapping: this.parsePortMapping(String(data.portMapping || '')),
                maxMessageSize: maxMessageSizeRaw ? Number.parseInt(maxMessageSizeRaw, 10) : null,
                receivedEmailsPath: String(data.receivedEmailsPath || '').trim() || null,
              },
            );
            DeesToast.show({ message: 'Email settings saved', type: 'success', duration: 2500 });
            m.destroy();
          },
        },
      ],
    });
  }

  private async showCreateDialog() {
    const { DeesModal } = await import('@design.estate/dees-catalog');
    const domainOptions = this.domainsState.domains.map((d) => ({
      option: `${d.name} (${d.source})`,
      key: d.id,
    }));

    DeesModal.createAndShow({
      heading: 'Add Email Domain',
      content: html`
        <dees-form>
          <dees-input-dropdown
            .key=${'linkedDomainId'}
            .label=${'Domain'}
            .description=${'Select an existing DNS domain'}
            .options=${domainOptions}
            .required=${true}
          ></dees-input-dropdown>
          <dees-input-text
            .key=${'subdomain'}
            .label=${'Subdomain'}
            .description=${'Leave empty for bare domain, e.g. "mail" for mail.example.com'}
          ></dees-input-text>
          <dees-input-text
            .key=${'dkimSelector'}
            .label=${'DKIM Selector'}
            .description=${'Identifier used in DNS record name'}
            .value=${'default'}
          ></dees-input-text>
          <dees-input-dropdown
            .key=${'dkimKeySize'}
            .label=${'DKIM Key Size'}
            .options=${[
              { option: '2048 (recommended)', key: '2048' },
              { option: '1024', key: '1024' },
              { option: '4096', key: '4096' },
            ]}
            .selectedOption=${{ option: '2048 (recommended)', key: '2048' }}
          ></dees-input-dropdown>
          <dees-input-checkbox
            .key=${'rotateKeys'}
            .label=${'Auto-rotate DKIM keys'}
            .value=${false}
          ></dees-input-checkbox>
        </dees-form>
      `,
      menuOptions: [
        { name: 'Cancel', action: async (m: any) => m.destroy() },
        {
          name: 'Create',
          action: async (m: any) => {
            const form = m.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
            if (!form) return;
            const data = await form.collectFormData();
            const linkedDomainId =
              typeof data.linkedDomainId === 'object'
                ? data.linkedDomainId.key
                : data.linkedDomainId;
            const keySize =
              typeof data.dkimKeySize === 'object'
                ? parseInt(data.dkimKeySize.key, 10)
                : parseInt(data.dkimKeySize || '2048', 10);

            const subdomain = data.subdomain?.trim() || undefined;
            await appstate.emailDomainsStatePart.dispatchAction(
              appstate.createEmailDomainAction,
              {
                linkedDomainId,
                subdomain,
                dkimSelector: data.dkimSelector || 'default',
                dkimKeySize: keySize,
                rotateKeys: Boolean(data.rotateKeys),
              },
            );
            m.destroy();
          },
        },
      ],
    });
  }

  private async showDnsRecordsDialog(emailDomain: interfaces.data.IEmailDomain) {
    const { DeesModal, DeesToast } = await import('@design.estate/dees-catalog');

    // Fetch required DNS records
    let records: interfaces.data.IEmailDnsRecord[] = [];
    try {
      const response = await appstate.fetchEmailDomainDnsRecords(emailDomain.id);
      records = response.records;
    } catch {
      records = [];
    }

    DeesModal.createAndShow({
      heading: `DNS Records: ${emailDomain.domain}`,
      content: html`
        <dees-table
          .data=${records}
          .displayFunction=${(r: interfaces.data.IEmailDnsRecord) => ({
            Type: r.type,
            Name: r.name,
            Value: r.value,
            Status: html`<span class="statusBadge ${r.status}">${r.status}</span>`,
          })}
          .dataActions=${[
            {
              name: 'Copy Value',
              iconName: 'lucide:copy',
              type: ['inRow'] as any,
              actionFunc: async (actionData: any) => {
                const rec = actionData.item as interfaces.data.IEmailDnsRecord;
                await navigator.clipboard.writeText(rec.value);
                DeesToast.show({ message: 'Copied to clipboard', type: 'success', duration: 1500 });
              },
            },
          ]}
          dataName="DNS record"
        ></dees-table>
      `,
      menuOptions: [
        {
          name: 'Auto-Provision All',
          action: async (m: any) => {
            await appstate.emailDomainsStatePart.dispatchAction(
              appstate.provisionEmailDomainDnsAction,
              emailDomain.id,
            );
            DeesToast.show({ message: 'DNS records provisioned', type: 'success', duration: 2500 });
            m.destroy();
          },
        },
        { name: 'Close', action: async (m: any) => m.destroy() },
      ],
    });
  }
}
