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

@customElement('ob-view-settings')
export class ObViewSettings extends DeesElement {
  @state()
  accessor settingsState: appstate.ISettingsState = {
    settings: null,
    backupPasswordConfigured: false,
    managedDcRouterStatus: null,
  };

  @state()
  accessor loginState: appstate.ILoginState = {
    identity: null,
    isLoggedIn: false,
  };

  constructor() {
    super();

    const settingsSub = appstate.settingsStatePart
      .select((s) => s)
      .subscribe((newState) => {
        this.settingsState = newState;
      });
    this.rxSubscriptions.push(settingsSub);

    const loginSub = appstate.loginStatePart
      .select((s) => s)
      .subscribe((newState) => {
        this.loginState = newState;
      });
    this.rxSubscriptions.push(loginSub);
  }

  public static styles = [
    cssManager.defaultStyles,
    shared.viewHostCss,
    css`
      dees-tile {
        display: block;
        margin-bottom: 24px;
      }

      .gateway-header {
        height: 36px;
        display: flex;
        align-items: center;
        padding: 0 16px;
        width: 100%;
        box-sizing: border-box;
      }

      .gateway-heading {
        flex: 1;
        display: flex;
        align-items: baseline;
        gap: 8px;
        min-width: 0;
      }

      .gateway-title {
        font-size: 13px;
        font-weight: 500;
        letter-spacing: -0.01em;
        color: var(--dees-color-text-secondary);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      .gateway-subtitle {
        font-size: 12px;
        color: var(--dees-color-text-muted);
        letter-spacing: -0.01em;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      .gateway-content {
        padding: 20px;
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 16px;
      }

      .gateway-mode-row,
      .gateway-status-row {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 12px;
        padding: 16px 20px;
        border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#27272a')};
      }

      .gateway-mode-row {
        justify-content: flex-start;
      }

      .gateway-mode-button {
        border: 1px solid ${cssManager.bdTheme('#d4d4d8', '#3f3f46')};
        border-radius: 999px;
        background: ${cssManager.bdTheme('#ffffff', '#18181b')};
        color: ${cssManager.bdTheme('#3f3f46', '#d4d4d8')};
        padding: 8px 12px;
        font: inherit;
        cursor: pointer;
      }

      .gateway-mode-button.active {
        border-color: ${cssManager.bdTheme('#2563eb', '#60a5fa')};
        background: ${cssManager.bdTheme('#eff6ff', '#172554')};
        color: ${cssManager.bdTheme('#1d4ed8', '#bfdbfe')};
      }

      .gateway-status-label {
        font-size: 12px;
        font-weight: 600;
        text-transform: uppercase;
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
      }

      .gateway-status-value {
        margin-top: 4px;
        font-size: 14px;
        color: ${cssManager.bdTheme('#18181b', '#fafafa')};
      }

      .gateway-status-error,
      .gateway-disabled {
        color: ${cssManager.bdTheme('#b91c1c', '#fca5a5')};
        font-size: 13px;
      }

      .gateway-disabled {
        grid-column: 1 / -1;
      }

      .gateway-actions {
        display: flex;
        gap: 8px;
      }

      .gateway-field.full {
        grid-column: 1 / -1;
      }

      .gateway-readonly {
        padding: 10px 12px;
        border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
        border-radius: 8px;
        background: ${cssManager.bdTheme('#fafafa', '#18181b')};
      }

      .gateway-readonly-label {
        font-size: 12px;
        font-weight: 600;
        color: ${cssManager.bdTheme('#52525b', '#d4d4d8')};
      }

      .gateway-readonly-value {
        margin-top: 4px;
        font-size: 13px;
        color: ${cssManager.bdTheme('#18181b', '#fafafa')};
        word-break: break-all;
      }

      .gateway-readonly-hint {
        margin-top: 4px;
        font-size: 12px;
        color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
      }

      dees-input-text {
        width: 100%;
      }

      .gateway-footer {
        display: flex;
        flex-direction: row;
        justify-content: flex-end;
        align-items: center;
        gap: 0;
        height: 36px;
        width: 100%;
        box-sizing: border-box;
      }

      .tile-button {
        padding: 0 16px;
        height: 100%;
        text-align: center;
        font-size: 12px;
        font-weight: 500;
        cursor: pointer;
        user-select: none;
        transition: all 0.15s ease;
        background: transparent;
        border: none;
        border-left: 1px solid var(--dees-color-border-subtle);
        color: var(--dees-color-text-muted);
        white-space: nowrap;
        display: flex;
        align-items: center;
        gap: 6px;
      }

      .tile-button:first-child {
        border-left: none;
      }

      .tile-button:hover {
        background: var(--dees-color-hover);
        color: var(--dees-color-text-primary);
      }

      .tile-button.primary {
        color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
        font-weight: 600;
      }

      .tile-button.primary:hover {
        background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8% / 0.08)', 'hsl(213.1 93.9% 67.8% / 0.08)')};
        color: ${cssManager.bdTheme('hsl(217.2 91.2% 50%)', 'hsl(213.1 93.9% 75%)')};
      }

      @media (max-width: 700px) {
        .gateway-content {
          grid-template-columns: 1fr;
        }

        .gateway-status-row {
          align-items: flex-start;
          flex-direction: column;
        }
      }
    `,
  ];

