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 { appRouter } from '../../router.js';

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

@customElement('ops-view-domains')
export class OpsViewDomains 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);
  }

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

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

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

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

  public render(): TemplateResult {
    const domains = this.domainsState.domains;
    const providersById = new Map(this.domainsState.providers.map((p) => [p.id, p]));

    return html`
      <dees-heading level="3">Domains</dees-heading>
      <div class="domainsContainer">
        <dees-table
          .heading1=${'Domains'}
          .heading2=${'Domains under management — served by dcrouter (authoritative) or imported from a provider'}
          .data=${domains}
          .showColumnFilters=${true}
          .displayFunction=${(d: interfaces.data.IDomain) => ({
            Name: d.name,
            Source: this.renderSourceBadge(d, providersById),
            Authoritative: d.authoritative ? 'yes' : 'no',
            Nameservers: d.nameservers?.join(', ') || '-',
            'Last Synced': d.lastSyncedAt
              ? new Date(d.lastSyncedAt).toLocaleString()
              : '-',
          })}
          .dataActions=${[
            {
              name: 'Add DcRouter Domain',
              iconName: 'lucide:plus',
              type: ['header' as const],
              actionFunc: async () => {
                await this.showCreateDcrouterDialog();
              },
            },
            {
              name: 'Import from Provider',
              iconName: 'lucide:download',
              type: ['header' as const],
              actionFunc: async () => {
                await this.showImportDialog();
              },
            },
            {
              name: 'Refresh',
              iconName: 'lucide:rotateCw',
              type: ['header' as const],
              actionFunc: async () => {
                await appstate.domainsStatePart.dispatchAction(
                  appstate.fetchDomainsAndProvidersAction,
                  null,
                );
              },
            },
            {
              name: 'View Records',
              iconName: 'lucide:list',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const domain = actionData.item as interfaces.data.IDomain;
                await appstate.domainsStatePart.dispatchAction(
                  appstate.fetchDnsRecordsForDomainAction,
                  { domainId: domain.id },
                );
                appRouter.navigateToView('domains', 'dns');
              },
            },
            {
              name: 'Sync Now',
              iconName: 'lucide:rotateCw',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const domain = actionData.item as interfaces.data.IDomain;
                if (domain.source !== 'provider') {
                  const { DeesToast } = await import('@design.estate/dees-catalog');
                  DeesToast.show({
                    message: 'Sync only applies to provider-managed domains',
                    type: 'warning',
                    duration: 3000,
                  });
                  return;
                }
                await appstate.domainsStatePart.dispatchAction(appstate.syncDomainAction, {
                  id: domain.id,
                });
              },
            },
            {
              name: 'Migrate',
              iconName: 'lucide:arrow-right-left',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const domain = actionData.item as interfaces.data.IDomain;
                await this.showMigrateDialog(domain);
              },
            },
            {
              name: 'Delete',
              iconName: 'lucide:trash2',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const domain = actionData.item as interfaces.data.IDomain;
                await this.deleteDomain(domain);
              },
            },
          ]}
        ></dees-table>
      </div>
    `;
  }

  private renderSourceBadge(
    d: interfaces.data.IDomain,
    providersById: Map<string, interfaces.data.IDnsProviderPublic>,
  ): TemplateResult {
    if (d.source === 'dcrouter') {
      return html`<span class="sourceBadge dcrouter">DcRouter</span>`;
    }
    const provider = d.providerId ? providersById.get(d.providerId) : undefined;
    return html`<span class="sourceBadge provider">${provider?.name || 'Provider'}</span>`;
  }

  private async showCreateDcrouterDialog() {
    const { DeesModal } = await import('@design.estate/dees-catalog');
    DeesModal.createAndShow({
      heading: 'Add DcRouter Domain',
      content: html`
        <dees-form>
          <dees-input-text .key=${'name'} .label=${'FQDN'} .description=${'e.g. example.com'} .required=${true}></dees-input-text>
          <dees-input-text .key=${'description'} .label=${'Description'}></dees-input-text>
        </dees-form>
        <p style="margin-top: 12px; font-size: 12px; opacity: 0.7;">
          dcrouter will become the authoritative DNS server for this domain. You'll need to
          delegate the domain's nameservers to dcrouter to make this effective.
        </p>
      `,
      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();
            await appstate.domainsStatePart.dispatchAction(appstate.createDcrouterDomainAction, {
              name: String(data.name),
              description: data.description ? String(data.description) : undefined,
            });
            modalArg.destroy();
          },
        },
      ],
    });
  }

  private async showImportDialog() {
    const providers = this.domainsState.providers;
    if (providers.length === 0) {
      const { DeesToast } = await import('@design.estate/dees-catalog');
      DeesToast.show({
        message: 'Add a DNS provider first (Domains > Providers)',
        type: 'warning',
        duration: 3500,
      });
      return;
    }

    const { DeesModal, DeesToast } = await import('@design.estate/dees-catalog');
    DeesModal.createAndShow({
      heading: 'Import Domains from Provider',
      content: html`
        <dees-form>
          <dees-input-dropdown
            .key=${'providerId'}
            .label=${'Provider'}
            .options=${providers.map((p) => ({ option: p.name, key: p.id }))}
            .required=${true}
          ></dees-input-dropdown>
          <dees-input-text
            .key=${'domainNames'}
            .label=${'Domain Names'}
            .description=${'Comma-separated FQDNs, e.g. example.com, foo.com'}
            .required=${true}
          ></dees-input-text>
        </dees-form>
        <p style="margin-top: 12px; font-size: 12px; opacity: 0.7;">
          Tip: use "List Provider Domains" to see what's available before typing.
        </p>
      `,
      menuOptions: [
        { name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
        {
          name: 'List Provider Domains',
          action: async (_modalArg: any) => {
            const form = _modalArg.shadowRoot
              ?.querySelector('.content')
              ?.querySelector('dees-form');
            if (!form) return;
            const data = await form.collectFormData();
            const providerKey = data.providerId?.key ?? data.providerId;
            if (!providerKey) {
              DeesToast.show({ message: 'Pick a provider first', type: 'warning', duration: 2500 });
              return;
            }
            const result = await appstate.fetchProviderDomains(String(providerKey));
            if (!result.success) {
              DeesToast.show({
                message: result.message || 'Failed to fetch domains',
                type: 'error',
                duration: 4000,
              });
              return;
            }
            const list = (result.domains ?? []).map((d) => d.name).join(', ');
            DeesToast.show({
              message: `Provider has: ${list || '(none)'}`,
              type: 'info',
              duration: 8000,
            });
          },
        },
        {
          name: 'Import',
          action: async (modalArg: any) => {
            const form = modalArg.shadowRoot
              ?.querySelector('.content')
              ?.querySelector('dees-form');
            if (!form) return;
            const data = await form.collectFormData();
            const providerKey = data.providerId?.key ?? data.providerId;
            if (!providerKey) {
              DeesToast.show({ message: 'Pick a provider', type: 'warning', duration: 2500 });
              return;
            }
            const names = String(data.domainNames || '')
              .split(',')
              .map((s) => s.trim())
              .filter(Boolean);
            if (names.length === 0) {
              DeesToast.show({ message: 'Enter at least one FQDN', type: 'warning', duration: 2500 });
              return;
            }
            await appstate.domainsStatePart.dispatchAction(
              appstate.importDomainsFromProviderAction,
              { providerId: String(providerKey), domainNames: names },
            );
            modalArg.destroy();
          },
        },
      ],
    });
  }

  private async showMigrateDialog(domain: interfaces.data.IDomain) {
    const { DeesModal, DeesToast } = await import('@design.estate/dees-catalog');
    const providers = this.domainsState.providers;

    // Build target options based on current source
    const targetOptions: { option: string; key: string }[] = [];
    for (const p of providers) {
      // Skip current source
      if (p.builtIn && domain.source === 'dcrouter') continue;
      if (!p.builtIn && domain.source === 'provider' && domain.providerId === p.id) continue;

      const label = p.builtIn ? 'DcRouter (self)' : `${p.name} (${p.type})`;
      const key = p.builtIn ? 'dcrouter' : `provider:${p.id}`;
      targetOptions.push({ option: label, key });
    }

    if (targetOptions.length === 0) {
      DeesToast.show({
        message: 'No migration targets available. Add a DNS provider first.',
        type: 'warning',
        duration: 3000,
      });
      return;
    }

    const currentLabel = domain.source === 'dcrouter'
      ? 'DcRouter (self)'
      : providers.find((p) => p.id === domain.providerId)?.name || 'Provider';

    DeesModal.createAndShow({
      heading: `Migrate: ${domain.name}`,
      content: html`
        <dees-form>
          <dees-input-text
            .key=${'currentSource'}
            .label=${'Current source'}
            .value=${currentLabel}
            .disabled=${true}
          ></dees-input-text>
          <dees-input-dropdown
            .key=${'target'}
            .label=${'Migrate to'}
            .description=${'Select the target DNS management'}
            .options=${targetOptions}
            .required=${true}
          ></dees-input-dropdown>
          <dees-input-checkbox
            .key=${'deleteExisting'}
            .label=${'Delete existing records at provider first'}
            .description=${'Removes all records at the provider before pushing migrated records'}
            .value=${true}
          ></dees-input-checkbox>
        </dees-form>
      `,
      menuOptions: [
        { name: 'Cancel', action: async (m: any) => m.destroy() },
        {
          name: 'Migrate',
          action: async (m: any) => {
            const form = m.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
            if (!form) return;
            const data = await form.collectFormData();
            const targetKey = typeof data.target === 'object' ? data.target.key : data.target;
            if (!targetKey) return;

            let targetSource: interfaces.data.TDomainSource;
            let targetProviderId: string | undefined;
            if (targetKey === 'dcrouter') {
              targetSource = 'dcrouter';
            } else {
              targetSource = 'provider';
              targetProviderId = targetKey.replace('provider:', '');
            }

            await appstate.domainsStatePart.dispatchAction(appstate.migrateDomainAction, {
              id: domain.id,
              targetSource,
              targetProviderId,
              deleteExistingProviderRecords: targetSource === 'provider' ? Boolean(data.deleteExisting) : false,
            });
            DeesToast.show({ message: `Domain ${domain.name} migrated successfully`, type: 'success', duration: 3000 });
            m.destroy();
          },
        },
      ],
    });
  }

  private async deleteDomain(domain: interfaces.data.IDomain) {
    const { DeesModal } = await import('@design.estate/dees-catalog');
    DeesModal.createAndShow({
      heading: `Delete domain ${domain.name}?`,
      content: html`
        <p>
          ${domain.source === 'provider'
            ? 'This removes the domain and its cached records from dcrouter only. The zone at the provider is NOT touched.'
            : 'This removes the domain and all of its DNS records from dcrouter. dcrouter will no longer answer queries for this domain after the next restart.'}
        </p>
      `,
      menuOptions: [
        { name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
        {
          name: 'Delete',
          action: async (modalArg: any) => {
            await appstate.domainsStatePart.dispatchAction(appstate.deleteDomainAction, {
              id: domain.id,
            });
            modalArg.destroy();
          },
        },
      ],
    });
  }
}
