import { DeesElement, customElement, html, css, cssManager, state, type TemplateResult } from '../plugins.js';
import { deesCatalog } from '../plugins.js';
import { appState, type IAppState, type IProviderStatus } from '../state/appstate.js';
import { viewHostCss } from './shared/index.js';
import type { IStatsTile } from '@design.estate/dees-catalog';

// ---------------------------------------------------------------------------
// Default provider templates
// ---------------------------------------------------------------------------
const PROVIDER_TEMPLATES = {
  sipgate: {
    domain: 'sipgate.de',
    outboundProxy: { address: 'sipgate.de', port: 5060 },
    registerIntervalSec: 300,
    codecs: [9, 0, 8, 101],
    quirks: { earlyMediaSilence: false },
  },
  o2: {
    domain: 'sip.alice-voip.de',
    outboundProxy: { address: 'sip.alice-voip.de', port: 5060 },
    registerIntervalSec: 300,
    codecs: [9, 0, 8, 101],
    quirks: { earlyMediaSilence: false },
  },
};

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function slugify(name: string): string {
  return name
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-|-$/g, '') || `provider-${Date.now()}`;
}

// ---------------------------------------------------------------------------
// View element
// ---------------------------------------------------------------------------
@customElement('sipproxy-view-providers')
export class SipproxyViewProviders extends DeesElement {
  @state() accessor appData: IAppState = appState.getState();

  public static styles = [
    cssManager.defaultStyles,
    viewHostCss,
    css`
      :host {
        display: block;
        padding: 16px;
      }
      .view-section {
        margin-bottom: 24px;
      }
    `,
  ];

  // ---- lifecycle -----------------------------------------------------------

  connectedCallback() {
    super.connectedCallback();
    this.rxSubscriptions.push({
      unsubscribe: appState.subscribe((s) => { this.appData = s; }),
    } as any);
  }

  // ---- stats tiles ---------------------------------------------------------

  private getStatsTiles(): IStatsTile[] {
    const providers = this.appData.providers || [];
    const total = providers.length;
    const registered = providers.filter((p) => p.registered).length;
    const unregistered = total - registered;

    return [
      {
        id: 'total',
        title: 'Total Providers',
        value: total,
        type: 'number',
        icon: 'lucide:server',
        description: 'Configured SIP trunks',
      },
      {
        id: 'registered',
        title: 'Registered',
        value: registered,
        type: 'number',
        icon: 'lucide:CheckCircle',
        color: 'hsl(142.1 76.2% 36.3%)',
        description: 'Active registrations',
      },
      {
        id: 'unregistered',
        title: 'Unregistered',
        value: unregistered,
        type: 'number',
        icon: 'lucide:AlertCircle',
        color: unregistered > 0 ? 'hsl(0 84.2% 60.2%)' : undefined,
        description: unregistered > 0 ? 'Needs attention' : 'All healthy',
      },
    ];
  }

  // ---- table columns -------------------------------------------------------

  private getColumns() {
    return [
      {
        key: 'displayName',
        header: 'Name',
        sortable: true,
      },
      {
        key: 'domain',
        header: 'Domain',
        value: (row: IProviderStatus) => (row as any).domain || '--',
        renderer: (val: string) =>
          html`<span style="font-family:'JetBrains Mono',monospace;font-size:.75rem">${val}</span>`,
      },
      {
        key: 'registered',
        header: 'Status',
        value: (row: IProviderStatus) => (row.registered ? 'Registered' : 'Not Registered'),
        renderer: (val: string, row: IProviderStatus) => {
          const on = row.registered;
          return html`
            <span style="display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px;${on ? 'background:#4ade80;box-shadow:0 0 6px #4ade80' : 'background:#f87171;box-shadow:0 0 6px #f87171'}"></span>
            <span style="color:${on ? '#4ade80' : '#f87171'}">${val}</span>
          `;
        },
      },
      {
        key: 'publicIp',
        header: 'Public IP',
        renderer: (val: any) =>
          html`<span style="font-family:'JetBrains Mono',monospace;font-size:.75rem">${val || '--'}</span>`,
      },
    ];
  }

  // ---- table actions -------------------------------------------------------