  async connectedCallback() {
    super.connectedCallback();
    await appstate.settingsStatePart.dispatchAction(appstate.fetchSettingsAction, null);
  }

  public render(): TemplateResult {
    return html`
      <ob-sectionheading>Settings</ob-sectionheading>
      ${this.renderAdminUiSettings()}
      ${this.renderExternalGatewaySettings()}
      <sz-settings-view
        .settings=${this.settingsState.settings || {
          darkMode: true,
          cloudflareToken: '',
          cloudflareZoneId: '',
          adminUiDomain: '',
          dcrouterMode: 'managed',
          dcrouterManagedImage: 'code.foss.global/serve.zone/dcrouter:latest',
          dcrouterManagedOpsPort: 3300,
          dcrouterManagedHttpPort: 80,
          dcrouterManagedHttpsPort: 443,
          dcrouterManagedDataDir: './.nogit/dcrouter-data',
          dcrouterGatewayClientId: '',
          dcrouterWorkHosterId: '',
          autoRenewCerts: false,
          renewalThreshold: 30,
          acmeEmail: '',
          httpPort: 80,
          httpsPort: 443,
          forceHttps: false,
        }}
        .currentUser=${this.loginState.identity?.username || 'admin'}
        @setting-change=${(e: CustomEvent) => {
          const { key, value } = e.detail;
          appstate.settingsStatePart.dispatchAction(appstate.updateSettingsAction, {
            settings: { [key]: value },
          });
        }}
        @save=${(e: CustomEvent) => {
          appstate.settingsStatePart.dispatchAction(appstate.updateSettingsAction, {
            settings: e.detail,
          });
        }}
        @change-password=${(e: CustomEvent) => {
          console.log('Change password requested:', e.detail);
        }}
        @reset=${() => {
          appstate.settingsStatePart.dispatchAction(appstate.fetchSettingsAction, null);
        }}
      ></sz-settings-view>
    `;
  }

  private renderAdminUiSettings(): TemplateResult {
    const settings = this.settingsState.settings;
    return html`
      <dees-tile>
        <div slot="header" class="gateway-header">
          <div class="gateway-heading">
            <span class="gateway-title">Onebox Admin UI</span>
            <span class="gateway-subtitle">Configure the public hostname for this Onebox dashboard</span>
          </div>
        </div>
        <div class="gateway-content">
          ${this.renderGatewayInput('adminUiDomain', 'Admin UI Domain', settings?.adminUiDomain || '', 'Example: onebox.example.com. Leave empty to disable the public Admin UI route.')}
          ${this.renderGatewayReadonly('Local Target', 'Onebox OpsServer on port 3000', 'The external gateway forwards to SmartProxy, which forwards this hostname to the Onebox Admin UI.')}
        </div>
        <div slot="footer" class="gateway-footer">
          <button class="tile-button primary" type="button" @click=${() => this.saveAdminUiSettings()}>
            Save Admin UI Domain
          </button>
        </div>
      </dees-tile>
    `;
  }

