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

const performanceProfileOptions = [
  { key: '', option: 'Default' },
  { key: 'balanced', option: 'Balanced' },
  { key: 'throughput', option: 'Throughput' },
  { key: 'highConcurrency', option: 'High concurrency' },
];

function getDropdownKey(value: any): string {
  return typeof value === 'string' ? value : value?.key || '';
}

declare global {
  interface HTMLElementTagNameMap {
    'ops-view-remoteingress': OpsViewRemoteIngress;
  }
}

@customElement('ops-view-remoteingress')
export class OpsViewRemoteIngress extends DeesElement {
  @state()
  accessor riState: appstate.IRemoteIngressState = appstate.remoteIngressStatePart.getState()!;

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

  async connectedCallback() {
    await super.connectedCallback();
    await appstate.remoteIngressStatePart.dispatchAction(appstate.fetchRemoteIngressAction, null);
  }

  public static styles = [
    cssManager.defaultStyles,
    viewHostCss,
    css`
      .remoteIngressContainer {
        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.connected {
        background: ${cssManager.bdTheme('#dcfce7', '#14532d')};
        color: ${cssManager.bdTheme('#166534', '#4ade80')};
      }

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

      .statusBadge.disabled {
        background: ${cssManager.bdTheme('#f3f4f6', '#374151')};
        color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};
      }

      .secretDialog {
        padding: 16px;
        background: ${cssManager.bdTheme('#fffbeb', '#1c1917')};
        border: 1px solid ${cssManager.bdTheme('#fbbf24', '#92400e')};
        border-radius: 8px;
        margin-bottom: 16px;
      }

      .secretDialog code {
        display: block;
        padding: 8px 12px;
        background: ${cssManager.bdTheme('#1f2937', '#111827')};
        color: #10b981;
        border-radius: 4px;
        font-family: monospace;
        font-size: 13px;
        word-break: break-all;
        margin: 8px 0;
        user-select: all;
      }

      .secretDialog .warning {
        font-size: 12px;
        color: ${cssManager.bdTheme('#92400e', '#fbbf24')};
        margin-top: 8px;
      }

      .portsDisplay {
        display: flex;
        gap: 4px;
        flex-wrap: wrap;
      }

      .portBadge {
        display: inline-flex;
        padding: 2px 8px;
        border-radius: 4px;
        font-size: 12px;
        font-weight: 500;
        background: ${cssManager.bdTheme('#eff6ff', '#172554')};
        color: ${cssManager.bdTheme('#1e40af', '#60a5fa')};
      }

      .portBadge.manual {
        background: ${cssManager.bdTheme('#eff6ff', '#172554')};
        color: ${cssManager.bdTheme('#1e40af', '#60a5fa')};
      }

      .portBadge.derived {
        background: ${cssManager.bdTheme('#ecfdf5', '#022c22')};
        color: ${cssManager.bdTheme('#047857', '#34d399')};
        border: 1px dashed ${cssManager.bdTheme('#6ee7b7', '#065f46')};
      }

      .metricStack {
        display: flex;
        flex-direction: column;
        gap: 2px;
        font-size: 12px;
        line-height: 1.35;
      }

      .metricMuted {
        color: var(--text-muted, #6b7280);
      }

      .settingsNote {
        margin: 12px 0 0;
        font-size: 12px;
        line-height: 1.5;
        color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};
      }
    `,
  ];