  private getDataActions() {
    return [
      {
        name: 'Edit',
        iconName: 'lucide:pencil',
        type: ['inRow'] as any,
        actionFunc: async (actionData: any) => {
          await this.openEditModal(actionData.item.id);
        },
      },
      {
        name: 'Delete',
        iconName: 'lucide:Trash2',
        type: ['inRow'] as any,
        actionFunc: async (actionData: any) => {
          await this.confirmDelete(actionData.item);
        },
      },
      {
        name: 'Add Provider',
        iconName: 'lucide:plus',
        type: ['header'] as any,
        actionFunc: async () => {
          await this.openAddStepper();
        },
      },
    ];
  }

  // ---- add provider stepper ------------------------------------------------

  private async openAddStepper() {
    const { DeesStepper } = await import('@design.estate/dees-catalog');
    type TDeesStepper = InstanceType<typeof DeesStepper>;
    // IStep / menuOptions types: we keep content typing loose (`any[]`) to
    // avoid having to import tsclass IMenuItem just for one parameter annotation.

    type TProviderType = 'Custom' | 'Sipgate' | 'O2/Alice';
    interface IAccumulator {
      providerType: TProviderType;
      displayName: string;
      domain: string;
      outboundProxyAddress: string;
      outboundProxyPort: string;
      username: string;
      password: string;
      // Advanced — exposed in step 4
      registerIntervalSec: string;
      codecs: string;
      earlyMediaSilence: boolean;
    }

    const accumulator: IAccumulator = {
      providerType: 'Custom',
      displayName: '',
      domain: '',
      outboundProxyAddress: '',
      outboundProxyPort: '5060',
      username: '',
      password: '',
      registerIntervalSec: '300',
      codecs: '9, 0, 8, 101',
      earlyMediaSilence: false,
    };

    // Snapshot the currently-selected step's form (if any) into accumulator.
    const snapshotActiveForm = async (stepper: TDeesStepper) => {
      const form = stepper.activeForm;
      if (!form) return;
      const data: Record<string, any> = await form.collectFormData();
      Object.assign(accumulator, data);
    };

    // Overwrite template-owned fields. Keep user-owned fields (username,
    // password) untouched. displayName is replaced only when empty or still
    // holds a branded auto-fill.
    const applyTemplate = (type: TProviderType) => {
      const tpl =
        type === 'Sipgate' ? PROVIDER_TEMPLATES.sipgate
        : type === 'O2/Alice' ? PROVIDER_TEMPLATES.o2
        : null;
      if (!tpl) return;
      accumulator.domain = tpl.domain;
      accumulator.outboundProxyAddress = tpl.outboundProxy.address;
      accumulator.outboundProxyPort = String(tpl.outboundProxy.port);
      accumulator.registerIntervalSec = String(tpl.registerIntervalSec);
      accumulator.codecs = tpl.codecs.join(', ');
      accumulator.earlyMediaSilence = tpl.quirks.earlyMediaSilence;
      if (
        !accumulator.displayName ||
        accumulator.displayName === 'Sipgate' ||
        accumulator.displayName === 'O2/Alice'
      ) {
        accumulator.displayName = type;
      }
    };

    // --- Step builders (called after step 1 so accumulator is populated) ---

    const buildConnectionStep = (): any => ({
      title: 'Connection',
      content: html`
        <dees-form>
          <dees-input-text
            .key=${'displayName'}
            .label=${'Display Name'}
            .value=${accumulator.displayName}
            .required=${true}
          ></dees-input-text>
          <dees-input-text
            .key=${'domain'}
            .label=${'Domain'}
            .value=${accumulator.domain}
            .required=${true}
          ></dees-input-text>
          <dees-input-text
            .key=${'outboundProxyAddress'}
            .label=${'Outbound Proxy Address'}
            .value=${accumulator.outboundProxyAddress}
          ></dees-input-text>
          <dees-input-text
            .key=${'outboundProxyPort'}
            .label=${'Outbound Proxy Port'}
            .value=${accumulator.outboundProxyPort}
          ></dees-input-text>
        </dees-form>
      `,
      menuOptions: [
        {
          name: 'Continue',
          iconName: 'lucide:arrow-right',
          action: async (stepper: TDeesStepper) => {
            await snapshotActiveForm(stepper);
            stepper.goNext();
          },
        },
      ],
    });

    const buildCredentialsStep = (): any => ({
      title: 'Credentials',
      content: html`
        <dees-form>
          <dees-input-text
            .key=${'username'}
            .label=${'Username / Auth ID'}
            .value=${accumulator.username}
            .required=${true}
          ></dees-input-text>
          <dees-input-text
            .key=${'password'}
            .label=${'Password'}
            .isPasswordBool=${true}
            .value=${accumulator.password}
            .required=${true}
          ></dees-input-text>
        </dees-form>
      `,
      menuOptions: [
        {
          name: 'Continue',
          iconName: 'lucide:arrow-right',
          action: async (stepper: TDeesStepper) => {
            await snapshotActiveForm(stepper);
            stepper.goNext();
          },
        },
      ],
    });

    const buildAdvancedStep = (): any => ({
      title: 'Advanced',
      content: html`
        <dees-form>
          <dees-input-text
            .key=${'registerIntervalSec'}
            .label=${'Register Interval (sec)'}
            .value=${accumulator.registerIntervalSec}
          ></dees-input-text>
          <dees-input-text
            .key=${'codecs'}
            .label=${'Codecs (comma-separated payload types)'}
            .value=${accumulator.codecs}
          ></dees-input-text>
          <dees-input-checkbox
            .key=${'earlyMediaSilence'}
            .label=${'Early Media Silence (quirk)'}
            .value=${accumulator.earlyMediaSilence}
          ></dees-input-checkbox>
        </dees-form>
      `,
      menuOptions: [
        {
          name: 'Continue',
          iconName: 'lucide:arrow-right',
          action: async (stepper: TDeesStepper) => {
            await snapshotActiveForm(stepper);
            // Rebuild the review step so its rendering reflects the latest
            // accumulator values (the review step captures values at build time).
            stepper.steps = [...stepper.steps.slice(0, 4), buildReviewStep()];
            await (stepper as any).updateComplete;
            stepper.goNext();
          },
        },
      ],
    });

    const buildReviewStep = (): any => {
      const resolvedId = slugify(accumulator.displayName);
      return {
        title: 'Review & Create',
        content: html`
          <dees-panel>
            <div
              style="display:grid;grid-template-columns:auto 1fr;gap:6px 16px;font-size:.85rem;padding:8px 4px;"
            >
              <div style="color:#94a3b8;">Type</div>
              <div>${accumulator.providerType}</div>
              <div style="color:#94a3b8;">Display Name</div>
              <div>${accumulator.displayName}</div>
              <div style="color:#94a3b8;">ID</div>
              <div style="font-family:'JetBrains Mono',monospace;">${resolvedId}</div>
              <div style="color:#94a3b8;">Domain</div>
              <div>${accumulator.domain}</div>
              <div style="color:#94a3b8;">Outbound Proxy</div>
              <div>
                ${accumulator.outboundProxyAddress || accumulator.domain}:${accumulator.outboundProxyPort}
              </div>
              <div style="color:#94a3b8;">Username</div>
              <div>${accumulator.username}</div>
              <div style="color:#94a3b8;">Password</div>
              <div>${'*'.repeat(Math.min(accumulator.password.length, 12))}</div>
              <div style="color:#94a3b8;">Register Interval</div>
              <div>${accumulator.registerIntervalSec}s</div>
              <div style="color:#94a3b8;">Codecs</div>
              <div>${accumulator.codecs}</div>
              <div style="color:#94a3b8;">Early-Media Silence</div>
              <div>${accumulator.earlyMediaSilence ? 'yes' : 'no'}</div>
            </div>
          </dees-panel>
        `,
        menuOptions: [
          {
            name: 'Create Provider',
            iconName: 'lucide:check',
            action: async (stepper: TDeesStepper) => {
              // Collision-resolve id against current state.
              const existing = (this.appData.providers || []).map((p) => p.id);
              let uniqueId = resolvedId;
              let suffix = 2;
              while (existing.includes(uniqueId)) {
                uniqueId = `${resolvedId}-${suffix++}`;
              }

              const parsedCodecs = accumulator.codecs
                .split(',')
                .map((s: string) => parseInt(s.trim(), 10))
                .filter((n: number) => !isNaN(n));

              const newProvider: any = {
                id: uniqueId,
                displayName: accumulator.displayName.trim(),
                domain: accumulator.domain.trim(),
                outboundProxy: {
                  address:
                    accumulator.outboundProxyAddress.trim() || accumulator.domain.trim(),
                  port: parseInt(accumulator.outboundProxyPort, 10) || 5060,
                },
                username: accumulator.username.trim(),
                password: accumulator.password,
                registerIntervalSec: parseInt(accumulator.registerIntervalSec, 10) || 300,
                codecs: parsedCodecs.length ? parsedCodecs : [9, 0, 8, 101],
                quirks: {
                  earlyMediaSilence: accumulator.earlyMediaSilence,
                },
              };

              try {
                const result = await appState.apiSaveConfig({
                  addProvider: newProvider,
                });
                if (result.ok) {
                  await stepper.destroy();
                  deesCatalog.DeesToast.success(
                    `Provider "${newProvider.displayName}" created`,
                  );
                } else {
                  deesCatalog.DeesToast.error('Failed to save provider');
                }
              } catch (err: any) {
                console.error('Failed to create provider:', err);
                deesCatalog.DeesToast.error('Failed to create provider');
              }
            },
          },
        ],
      };
    };

    // --- Step 1: Provider Type ------------------------------------------------
    //
    // Note: `DeesStepper.createAndShow()` dismisses on backdrop click; a user
    // mid-form could lose work. Acceptable for v1 — revisit if users complain.

    const typeOptions: { option: string; key: TProviderType }[] = [
      { option: 'Custom', key: 'Custom' },
      { option: 'Sipgate', key: 'Sipgate' },
      { option: 'O2 / Alice', key: 'O2/Alice' },
    ];
    const currentTypeOption =
      typeOptions.find((o) => o.key === accumulator.providerType) || null;

    const typeStep: any = {
      title: 'Choose provider type',
      content: html`
        <dees-form>
          <dees-input-dropdown
            .key=${'providerType'}
            .label=${'Provider Type'}
            .options=${typeOptions}
            .selectedOption=${currentTypeOption}
            .enableSearch=${false}
            .required=${true}
          ></dees-input-dropdown>
        </dees-form>
      `,
      menuOptions: [
        {
          name: 'Continue',
          iconName: 'lucide:arrow-right',
          action: async (stepper: TDeesStepper) => {
            // `dees-input-dropdown.value` is an object `{option, key, payload?}`,
            // not a plain string — extract the `key` directly instead of using
            // the generic `snapshotActiveForm` helper (which would clobber
            // `accumulator.providerType`'s string type via Object.assign).
            const form = stepper.activeForm;
            if (form) {
              const data: Record<string, any> = await form.collectFormData();
              const selected = data.providerType;
              if (selected && typeof selected === 'object' && selected.key) {
                accumulator.providerType = selected.key as TProviderType;
              }
            }
            if (!accumulator.providerType) {
              accumulator.providerType = 'Custom';
            }
            applyTemplate(accumulator.providerType);
            // (Re)build steps 2-5 with current accumulator values.
            stepper.steps = [
              typeStep,
              buildConnectionStep(),
              buildCredentialsStep(),
              buildAdvancedStep(),
              buildReviewStep(),
            ];
            await (stepper as any).updateComplete;
            stepper.goNext();
          },
        },
      ],
    };

    await DeesStepper.createAndShow({ steps: [typeStep] });
  }