  private renderExternalGatewaySettings(): TemplateResult {
    const settings = this.settingsState.settings;
    const mode = settings?.dcrouterMode || 'managed';
    return html`
      <dees-tile>
        <div slot="header" class="gateway-header">
          <div class="gateway-heading">
            <span class="gateway-title">dcrouter Gateway</span>
            <span class="gateway-subtitle">Run a local managed dcrouter or delegate routing to an external dcrouter</span>
          </div>
        </div>
        <div class="gateway-mode-row">
          ${this.renderModeButton('managed', 'Managed Local', mode)}
          ${this.renderModeButton('external', 'External dcrouter', mode)}
          ${this.renderModeButton('disabled', 'Disabled', mode)}
        </div>
        ${mode === 'managed' ? this.renderManagedGatewayStatus() : null}
        <div class="gateway-content">
          ${mode === 'managed' ? html`
            ${this.renderGatewayInput('dcrouterManagedImage', 'dcrouter Image', settings?.dcrouterManagedImage || 'code.foss.global/serve.zone/dcrouter:latest', 'OCI image used for the managed local gateway.')}
            ${this.renderGatewayInput('dcrouterManagedDataDir', 'Data Directory', settings?.dcrouterManagedDataDir || './.nogit/dcrouter-data', 'Host directory mounted into the dcrouter container.')}
            ${this.renderGatewayInput('dcrouterManagedOpsPort', 'Local Ops Port', String(settings?.dcrouterManagedOpsPort || 3300), 'Bound to 127.0.0.1 for Onebox to call dcrouter APIs.')}
            ${this.renderGatewayInput('dcrouterManagedHttpPort', 'Public HTTP Port', String(settings?.dcrouterManagedHttpPort || 80), 'Host port owned by dcrouter for HTTP ingress.')}
            ${this.renderGatewayInput('dcrouterManagedHttpsPort', 'Public HTTPS Port', String(settings?.dcrouterManagedHttpsPort || 443), 'Host port owned by dcrouter for HTTPS ingress.')}
            ${this.renderGatewayReadonly('Gateway Client ID', settings?.dcrouterGatewayClientId || settings?.dcrouterWorkHosterId || 'Created when managed dcrouter starts', 'Diagnostic only. Onebox manages this local client automatically.')}
          ` : mode === 'external' ? html`
            ${this.renderGatewayInput('dcrouterGatewayUrl', 'Gateway URL', settings?.dcrouterGatewayUrl || '', 'Base URL of the dcrouter OpsServer.')}
            ${this.renderGatewayInput('dcrouterGatewayApiToken', 'API Token', settings?.dcrouterGatewayApiToken || '', 'Requires gateway-client access in dcrouter.', true)}
            ${this.renderGatewayReadonly('Gateway Client ID', settings?.dcrouterGatewayClientId || settings?.dcrouterWorkHosterId || 'Derived from token', 'Configure this in dcrouter Gateway Clients, not in Onebox.')}
            ${this.renderGatewayInput('dcrouterTargetHost', 'Target Host', settings?.dcrouterTargetHost || '', 'Defaults to the configured server IP when empty.')}
            ${this.renderGatewayInput('dcrouterTargetPort', 'Target Port', String(settings?.dcrouterTargetPort || 80), 'Internal HTTP port dcrouter forwards to.')}
          ` : html`
            <div class="gateway-disabled">dcrouter route delegation is disabled. Onebox will keep using its local SmartProxy directly.</div>
          `}
        </div>
        <div slot="footer" class="gateway-footer">
          <button class="tile-button primary" type="button" @click=${() => this.saveExternalGatewaySettings()}>
            Save dcrouter Settings
          </button>
        </div>
      </dees-tile>
    `;
  }

  private renderModeButton(
    mode: 'managed' | 'external' | 'disabled',
    label: string,
    activeMode: string,
  ): TemplateResult {
    return html`
      <button
        class="gateway-mode-button ${activeMode === mode ? 'active' : ''}"
        @click=${() => this.updateGatewayDraft('dcrouterMode', mode)}
      >${label}</button>
    `;
  }

