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';

declare global {
  interface HTMLElementTagNameMap {
    'ops-view-dns': OpsViewDns;
  }
}

const RECORD_TYPES: interfaces.data.TDnsRecordType[] = [
  'A',
  'AAAA',
  'CNAME',
  'MX',
  'TXT',
  'NS',
  'CAA',
];

@customElement('ops-view-dns')
export class OpsViewDns extends DeesElement {
  @state()
  accessor domainsState: appstate.IDomainsState = appstate.domainsStatePart.getState()!;

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

  async connectedCallback() {
    await super.connectedCallback();
    await appstate.domainsStatePart.dispatchAction(appstate.fetchDomainsAndProvidersAction, null);
    // If a domain is already selected (e.g. via "View Records" navigation), refresh its records
    const selected = this.domainsState.selectedDomainId;
    if (selected) {
      await appstate.domainsStatePart.dispatchAction(appstate.fetchDnsRecordsForDomainAction, {
        domainId: selected,
      });
    }
  }

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

      .domainPicker {
        display: flex;
        align-items: center;
        gap: 12px;
        padding: 12px 16px;
        background: ${cssManager.bdTheme('#f9fafb', '#111827')};
        border-radius: 8px;
      }

      .sourceBadge {
        display: inline-flex;
        align-items: center;
        padding: 2px 8px;
        border-radius: 4px;
        font-size: 11px;
        font-weight: 500;
      }

      .sourceBadge.local {
        background: ${cssManager.bdTheme('#e0e7ff', '#1e1b4b')};
        color: ${cssManager.bdTheme('#3730a3', '#a5b4fc')};
      }

      .sourceBadge.synced {
        background: ${cssManager.bdTheme('#fef3c7', '#451a03')};
        color: ${cssManager.bdTheme('#92400e', '#fde047')};
      }
    `,
  ];

  public render(): TemplateResult {
    const domains = this.domainsState.domains;
    const selectedId = this.domainsState.selectedDomainId;
    const records = this.domainsState.records;

    return html`
      <dees-heading level="3">DNS Records</dees-heading>
      <div class="dnsContainer">
        <div class="domainPicker">
          <dees-input-dropdown
            .label=${'Domain'}
            .options=${domains.map((d) => ({ option: d.name, key: d.id }))}
            .selectedOption=${selectedId
              ? { option: domains.find((d) => d.id === selectedId)?.name || '', key: selectedId }
              : undefined}
            @selectedOption=${async (e: CustomEvent) => {
              const id = (e.detail as any)?.key;
              if (!id) return;
              await appstate.domainsStatePart.dispatchAction(
                appstate.fetchDnsRecordsForDomainAction,
                { domainId: id },
              );
            }}
          ></dees-input-dropdown>
        </div>