  render(): TemplateResult {
    const totalEdges = this.riState.edges.length;
    const connectedEdges = this.riState.statuses.filter(s => s.connected).length;
    const disconnectedEdges = totalEdges - connectedEdges;
    const activeTunnels = this.riState.statuses.reduce((sum, s) => sum + s.activeTunnels, 0);

    const statsTiles: IStatsTile[] = [
      {
        id: 'totalEdges',
        title: 'Total Edges',
        type: 'number',
        value: totalEdges,
        icon: 'lucide:server',
        description: 'Registered edge nodes',
        color: '#3b82f6',
      },
      {
        id: 'connectedEdges',
        title: 'Connected',
        type: 'number',
        value: connectedEdges,
        icon: 'lucide:link',
        description: 'Currently connected edges',
        color: '#10b981',
      },
      {
        id: 'disconnectedEdges',
        title: 'Disconnected',
        type: 'number',
        value: disconnectedEdges,
        icon: 'lucide:unlink',
        description: 'Offline edge nodes',
        color: disconnectedEdges > 0 ? '#ef4444' : '#6b7280',
      },
      {
        id: 'activeTunnels',
        title: 'Active Tunnels',
        type: 'number',
        value: activeTunnels,
        icon: 'lucide:cable',
        description: 'Active client connections',
        color: '#8b5cf6',
      },
    ];

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

      ${this.riState.newEdgeId ? html`
        <div class="secretDialog">
          <strong>Edge created successfully!</strong>
          <div class="warning">Copy the connection token now. Use it with edge.start({ token: '...' }).</div>
          <dees-button
            @click=${async () => {
              const { DeesToast } = await import('@design.estate/dees-catalog');
              try {
                const response = await appstate.fetchConnectionToken(this.riState.newEdgeId!);
                if (response.success && response.token) {
                  if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
                    await navigator.clipboard.writeText(response.token);
                  } else {
                    const textarea = document.createElement('textarea');
                    textarea.value = response.token;
                    textarea.style.position = 'fixed';
                    textarea.style.opacity = '0';
                    document.body.appendChild(textarea);
                    textarea.select();
                    document.execCommand('copy');
                    document.body.removeChild(textarea);
                  }
                  DeesToast.show({ message: 'Connection token copied!', type: 'success', duration: 3000 });
                } else {
                  DeesToast.show({ message: response.message || 'Failed to get token', type: 'error', duration: 4000 });
                }
              } catch (err: unknown) {
                DeesToast.show({ message: `Failed: ${(err as Error).message}`, type: 'error', duration: 4000 });
              }
            }}
          >Copy Connection Token</dees-button>
          <dees-button
            @click=${() => appstate.remoteIngressStatePart.dispatchAction(appstate.clearNewEdgeIdAction, null)}
          >Dismiss</dees-button>
        </div>
      ` : ''}

      <div class="remoteIngressContainer">
        <dees-statsgrid .tiles=${statsTiles}></dees-statsgrid>

        <dees-table
          .heading1=${'Edge Nodes'}
          .heading2=${'Manage remote ingress edge registrations'}
          .data=${this.riState.edges}
          .rowKey=${'id'}
          .highlightUpdates=${'flash'}
          .showColumnFilters=${true}
          .displayFunction=${(edge: interfaces.data.IRemoteIngress) => ({
            name: edge.name,
            status: this.getEdgeStatusHtml(edge),
            transport: this.getTransportHtml(edge.id),
            publicIp: this.getEdgePublicIp(edge.id),
            ports: this.getPortsHtml(edge),
            tunnels: this.getEdgeTunnelCount(edge.id),
            maxConnections: this.getMaxConnectionsHtml(edge),
            window: this.getWindowHtml(edge.id),
            queues: this.getQueuesHtml(edge.id),
            traffic: this.getTrafficHtml(edge.id),
            lastHeartbeat: this.getLastHeartbeat(edge.id),
          })}
          .dataActions=${[
            {
              name: 'Create Edge Node',
              iconName: 'lucide:plus',
              type: ['header'],
              actionFunc: async () => {
                const { DeesModal } = await import('@design.estate/dees-catalog');
                const modal = await DeesModal.createAndShow({
                  heading: 'Create Edge Node',
                  content: html`
                    <dees-form>
                      <dees-input-text .key=${'name'} .label=${'Name'} .required=${true}></dees-input-text>
                      <dees-input-text .key=${'listenPorts'} .label=${'Manual Ports'} .description=${'Comma-separated port numbers, optional'}></dees-input-text>
                      <dees-input-checkbox .key=${'autoDerivePorts'} .label=${'Auto-derive ports from routes'} .value=${true}></dees-input-checkbox>
                      <dees-input-text .key=${'maxStreamsPerEdge'} .label=${'Max Connections'} .description=${'Optional maximum concurrent client connections for this edge. Leave empty to use the hub default.'}></dees-input-text>
                      <dees-input-text .key=${'tags'} .label=${'Tags'} .description=${'Comma-separated, optional'}></dees-input-text>
                    </dees-form>
                  `,
                  menuOptions: [
                    {
                      name: 'Cancel',
                      iconName: 'lucide:x',
                      action: async (modalArg: any) => await modalArg.destroy(),
                    },
                    {
                      name: 'Create',
                      iconName: 'lucide:plus',
                      action: async (modalArg: any) => {
                        const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
                        if (!form) return;
                        const formData = await form.collectFormData();
                        const name = formData.name;
                        if (!name) return;
                        const portsStr = formData.listenPorts?.trim();
                        const listenPorts = portsStr
                          ? portsStr.split(',').map((p: string) => parseInt(p.trim(), 10)).filter((p: number) => !isNaN(p))
                          : undefined;
                        const autoDerivePorts = formData.autoDerivePorts !== false;
                        let performance: interfaces.data.IRemoteIngressPerformanceConfig | undefined;
                        try {
                          performance = this.collectPerformanceOverride(formData);
                        } catch (err: unknown) {
                          const { DeesToast } = await import('@design.estate/dees-catalog');
                          DeesToast.show({ message: (err as Error).message, type: 'error', duration: 4000 });
                          return;
                        }
                        const tags = formData.tags
                          ? formData.tags.split(',').map((t: string) => t.trim()).filter(Boolean)
                          : undefined;
                        await appstate.remoteIngressStatePart.dispatchAction(
                          appstate.createRemoteIngressAction,
                          { name, listenPorts, autoDerivePorts, performance, tags },
                        );
                        await modalArg.destroy();
                      },
                    },
                  ],
                });
              },
            },
            {
              name: 'Hub Settings',
              iconName: 'lucide:slidersHorizontal',
              type: ['header' as const],
              actionFunc: async () => {
                await this.showHubSettingsDialog();
              },
            },
            {
              name: 'Enable',
              iconName: 'lucide:play',
              type: ['inRow', 'contextmenu'] as any,
              actionRelevancyCheckFunc: (actionData: any) => !actionData.item.enabled,
              actionFunc: async (actionData: any) => {
                const edge = actionData.item as interfaces.data.IRemoteIngress;
                await appstate.remoteIngressStatePart.dispatchAction(
                  appstate.toggleRemoteIngressAction,
                  { id: edge.id, enabled: true },
                );
              },
            },
            {
              name: 'Disable',
              iconName: 'lucide:pause',
              type: ['inRow', 'contextmenu'] as any,
              actionRelevancyCheckFunc: (actionData: any) => actionData.item.enabled,
              actionFunc: async (actionData: any) => {
                const edge = actionData.item as interfaces.data.IRemoteIngress;
                await appstate.remoteIngressStatePart.dispatchAction(
                  appstate.toggleRemoteIngressAction,
                  { id: edge.id, enabled: false },
                );
              },
            },
            {
              name: 'Edit',
              iconName: 'lucide:pencil',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const edge = actionData.item as interfaces.data.IRemoteIngress;
                const { DeesModal } = await import('@design.estate/dees-catalog');
                await DeesModal.createAndShow({
                  heading: `Edit Edge: ${edge.name}`,
                  content: html`
                    <dees-form>
                      <dees-input-text .key=${'name'} .label=${'Name'} .value=${edge.name}></dees-input-text>
                      <dees-input-text .key=${'listenPorts'} .label=${'Manual Ports'} .description=${'Comma-separated port numbers'} .value=${(edge.listenPorts || []).join(', ')}></dees-input-text>
                      <dees-input-checkbox .key=${'autoDerivePorts'} .label=${'Auto-derive ports from routes'} .value=${edge.autoDerivePorts !== false}></dees-input-checkbox>
                      <dees-input-text .key=${'maxStreamsPerEdge'} .label=${'Max Connections'} .description=${'Optional maximum concurrent client connections for this edge. Leave empty to use the hub default.'} .value=${edge.performance?.maxStreamsPerEdge?.toString() || ''}></dees-input-text>
                      <dees-input-text .key=${'tags'} .label=${'Tags'} .description=${'Comma-separated'} .value=${(edge.tags || []).join(', ')}></dees-input-text>
                    </dees-form>
                  `,
                  menuOptions: [
                    {
                      name: 'Cancel',
                      iconName: 'lucide:x',
                      action: async (modalArg: any) => await modalArg.destroy(),
                    },
                    {
                      name: 'Save',
                      iconName: 'lucide:check',
                      action: async (modalArg: any) => {
                        const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
                        if (!form) return;
                        const formData = await form.collectFormData();
                        const portsStr = formData.listenPorts?.trim();
                        const listenPorts = portsStr
                          ? portsStr.split(',').map((p: string) => parseInt(p.trim(), 10)).filter((p: number) => !isNaN(p))
                          : [];
                        const autoDerivePorts = formData.autoDerivePorts !== false;
                        let performance: interfaces.data.IRemoteIngressPerformanceConfig | undefined;
                        try {
                          performance = this.collectPerformanceOverride(formData, edge.performance);
                        } catch (err: unknown) {
                          const { DeesToast } = await import('@design.estate/dees-catalog');
                          DeesToast.show({ message: (err as Error).message, type: 'error', duration: 4000 });
                          return;
                        }
                        const tags = formData.tags
                          ? formData.tags.split(',').map((t: string) => t.trim()).filter(Boolean)
                          : [];
                        await appstate.remoteIngressStatePart.dispatchAction(
                          appstate.updateRemoteIngressAction,
                          {
                            id: edge.id,
                            name: formData.name || edge.name,
                            listenPorts,
                            autoDerivePorts,
                            performance,
                            tags,
                          },
                        );
                        await modalArg.destroy();
                      },
                    },
                  ],
                });
              },
            },
            {
              name: 'Regenerate Secret',
              iconName: 'lucide:key',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const edge = actionData.item as interfaces.data.IRemoteIngress;
                await appstate.remoteIngressStatePart.dispatchAction(
                  appstate.regenerateRemoteIngressSecretAction,
                  edge.id,
                );
              },
            },
            {
              name: 'Copy Token',
              iconName: 'lucide:ClipboardCopy',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const edge = actionData.item as interfaces.data.IRemoteIngress;
                const { DeesToast } = await import('@design.estate/dees-catalog');
                try {
                  const response = await appstate.fetchConnectionToken(edge.id);
                  if (response.success && response.token) {
                    // Use clipboard API with fallback for non-HTTPS contexts
                    if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
                      await navigator.clipboard.writeText(response.token);
                    } else {
                      const textarea = document.createElement('textarea');
                      textarea.value = response.token;
                      textarea.style.position = 'fixed';
                      textarea.style.opacity = '0';
                      document.body.appendChild(textarea);
                      textarea.select();
                      document.execCommand('copy');
                      document.body.removeChild(textarea);
                    }
                    DeesToast.show({ message: `Connection token copied for ${edge.name}`, type: 'success', duration: 3000 });
                  } else {
                    DeesToast.show({ message: response.message || 'Failed to get token', type: 'error', duration: 4000 });
                  }
                } catch (err: unknown) {
                  DeesToast.show({ message: `Failed: ${(err as Error).message}`, type: 'error', duration: 4000 });
                }
              },
            },
            {
              name: 'Delete',
              iconName: 'lucide:trash2',
              type: ['inRow', 'contextmenu'] as any,
              actionFunc: async (actionData: any) => {
                const edge = actionData.item as interfaces.data.IRemoteIngress;
                await appstate.remoteIngressStatePart.dispatchAction(
                  appstate.deleteRemoteIngressAction,
                  edge.id,
                );
              },
            },
          ]}
        ></dees-table>
      </div>
    `;
  }

  private getEdgeStatus(edgeId: string): interfaces.data.IRemoteIngressStatus | undefined {
    return this.riState.statuses.find(s => s.edgeId === edgeId);
  }

  private getEdgeStatusHtml(edge: interfaces.data.IRemoteIngress): TemplateResult {
    if (!edge.enabled) {
      return html`<span class="statusBadge disabled">Disabled</span>`;
    }
    const status = this.getEdgeStatus(edge.id);
    if (status?.connected) {
      return html`<span class="statusBadge connected">Connected</span>`;
    }
    return html`<span class="statusBadge disconnected">Disconnected</span>`;
  }

  private getEdgePublicIp(edgeId: string): string {
    const status = this.getEdgeStatus(edgeId);
    return status?.publicIp || '-';
  }

  private getPortsHtml(edge: interfaces.data.IRemoteIngress): TemplateResult {
    const manualPorts = edge.manualPorts || [];
    const derivedPorts = edge.derivedPorts || [];
    if (manualPorts.length === 0 && derivedPorts.length === 0) {
      return html`<span style="color: var(--text-muted, #6b7280); font-size: 12px;">none</span>`;
    }
    return html`<div class="portsDisplay">${manualPorts.map(p => html`<span class="portBadge manual">${p}</span>`)}${derivedPorts.map(p => html`<span class="portBadge derived">${p}</span>`)}${derivedPorts.length > 0 ? html`<span style="font-size: 11px; color: var(--text-muted, #6b7280); align-self: center;">(auto)</span>` : ''}</div>`;
  }

  private getEdgeTunnelCount(edgeId: string): number {
    const status = this.getEdgeStatus(edgeId);
    return status?.activeTunnels || 0;
  }

  private getMaxConnectionsHtml(edge: interfaces.data.IRemoteIngress): TemplateResult | string {
    const status = this.getEdgeStatus(edge.id);
    const override = edge.performance?.maxStreamsPerEdge;
    const effective = status?.performance?.maxStreamsPerEdge;
    if (!override && !effective) return '-';
    return html`
      <div class="metricStack">
        <span>${override || effective}</span>
        <span class="metricMuted">${override ? 'edge override' : 'hub default'}</span>
      </div>
    `;
  }

  private getTransportHtml(edgeId: string): TemplateResult | string {
    const status = this.getEdgeStatus(edgeId);
    if (!status?.connected) return '-';
    const mode = status.transportMode || 'unknown';
    const label = mode === 'quic' ? 'QUIC' : mode === 'tcpTls' ? 'TCP/TLS' : mode;
    return html`<div class="metricStack"><strong>${label}</strong><span class="metricMuted">${status.fallbackUsed ? 'fallback' : status.performance?.profile || 'default'}</span></div>`;
  }

  private getWindowHtml(edgeId: string): TemplateResult | string {
    const status = this.getEdgeStatus(edgeId);
    if (!status?.connected || !status.flowControl) return '-';
    if (!status.flowControl.applies) {
      return html`<div class="metricStack"><span>native QUIC</span><span class="metricMuted">max ${status.performance?.maxStreamsPerEdge || '-'} streams</span></div>`;
    }
    return html`
      <div class="metricStack">
        <span>${this.formatBytes(status.flowControl.currentWindowBytes)} window</span>
        <span class="metricMuted">${this.formatBytes(status.flowControl.estimatedInFlightBytes)} est. in-flight</span>
      </div>
    `;
  }

  private getQueuesHtml(edgeId: string): TemplateResult | string {
    const status = this.getEdgeStatus(edgeId);
    if (!status?.connected || !status.queues) return '-';
    return html`<div class="metricStack"><span>C ${status.queues.ctrlQueueDepth} / D ${status.queues.dataQueueDepth}</span><span class="metricMuted">S ${status.queues.sustainedQueueDepth}</span></div>`;
  }

  private getTrafficHtml(edgeId: string): TemplateResult | string {
    const status = this.getEdgeStatus(edgeId);
    if (!status?.connected || !status.traffic) return '-';
    const drops = (status.traffic.rejectedStreams || 0) + (status.udp?.droppedDatagrams || 0);
    return html`
      <div class="metricStack">
        <span>${this.formatBytes(status.traffic.bytesIn)} in / ${this.formatBytes(status.traffic.bytesOut)} out</span>
        <span class="metricMuted">${drops} rejected/dropped</span>
      </div>
    `;
  }

  private getLastHeartbeat(edgeId: string): string {
    const status = this.getEdgeStatus(edgeId);
    if (!status?.lastHeartbeat) return '-';
    const ago = Date.now() - status.lastHeartbeat;
    if (ago < 60000) return `${Math.floor(ago / 1000)}s ago`;
    if (ago < 3600000) return `${Math.floor(ago / 60000)}m ago`;
    return `${Math.floor(ago / 3600000)}h ago`;
  }

  private formatBytes(bytes: number): string {
    if (!Number.isFinite(bytes) || bytes <= 0) return '0 B';
    const units = ['B', 'KB', 'MB', 'GB', 'TB'];
    let value = bytes;
    let unitIndex = 0;
    while (value >= 1024 && unitIndex < units.length - 1) {
      value = value / 1024;
      unitIndex++;
    }
    return `${value >= 10 || unitIndex === 0 ? value.toFixed(0) : value.toFixed(1)} ${units[unitIndex]}`;
  }

  private collectPerformanceOverride(
    formData: Record<string, any>,
    base?: interfaces.data.IRemoteIngressPerformanceConfig,
  ): interfaces.data.IRemoteIngressPerformanceConfig | undefined {
    const next: interfaces.data.IRemoteIngressPerformanceConfig = { ...(base || {}) };
    const maxStreamsText = `${formData.maxStreamsPerEdge || ''}`.trim();
    if (maxStreamsText) {
      const maxStreamsPerEdge = Number.parseInt(maxStreamsText, 10);
      if (!Number.isInteger(maxStreamsPerEdge) || maxStreamsPerEdge < 1) {
        throw new Error('Max Connections must be a positive integer');
      }
      next.maxStreamsPerEdge = maxStreamsPerEdge;
    } else {
      delete next.maxStreamsPerEdge;
    }

    if (Object.keys(next).length > 0) {
      return next;
    }

    return base ? {} : undefined;
  }

  private async showHubSettingsDialog(): Promise<void> {
    const { DeesModal, DeesToast } = await import('@design.estate/dees-catalog');
    const hubSettings = this.riState.hubSettings;
    const performance = hubSettings?.performance || {};
    const selectedProfile = performanceProfileOptions.find((option) => option.key === (performance.profile || '')) || performanceProfileOptions[0];
    const updatedAt = hubSettings?.updatedAt
      ? new Date(hubSettings.updatedAt).toLocaleString()
      : 'not persisted yet';

    await DeesModal.createAndShow({
      heading: 'RemoteIngress Hub Settings',
      content: html`
        <dees-form>
          <dees-input-checkbox
            .key=${'enabled'}
            .label=${'Enable RemoteIngress Hub'}
            .value=${hubSettings?.enabled ?? false}
          ></dees-input-checkbox>
          <dees-input-text
            .key=${'tunnelPort'}
            .label=${'Tunnel Port'}
            .description=${'TCP/UDP port edges connect to on the hub.'}
            .value=${(hubSettings?.tunnelPort || 8443).toString()}
          ></dees-input-text>
          <dees-input-text
            .key=${'hubDomain'}
            .label=${'Hub Domain / Address'}
            .description=${'Public host or IP embedded in edge connection tokens.'}
            .value=${hubSettings?.hubDomain || ''}
          ></dees-input-text>
          <dees-input-dropdown
            .key=${'profile'}
            .label=${'Performance Profile'}
            .options=${performanceProfileOptions}
            .selectedOption=${selectedProfile}
          ></dees-input-dropdown>
          <dees-input-text
            .key=${'maxStreamsPerEdge'}
            .label=${'Max Connections / Edge'}
            .description=${'Maximum concurrent client streams per edge. Leave empty for RemoteIngress defaults.'}
            .value=${performance.maxStreamsPerEdge?.toString() || ''}
          ></dees-input-text>
          <dees-input-text
            .key=${'clientWriteTimeoutMs'}
            .label=${'Client Write Timeout'}
            .description=${'Milliseconds before idle client writes are timed out. Leave empty for default.'}
            .value=${performance.clientWriteTimeoutMs?.toString() || ''}
          ></dees-input-text>
          <dees-input-text
            .key=${'firstDataConnectTimeoutMs'}
            .label=${'First Data Timeout'}
            .description=${'Milliseconds to wait for initial client data before connecting upstream. Leave empty for default.'}
            .value=${performance.firstDataConnectTimeoutMs?.toString() || ''}
          ></dees-input-text>
          <dees-input-text
            .key=${'serverFirstPorts'}
            .label=${'Server-first Ports'}
            .description=${'Comma-separated ports such as 21, 22, 25, 110, 143, 587. Do not include 443.'}
            .value=${(performance.serverFirstPorts || []).join(', ')}
          ></dees-input-text>
        </dees-form>
        <p class="settingsNote">
          Saving applies DB-backed hub settings. Enabling or disabling the hub restarts SmartProxy so tunneled traffic and route metadata stay consistent.
          Last updated: ${updatedAt} by ${hubSettings?.updatedBy || 'default'}.
        </p>
      `,
      menuOptions: [
        {
          name: 'Cancel',
          iconName: 'lucide:x',
          action: async (modalArg: any) => await modalArg.destroy(),
        },
        {
          name: 'Save',
          iconName: 'lucide:check',
          action: async (modalArg: any) => {
            const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
            if (!form) return;
            const formData = await form.collectFormData();
            let performanceSettings: interfaces.data.IRemoteIngressPerformanceConfig | null;
            let tunnelPort: number;
            try {
              tunnelPort = this.parseRequiredPort(formData.tunnelPort, 'Tunnel Port');
              performanceSettings = this.collectHubPerformanceSettings(formData, performance);
            } catch (err: unknown) {
              DeesToast.show({ message: (err as Error).message, type: 'error', duration: 4000 });
              return;
            }

            const nextState = await appstate.remoteIngressStatePart.dispatchAction(
              appstate.updateRemoteIngressHubSettingsAction,
              {
                enabled: formData.enabled !== false,
                tunnelPort,
                hubDomain: `${formData.hubDomain || ''}`.trim() || null,
                performance: performanceSettings,
              },
            );
            if (nextState.error) {
              DeesToast.show({ message: nextState.error, type: 'error', duration: 4000 });
              return;
            }
            await modalArg.destroy();
            DeesToast.show({ message: 'RemoteIngress hub settings saved', type: 'success', duration: 3000 });
          },
        },
      ],
    });
  }

  private collectHubPerformanceSettings(
    formData: Record<string, any>,
    currentPerformance: interfaces.data.IRemoteIngressPerformanceConfig,
  ): interfaces.data.IRemoteIngressPerformanceConfig | null {
    const next: interfaces.data.IRemoteIngressPerformanceConfig = { ...currentPerformance };
    const profile = getDropdownKey(formData.profile) as interfaces.data.TRemoteIngressPerformanceProfile | '';
    if (profile) {
      next.profile = profile;
    } else {
      delete next.profile;
    }

    this.assignOptionalPositiveIntegerSetting(next, 'maxStreamsPerEdge', formData.maxStreamsPerEdge, 'Max Connections / Edge');
    this.assignOptionalPositiveIntegerSetting(next, 'clientWriteTimeoutMs', formData.clientWriteTimeoutMs, 'Client Write Timeout');
    this.assignOptionalPositiveIntegerSetting(next, 'firstDataConnectTimeoutMs', formData.firstDataConnectTimeoutMs, 'First Data Timeout');

    const serverFirstPortsText = `${formData.serverFirstPorts || ''}`.trim();
    if (serverFirstPortsText) {
      const serverFirstPorts = this.parsePortList(serverFirstPortsText, 'Server-first Ports');
      if (serverFirstPorts.includes(443)) {
        throw new Error('Port 443 is client-first TLS and must not be listed as server-first');
      }
      next.serverFirstPorts = serverFirstPorts;
    } else {
      delete next.serverFirstPorts;
    }

    return Object.keys(next).length > 0 ? next : null;
  }

  private assignOptionalPositiveIntegerSetting(
    target: interfaces.data.IRemoteIngressPerformanceConfig,
    key: 'maxStreamsPerEdge' | 'clientWriteTimeoutMs' | 'firstDataConnectTimeoutMs',
    value: any,
    label: string,
  ): void {
    const text = `${value || ''}`.trim();
    if (!text) {
      delete target[key];
      return;
    }
    const parsed = Number.parseInt(text, 10);
    if (!Number.isInteger(parsed) || parsed < 1) {
      throw new Error(`${label} must be a positive integer`);
    }
    target[key] = parsed;
  }

  private parsePortList(value: any, label: string): number[] {
    const text = `${value || ''}`.trim();
    if (!text) {
      return [];
    }
    const ports = text.split(',').map((part) => Number.parseInt(part.trim(), 10));
    for (const port of ports) {
      if (!Number.isInteger(port) || port < 1 || port > 65535) {
        throw new Error(`${label} must contain valid port numbers`);
      }
    }
    return [...new Set(ports)].sort((a, b) => a - b);
  }

  private parseRequiredPort(value: any, label: string): number {
    const port = Number.parseInt(`${value || ''}`.trim(), 10);
    if (!Number.isInteger(port) || port < 1 || port > 65535) {
      throw new Error(`${label} must be a valid port number`);
    }
    return port;
  }
}