  // ---- edit provider modal -------------------------------------------------

  private async openEditModal(providerId: string) {
    const { DeesModal } = await import('@design.estate/dees-catalog');

    let cfg: any;
    try {
      cfg = await appState.apiGetConfig();
    } catch {
      deesCatalog.DeesToast.error('Failed to load configuration');
      return;
    }

    const provider = cfg.providers?.find((p: any) => p.id === providerId);
    if (!provider) {
      deesCatalog.DeesToast.error('Provider not found in configuration');
      return;
    }

    const allDevices: { id: string; displayName: string }[] = (cfg.devices || []).map((d: any) => ({
      id: d.id,
      displayName: d.displayName,
    }));

    const formData = {
      displayName: provider.displayName || '',
      domain: provider.domain || '',
      outboundProxyAddress: provider.outboundProxy?.address || '',
      outboundProxyPort: String(provider.outboundProxy?.port ?? 5060),
      username: provider.username || '',
      password: provider.password || '',
      registerIntervalSec: String(provider.registerIntervalSec ?? 300),
      codecs: (provider.codecs || []).join(', '),
      earlyMediaSilence: provider.quirks?.earlyMediaSilence ?? false,
      inboundDevices: (() => {
        const route = (cfg.routing?.routes || []).find((r: any) => r.match?.direction === 'inbound' && r.match?.sourceProvider === providerId);
        return route?.action?.targets ? [...route.action.targets] : [];
      })() as string[],
      ringBrowsers: (() => {
        const route = (cfg.routing?.routes || []).find((r: any) => r.match?.direction === 'inbound' && r.match?.sourceProvider === providerId);
        return route?.action?.ringBrowsers ?? false;
      })(),
    };

    await DeesModal.createAndShow({
      heading: `Edit Provider: ${formData.displayName}`,
      width: 'small',
      showCloseButton: true,
      content: html`
        <div style="display:flex;flex-direction:column;gap:12px;padding:4px 0;">
          <dees-input-text
            .key=${'displayName'}
            .label=${'Display Name'}
            .value=${formData.displayName}
            @input=${(e: Event) => { formData.displayName = (e.target as any).value; }}
          ></dees-input-text>
          <dees-input-text
            .key=${'domain'}
            .label=${'Domain'}
            .value=${formData.domain}
            @input=${(e: Event) => { formData.domain = (e.target as any).value; }}
          ></dees-input-text>
          <dees-input-text
            .key=${'outboundProxyAddress'}
            .label=${'Outbound Proxy Address'}
            .value=${formData.outboundProxyAddress}
            @input=${(e: Event) => { formData.outboundProxyAddress = (e.target as any).value; }}
          ></dees-input-text>
          <dees-input-text
            .key=${'outboundProxyPort'}
            .label=${'Outbound Proxy Port'}
            .value=${formData.outboundProxyPort}
            @input=${(e: Event) => { formData.outboundProxyPort = (e.target as any).value; }}
          ></dees-input-text>
          <dees-input-text
            .key=${'username'}
            .label=${'Username / Auth ID'}
            .value=${formData.username}
            @input=${(e: Event) => { formData.username = (e.target as any).value; }}
          ></dees-input-text>
          <dees-input-text
            .key=${'password'}
            .label=${'Password'}
            .isPasswordBool=${true}
            .value=${formData.password}
            .description=${'Leave unchanged to keep existing password'}
            @input=${(e: Event) => { formData.password = (e.target as any).value; }}
          ></dees-input-text>
          <dees-input-text
            .key=${'registerIntervalSec'}
            .label=${'Register Interval (sec)'}
            .value=${formData.registerIntervalSec}
            @input=${(e: Event) => { formData.registerIntervalSec = (e.target as any).value; }}
          ></dees-input-text>
          <dees-input-text
            .key=${'codecs'}
            .label=${'Codecs (comma-separated payload types)'}
            .value=${formData.codecs}
            @input=${(e: Event) => { formData.codecs = (e.target as any).value; }}
          ></dees-input-text>
          <dees-input-checkbox
            .key=${'earlyMediaSilence'}
            .label=${'Early Media Silence (quirk)'}
            .value=${formData.earlyMediaSilence}
            @newValue=${(e: CustomEvent) => { formData.earlyMediaSilence = e.detail; }}
          ></dees-input-checkbox>

          <div style="margin-top:8px;padding-top:12px;border-top:1px solid #334155;">
            <div style="font-size:.75rem;color:#94a3b8;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;font-weight:600;">
              Inbound Routing
            </div>
            <div style="font-size:.8rem;color:#64748b;margin-bottom:12px;">
              Select which devices should ring when this provider receives an incoming call.
            </div>
            ${allDevices.map((d) => html`
              <dees-input-checkbox
                .key=${`inbound-${d.id}`}
                .label=${d.displayName}
                .value=${formData.inboundDevices.includes(d.id)}
                @newValue=${(e: CustomEvent) => {
                  if (e.detail) {
                    if (!formData.inboundDevices.includes(d.id)) {
                      formData.inboundDevices = [...formData.inboundDevices, d.id];
                    }
                  } else {
                    formData.inboundDevices = formData.inboundDevices.filter((id) => id !== d.id);
                  }
                }}
              ></dees-input-checkbox>
            `)}
            <dees-input-checkbox
              .key=${'ringBrowsers'}
              .label=${'Also ring all connected browsers'}
              .value=${formData.ringBrowsers}
              @newValue=${(e: CustomEvent) => { formData.ringBrowsers = e.detail; }}
            ></dees-input-checkbox>
          </div>
        </div>
      `,
      menuOptions: [
        {
          name: 'Cancel',
          iconName: 'lucide:x',
          action: async (modalRef: any) => {
            modalRef.destroy();
          },
        },
        {
          name: 'Save',
          iconName: 'lucide:check',
          action: async (modalRef: any) => {
            try {
              const codecs = formData.codecs
                .split(',')
                .map((s: string) => parseInt(s.trim(), 10))
                .filter((n: number) => !isNaN(n));

              // Build updated routes: update/create the inbound route for this provider.
              const currentRoutes = [...(cfg.routing?.routes || [])];
              const existingIdx = currentRoutes.findIndex((r: any) =>
                r.match?.direction === 'inbound' && r.match?.sourceProvider === providerId
              );
              const inboundRoute = {
                id: `inbound-${providerId}`,
                name: `Inbound from ${formData.displayName.trim() || providerId}`,
                priority: 0,
                enabled: true,
                match: { direction: 'inbound' as const, sourceProvider: providerId },
                action: {
                  targets: formData.inboundDevices.length ? formData.inboundDevices : undefined,
                  ringBrowsers: formData.ringBrowsers,
                },
              };
              if (existingIdx >= 0) {
                currentRoutes[existingIdx] = { ...currentRoutes[existingIdx], ...inboundRoute };
              } else {
                currentRoutes.push(inboundRoute);
              }

              const updates: any = {
                providers: [{
                  id: providerId,
                  displayName: formData.displayName.trim(),
                  domain: formData.domain.trim(),
                  outboundProxy: {
                    address: formData.outboundProxyAddress.trim() || formData.domain.trim(),
                    port: parseInt(formData.outboundProxyPort, 10) || 5060,
                  },
                  username: formData.username.trim(),
                  registerIntervalSec: parseInt(formData.registerIntervalSec, 10) || 300,
                  codecs,
                  quirks: {
                    earlyMediaSilence: formData.earlyMediaSilence,
                  },
                }] as any[],
                routing: { routes: currentRoutes },
              };

              // Only send password if it was changed (not the masked placeholder).
              if (formData.password && !formData.password.match(/^\*+$/)) {
                updates.providers[0].password = formData.password;
              }

              const result = await appState.apiSaveConfig(updates);
              if (result.ok) {
                modalRef.destroy();
                deesCatalog.DeesToast.success('Provider updated');
              } else {
                deesCatalog.DeesToast.error('Failed to save changes');
              }
            } catch (err: any) {
              console.error('Save failed:', err);
              deesCatalog.DeesToast.error('Failed to save changes');
            }
          },
        },
      ],
    });
  }