  private renderManagedGatewayStatus(): TemplateResult {
    const status = this.settingsState.managedDcRouterStatus;
    const stateText = status?.running ? (status.healthy ? 'Running' : 'Starting') : 'Stopped';
    return html`
      <div class="gateway-status-row">
        <div>
          <div class="gateway-status-label">Managed dcrouter</div>
          <div class="gateway-status-value">${stateText}${status?.gatewayUrl ? ` at ${status.gatewayUrl}` : ''}</div>
          ${status?.message ? html`<div class="gateway-status-error">${status.message}</div>` : null}
        </div>
        <div class="gateway-actions">
          <dees-button .text=${'Start'} .type=${'default'} @click=${() => appstate.settingsStatePart.dispatchAction(appstate.startManagedDcRouterAction, null)}></dees-button>
          <dees-button .text=${'Restart'} .type=${'default'} @click=${() => appstate.settingsStatePart.dispatchAction(appstate.restartManagedDcRouterAction, null)}></dees-button>
          <dees-button .text=${'Stop'} .type=${'default'} @click=${() => appstate.settingsStatePart.dispatchAction(appstate.stopManagedDcRouterAction, null)}></dees-button>
        </div>
      </div>
    `;
  }

  private renderGatewayInput(
    key: keyof NonNullable<appstate.ISettingsState['settings']>,
    label: string,
    value: string,
    hint: string,
    isPassword = false,
  ): TemplateResult {
    return html`
      <div class="gateway-field ${key === 'dcrouterGatewayUrl' || key === 'adminUiDomain' ? 'full' : ''}">
        <dees-input-text
          .key=${key}
          .label=${label}
          .value=${value}
          .description=${hint}
          .isPasswordBool=${isPassword}
          @input=${(event: Event) => this.updateGatewayDraft(key, (event.target as HTMLInputElement).value)}
        ></dees-input-text>
      </div>
    `;
  }

  private renderGatewayReadonly(label: string, value: string, hint: string): TemplateResult {
    return html`
      <div class="gateway-readonly">
        <div class="gateway-readonly-label">${label}</div>
        <div class="gateway-readonly-value">${value}</div>
        <div class="gateway-readonly-hint">${hint}</div>
      </div>
    `;
  }

  private updateGatewayDraft(
    key: keyof NonNullable<appstate.ISettingsState['settings']>,
    value: string,
  ): void {
    const currentSettings = this.settingsState.settings || {} as NonNullable<appstate.ISettingsState['settings']>;
    const numberKeys = new Set([
      'dcrouterTargetPort',
      'dcrouterManagedOpsPort',
      'dcrouterManagedHttpPort',
      'dcrouterManagedHttpsPort',
    ]);
    const nextValue = numberKeys.has(key as string) ? Number(value) || 0 : value;
    this.settingsState = {
      ...this.settingsState,
      settings: {
        ...currentSettings,
        [key]: nextValue,
      },
    };
  }

  private async saveExternalGatewaySettings(): Promise<void> {
    const settings = this.settingsState.settings;
    if (!settings) return;

    await appstate.settingsStatePart.dispatchAction(appstate.updateSettingsAction, {
      settings: {
        dcrouterMode: settings.dcrouterMode || 'managed',
        dcrouterManagedImage: settings.dcrouterManagedImage || 'code.foss.global/serve.zone/dcrouter:latest',
        dcrouterManagedOpsPort: Number(settings.dcrouterManagedOpsPort) || 3300,
        dcrouterManagedHttpPort: Number(settings.dcrouterManagedHttpPort) || 80,
        dcrouterManagedHttpsPort: Number(settings.dcrouterManagedHttpsPort) || 443,
        dcrouterManagedDataDir: settings.dcrouterManagedDataDir || './.nogit/dcrouter-data',
        dcrouterGatewayUrl: settings.dcrouterGatewayUrl || '',
        dcrouterGatewayApiToken: settings.dcrouterGatewayApiToken || '',
        dcrouterTargetHost: settings.dcrouterTargetHost || '',
        dcrouterTargetPort: Number(settings.dcrouterTargetPort) || 80,
      },
    });
    await appstate.settingsStatePart.dispatchAction(appstate.fetchManagedDcRouterStatusAction, null);
  }

  private async saveAdminUiSettings(): Promise<void> {
    const settings = this.settingsState.settings;
    if (!settings) return;

    await appstate.settingsStatePart.dispatchAction(appstate.updateSettingsAction, {
      settings: {
        adminUiDomain: settings.adminUiDomain || '',
      },
    });
  }
}