        ${selectedId
          ? html`
              <dees-table
                .heading1=${'DNS Records'}
                .heading2=${this.domainHint(selectedId)}
                .data=${records}
                .showColumnFilters=${true}
                .displayFunction=${(r: interfaces.data.IDnsRecord) => ({
                  Name: r.name,
                  Type: r.type,
                  Value: r.value,
                  TTL: r.ttl,
                  Source: html`<span class="sourceBadge ${r.source}">${r.source}</span>`,
                })}
                .dataActions=${[
                  {
                    name: 'Add Record',
                    iconName: 'lucide:plus',
                    type: ['header' as const],
                    actionFunc: async () => {
                      await this.showCreateRecordDialog(selectedId);
                    },
                  },
                  {
                    name: 'Refresh',
                    iconName: 'lucide:rotateCw',
                    type: ['header' as const],
                    actionFunc: async () => {
                      await appstate.domainsStatePart.dispatchAction(
                        appstate.fetchDnsRecordsForDomainAction,
                        { domainId: selectedId },
                      );
                    },
                  },
                  {
                    name: 'Edit',
                    iconName: 'lucide:pencil',
                    type: ['inRow', 'contextmenu'] as any,
                    actionFunc: async (actionData: any) => {
                      const rec = actionData.item as interfaces.data.IDnsRecord;
                      await this.showEditRecordDialog(rec);
                    },
                  },
                  {
                    name: 'Delete',
                    iconName: 'lucide:trash2',
                    type: ['inRow', 'contextmenu'] as any,
                    actionFunc: async (actionData: any) => {
                      const rec = actionData.item as interfaces.data.IDnsRecord;
                      await appstate.domainsStatePart.dispatchAction(
                        appstate.deleteDnsRecordAction,
                        { id: rec.id, domainId: rec.domainId },
                      );
                    },
                  },
                ]}
              ></dees-table>
            `
          : html`<p style="opacity: 0.7;">Pick a domain above to view its records.</p>`}
      </div>
    `;
  }

  private domainHint(domainId: string): string {
    const domain = this.domainsState.domains.find((d) => d.id === domainId);
    if (!domain) return '';
    if (domain.source === 'dcrouter') {
      return 'Records are served by dcrouter (authoritative).';
    }
    return 'Records are stored at the provider — changes here are pushed via the provider API.';
  }

  private async showCreateRecordDialog(domainId: string) {
    const { DeesModal } = await import('@design.estate/dees-catalog');
    DeesModal.createAndShow({
      heading: 'Add DNS Record',
      content: html`
        <dees-form>
          <dees-input-text .key=${'name'} .label=${'Name'} .description=${'Fully qualified domain name'} .required=${true}></dees-input-text>
          <dees-input-dropdown
            .key=${'type'}
            .label=${'Type'}
            .options=${RECORD_TYPES.map((t) => ({ option: t, key: t }))}
            .required=${true}
          ></dees-input-dropdown>
          <dees-input-text
            .key=${'value'}
            .label=${'Value'}
            .description=${'For MX records use priority format, e.g. "10 mail.example.com"'}
            .required=${true}
          ></dees-input-text>
          <dees-input-text .key=${'ttl'} .label=${'TTL'} .description=${'Time to live in seconds'} .value=${'300'}></dees-input-text>
        </dees-form>
      `,
      menuOptions: [
        { name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
        {
          name: 'Create',
          action: async (modalArg: any) => {
            const form = modalArg.shadowRoot
              ?.querySelector('.content')
              ?.querySelector('dees-form');
            if (!form) return;
            const data = await form.collectFormData();
            const type = (data.type?.key ?? data.type) as interfaces.data.TDnsRecordType;
            await appstate.domainsStatePart.dispatchAction(appstate.createDnsRecordAction, {
              domainId,
              name: String(data.name),
              type,
              value: String(data.value),
              ttl: parseInt(String(data.ttl || '300'), 10),
            });
            modalArg.destroy();
          },
        },
      ],
    });
  }

  private async showEditRecordDialog(rec: interfaces.data.IDnsRecord) {
    const { DeesModal } = await import('@design.estate/dees-catalog');
    DeesModal.createAndShow({
      heading: `Edit ${rec.type} ${rec.name}`,
      content: html`
        <dees-form>
          <dees-input-text .key=${'name'} .label=${'Name'} .description=${'Fully qualified domain name'} .value=${rec.name}></dees-input-text>
          <dees-input-text .key=${'value'} .label=${'Value'} .value=${rec.value}></dees-input-text>
          <dees-input-text .key=${'ttl'} .label=${'TTL'} .description=${'Time to live in seconds'} .value=${String(rec.ttl)}></dees-input-text>
        </dees-form>
      `,
      menuOptions: [
        { name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
        {
          name: 'Save',
          action: async (modalArg: any) => {
            const form = modalArg.shadowRoot
              ?.querySelector('.content')
              ?.querySelector('dees-form');
            if (!form) return;
            const data = await form.collectFormData();
            await appstate.domainsStatePart.dispatchAction(appstate.updateDnsRecordAction, {
              id: rec.id,
              domainId: rec.domainId,
              name: String(data.name),
              value: String(data.value),
              ttl: parseInt(String(data.ttl || '300'), 10),
            });
            modalArg.destroy();
          },
        },
      ],
    });
  }
}