  // ---- delete confirmation -------------------------------------------------

  private async confirmDelete(provider: IProviderStatus) {
    const { DeesModal } = await import('@design.estate/dees-catalog');

    await DeesModal.createAndShow({
      heading: 'Delete Provider',
      width: 'small',
      showCloseButton: true,
      content: html`
        <div style="padding:8px 0;font-size:.9rem;color:#e2e8f0;">
          Are you sure you want to delete
          <strong style="color:#f87171;">${provider.displayName}</strong>?
          This action cannot be undone.
        </div>
      `,
      menuOptions: [
        {
          name: 'Cancel',
          iconName: 'lucide:x',
          action: async (modalRef: any) => {
            modalRef.destroy();
          },
        },
        {
          name: 'Delete',
          iconName: 'lucide:Trash2',
          action: async (modalRef: any) => {
            try {
              const result = await appState.apiSaveConfig({
                removeProvider: provider.id,
              });
              if (result.ok) {
                modalRef.destroy();
                deesCatalog.DeesToast.success(`Provider "${provider.displayName}" deleted`);
              } else {
                deesCatalog.DeesToast.error('Failed to delete provider');
              }
            } catch (err: any) {
              console.error('Delete failed:', err);
              deesCatalog.DeesToast.error('Failed to delete provider');
            }
          },
        },
      ],
    });
  }

  // ---- render --------------------------------------------------------------

  public render(): TemplateResult {
    const providers = this.appData.providers || [];

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

      <div class="view-section">
        <dees-statsgrid
          .tiles=${this.getStatsTiles()}
          .minTileWidth=${220}
          .gap=${16}
        ></dees-statsgrid>
      </div>

      <div class="view-section">
        <dees-table
          heading1="Providers"
          heading2="${providers.length} configured"
          dataName="providers"
          .data=${providers}
          .rowKey=${'id'}
          .searchable=${true}
          .columns=${this.getColumns()}
          .dataActions=${this.getDataActions()}
        ></dees-table>
      </div>
    `;
  }
}
