'use client';

import { useEffect, useState } from 'react';
import { Save, Loader2, Plus, X } from 'lucide-react';
import { apiFetch } from '@/lib/browser-navigation';

interface VncDirectoryFormData {
  enabled: boolean;
  apiUrl: string;
  apiKey: string;
  samlEnabled: boolean;
  samlIdpUrl: string;
  samlSpCert: string;
  samlIssuer: string;
  ldapEnabled: boolean;
  ldapUri: string;
  ldapBindDn: string;
  ldapBindPassword: string;
  ldapSearchBase: string;
  ldapType: 'openldap' | 'ms-ad';
  tfaEnabled: boolean;
  oidcEnabled: boolean;
  oidcClientId: string;
  oidcDiscoveryUrl: string;
  sessionTtl: number;
  federatedApps: Record<string, string>;
}

const BLANK_FORM: VncDirectoryFormData = {
  enabled: false,
  apiUrl: '',
  apiKey: '',
  samlEnabled: false,
  samlIdpUrl: '',
  samlSpCert: '',
  samlIssuer: '',
  ldapEnabled: false,
  ldapUri: '',
  ldapBindDn: '',
  ldapBindPassword: '',
  ldapSearchBase: '',
  ldapType: 'openldap',
  tfaEnabled: false,
  oidcEnabled: false,
  oidcClientId: '',
  oidcDiscoveryUrl: '',
  sessionTtl: 28800,
  federatedApps: {},
};

export function VncDirectoryTab() {
  const [config, setConfig] = useState<VncDirectoryFormData>({ ...BLANK_FORM });
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  const [dirty, setDirty] = useState(false);

  useEffect(() => { fetchConfig(); }, []);

  async function fetchConfig() {
    setLoading(true);
    try {
      const res = await apiFetch('/api/admin/vncdirectory');
      if (res.ok) {
        const data = await res.json();
        setConfig(data);
      }
    } finally {
      setLoading(false);
    }
  }

  function updateField<K extends keyof VncDirectoryFormData>(key: K, value: VncDirectoryFormData[K]) {
    setConfig((prev) => ({ ...prev, [key]: value }));
    setDirty(true);
    setMessage(null);
  }

  function toggleBool(key: keyof VncDirectoryFormData) {
    setConfig((prev) => ({ ...prev, [key]: !prev[key] }));
    setDirty(true);
    setMessage(null);
  }

  function setFederatedApp(name: string, url: string) {
    setConfig((prev) => ({
      ...prev,
      federatedApps: { ...prev.federatedApps, [name]: url },
    }));
    setDirty(true);
    setMessage(null);
  }

  function removeFederatedApp(name: string) {
    setConfig((prev) => {
      const next = { ...prev.federatedApps };
      delete next[name];
      return { ...prev, federatedApps: next };
    });
    setDirty(true);
    setMessage(null);
  }

  async function handleSave() {
    setSaving(true);
    setMessage(null);

    const res = await apiFetch('/api/admin/vncdirectory', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(config),
    });

    if (res.ok) {
      setMessage({ type: 'success', text: 'VNCdirectory configuration saved.' });
      setDirty(false);
      await fetchConfig();
    } else {
      const data = await res.json();
      setMessage({ type: 'error', text: data.error || 'Failed to save' });
    }
    setSaving(false);
  }

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12 text-muted-foreground text-sm">
        Loading...
      </div>
    );
  }

  const federatedAppsList = Object.entries(config.federatedApps);

  return (
    <div className="space-y-6">
      <div className="flex flex-wrap items-start justify-between gap-3">
        <div className="min-w-0">
          <h1 className="text-2xl font-semibold text-foreground">VNCdirectory</h1>
          <p className="text-sm text-muted-foreground mt-1">
            Centralized identity and directory integration (SAML, LDAP, 2FA)
          </p>
        </div>
        {dirty && (
          <button
            onClick={handleSave}
            disabled={saving}
            className="inline-flex items-center gap-2 h-9 px-4 rounded-md bg-primary text-primary-foreground text-sm font-medium hover:bg-primary/90 disabled:opacity-50 transition-all shadow-sm"
          >
            {saving ? <Loader2 className="w-4 h-4 animate-spin" /> : <Save className="w-4 h-4" />}
            Save configuration
          </button>
        )}
      </div>

      {message && (
        <div
          className={`text-sm rounded-md px-3 py-2 ${
            message.type === 'success'
              ? 'bg-emerald-50 text-emerald-700 dark:bg-emerald-950/30 dark:text-emerald-300'
              : 'bg-destructive/10 text-destructive'
          }`}
        >
          {message.text}
        </div>
      )}

      <Section title="Enable VNCdirectory Integration">
        <div className="px-4 py-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
          <div className="min-w-0">
            <span className="text-sm text-foreground">Enabled</span>
            <p className="text-xs text-muted-foreground mt-0.5">
              Turn on VNCdirectory integration for identity management, SSO, and directory services
            </p>
          </div>
          <button
            onClick={() => toggleBool('enabled')}
            className={`shrink-0 relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${
              config.enabled
                ? 'bg-primary'
                : 'bg-muted-foreground/25 dark:bg-muted-foreground/50'
            }`}
          >
            <span
              className={`inline-block h-3.5 w-3.5 transform rounded-full bg-background shadow transition-transform ${
                config.enabled ? 'translate-x-[18px]' : 'translate-x-[3px]'
              }`}
            />
          </button>
        </div>
      </Section>

      {config.enabled && (
        <>
          <Section title="Connection">
            <div className="divide-y divide-border">
              <TextRow
                label="VNCdirectory URL"
                value={config.apiUrl}
                onChange={(v) => updateField('apiUrl', v)}
                placeholder="https://vncdirectory.example.com"
              />
              <PasswordRow
                label="API Key"
                value={config.apiKey}
                onChange={(v) => updateField('apiKey', v)}
                placeholder="Enter API key"
              />
            </div>
          </Section>

          <Section title="SAML / Identity Provider">
            <div className="divide-y divide-border">
              <ToggleRow
                label="SAML Enabled"
                description="Enable SAML single sign-on via VNCdirectory"
                value={config.samlEnabled}
                onChange={() => toggleBool('samlEnabled')}
              />
              {config.samlEnabled && (
                <>
                  <TextRow
                    label="Identity Provider URL"
                    value={config.samlIdpUrl}
                    onChange={(v) => updateField('samlIdpUrl', v)}
                    placeholder="https://idp.example.com/saml2/idp"
                  />
                  <TextRow
                    label="Issuer Name (Entity ID)"
                    value={config.samlIssuer}
                    onChange={(v) => updateField('samlIssuer', v)}
                    placeholder="urn:example:vncmail"
                  />
                  <div className="px-4 py-3 flex flex-col gap-2">
                    <label className="text-sm text-foreground">
                      Service Provider Certificate (X.509)
                    </label>
                    <textarea
                      value={config.samlSpCert}
                      onChange={(e) => updateField('samlSpCert', e.target.value)}
                      placeholder="-----BEGIN CERTIFICATE-----&#10;...&#10;-----END CERTIFICATE-----"
                      rows={4}
                      className="w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-sm font-mono text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring resize-vertical"
                    />
                  </div>
                </>
              )}
            </div>
          </Section>

          <Section title="LDAP Directory">
            <div className="divide-y divide-border">
              <ToggleRow
                label="LDAP Enabled"
                description="Query user directory via LDAP for contact lookups and authentication"
                value={config.ldapEnabled}
                onChange={() => toggleBool('ldapEnabled')}
              />
              {config.ldapEnabled && (
                <>
                  <TextRow
                    label="LDAP Server URI"
                    value={config.ldapUri}
                    onChange={(v) => updateField('ldapUri', v)}
                    placeholder="ldaps://ldap.example.com:636"
                  />
                  <TextRow
                    label="Bind DN"
                    value={config.ldapBindDn}
                    onChange={(v) => updateField('ldapBindDn', v)}
                    placeholder="cn=readonly,dc=example,dc=com"
                  />
                  <PasswordRow
                    label="Bind Password"
                    value={config.ldapBindPassword}
                    onChange={(v) => updateField('ldapBindPassword', v)}
                    placeholder="Enter LDAP bind password"
                  />
                  <TextRow
                    label="Search Base"
                    value={config.ldapSearchBase}
                    onChange={(v) => updateField('ldapSearchBase', v)}
                    placeholder="ou=users,dc=example,dc=com"
                  />
                  <SelectRow
                    label="LDAP Type"
                    value={config.ldapType}
                    options={[
                      { value: 'openldap', label: 'OpenLDAP' },
                      { value: 'ms-ad', label: 'Microsoft Active Directory' },
                    ]}
                    onChange={(v) => updateField('ldapType', v as 'openldap' | 'ms-ad')}
                  />
                </>
              )}
            </div>
          </Section>

          <Section title="Authentication">
            <div className="divide-y divide-border">
              <ToggleRow
                label="Enforce 2FA/TOTP"
                description="Require two-factor authentication for all users"
                value={config.tfaEnabled}
                onChange={() => toggleBool('tfaEnabled')}
              />
              <ToggleRow
                label="OpenID Connect (OIDC)"
                description="Enable OIDC login alongside or instead of SAML"
                value={config.oidcEnabled}
                onChange={() => toggleBool('oidcEnabled')}
              />
              {config.oidcEnabled && (
                <>
                  <TextRow
                    label="OIDC Client ID"
                    value={config.oidcClientId}
                    onChange={(v) => updateField('oidcClientId', v)}
                    placeholder="vncmail-client"
                  />
                  <TextRow
                    label="OIDC Discovery URL"
                    value={config.oidcDiscoveryUrl}
                    onChange={(v) => updateField('oidcDiscoveryUrl', v)}
                    placeholder="https://idp.example.com/.well-known/openid-configuration"
                  />
                </>
              )}
              <div className="px-4 py-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
                <div className="min-w-0">
                  <span className="text-sm text-foreground">Session TTL (seconds)</span>
                  <p className="text-xs text-muted-foreground mt-0.5">
                    How long SSO sessions remain valid. Default: 8 hours (28800)
                  </p>
                </div>
                <input
                  type="number"
                  min={0}
                  value={config.sessionTtl}
                  onChange={(e) => updateField('sessionTtl', Number(e.target.value))}
                  className="h-8 w-full sm:w-32 rounded-md border border-input bg-background px-2.5 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
                />
              </div>
            </div>
          </Section>

          <Section title="Federated Applications">
            <div className="px-4 py-3">
              <p className="text-xs text-muted-foreground mb-3">
                Configure SSO redirect URLs for other VNC applications. Users signed into one
                app will be transparently authenticated when navigating to another.
              </p>
              <div className="space-y-2">
                {federatedAppsList.map(([appName, url]) => (
                  <div
                    key={appName}
                    className="flex flex-col sm:flex-row items-start sm:items-center gap-2"
                  >
                    <input
                      type="text"
                      value={appName}
                      readOnly
                      className="h-8 w-full sm:w-36 rounded-md border border-input bg-muted/50 px-2.5 text-sm text-muted-foreground"
                    />
                    <input
                      type="url"
                      value={url}
                      onChange={(e) => setFederatedApp(appName, e.target.value)}
                      placeholder="https://vnc.example.com/auth/sso"
                      className="h-8 w-full sm:flex-1 rounded-md border border-input bg-background px-2.5 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
                    />
                    <button
                      onClick={() => removeFederatedApp(appName)}
                      className="shrink-0 text-muted-foreground hover:text-destructive transition-colors"
                      title={`Remove ${appName}`}
                    >
                      <X className="w-4 h-4" />
                    </button>
                  </div>
                ))}
                <AddFederatedApp
                  existingKeys={new Set(Object.keys(config.federatedApps))}
                  onAdd={(name, url) => setFederatedApp(name, url)}
                />
              </div>
            </div>
          </Section>
        </>
      )}
    </div>
  );
}

function AddFederatedApp({
  existingKeys,
  onAdd,
}: {
  existingKeys: Set<string>;
  onAdd: (name: string, url: string) => void;
}) {
  const [adding, setAdding] = useState(false);
  const [name, setName] = useState('');
  const [url, setUrl] = useState('');
  const [error, setError] = useState<string | null>(null);

  if (!adding) {
    return (
      <button
        type="button"
        onClick={() => setAdding(true)}
        className="inline-flex items-center gap-1.5 h-8 px-3 rounded-md border border-dashed border-input text-sm text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
      >
        <Plus className="w-3.5 h-3.5" />
        Add federated app
      </button>
    );
  }

  function handleAdd() {
    const trimmed = name.trim();
    if (!trimmed) {
      setError('Enter an application name');
      return;
    }
    if (!/^[a-zA-Z0-9_-]+$/.test(trimmed)) {
      setError('Name must contain only letters, numbers, hyphens, and underscores');
      return;
    }
    if (existingKeys.has(trimmed)) {
      setError('An app with this name already exists');
      return;
    }
    if (!url.trim()) {
      setError('Enter an SSO URL');
      return;
    }
    setError(null);
    onAdd(trimmed, url.trim());
    setName('');
    setUrl('');
    setAdding(false);
  }

  function handleCancel() {
    setAdding(false);
    setName('');
    setUrl('');
    setError(null);
  }

  return (
    <div className="flex flex-col gap-1.5">
      <div className="flex flex-col sm:flex-row items-start sm:items-center gap-2">
        <input
          type="text"
          autoFocus
          value={name}
          onChange={(e) => { setName(e.target.value); setError(null); }}
          onKeyDown={(e) => { if (e.key === 'Enter') handleAdd(); }}
          placeholder="App name (e.g. vnctalk)"
          className="h-8 w-full sm:w-36 rounded-md border border-input bg-background px-2.5 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
        />
        <input
          type="url"
          value={url}
          onChange={(e) => { setUrl(e.target.value); setError(null); }}
          onKeyDown={(e) => { if (e.key === 'Enter') handleAdd(); }}
          placeholder="https://vnctalk.example.com/auth/sso"
          className="h-8 w-full sm:flex-1 rounded-md border border-input bg-background px-2.5 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
        />
        <div className="flex items-center gap-1 shrink-0">
          <button
            type="button"
            onClick={handleAdd}
            className="inline-flex items-center h-8 px-3 rounded-md bg-primary text-primary-foreground text-sm font-medium hover:bg-primary/90 transition-colors"
          >
            Add
          </button>
          <button
            type="button"
            onClick={handleCancel}
            className="h-8 px-2.5 rounded-md text-sm text-muted-foreground hover:text-foreground transition-colors"
          >
            Cancel
          </button>
        </div>
      </div>
      {error && <span className="text-xs text-destructive">{error}</span>}
    </div>
  );
}

function Section({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <div className="border border-border rounded-lg">
      <div className="px-4 py-3 border-b border-border bg-muted/30">
        <h2 className="text-sm font-medium text-foreground">{title}</h2>
      </div>
      {children}
    </div>
  );
}

function TextRow({
  label,
  value,
  onChange,
  placeholder,
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
}) {
  return (
    <div className="px-4 py-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
      <span className="text-sm text-foreground">{label}</span>
      <input
        type="text"
        value={value ?? ''}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        className="h-8 w-full sm:w-72 rounded-md border border-input bg-background px-2.5 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
      />
    </div>
  );
}

function PasswordRow({
  label,
  value,
  onChange,
  placeholder,
}: {
  label: string;
  value: string;
  onChange: (v: string) => void;
  placeholder?: string;
}) {
  const isMasked = value === '••••••';

  return (
    <div className="px-4 py-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
      <span className="text-sm text-foreground">{label}</span>
      <div className="flex items-center gap-2 w-full sm:w-auto">
        <input
          type={isMasked ? 'text' : 'password'}
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value)}
          placeholder={placeholder || (isMasked ? 'Saved - type to replace' : undefined)}
          className="h-8 w-full sm:w-72 rounded-md border border-input bg-background px-2.5 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
        />
      </div>
    </div>
  );
}

function ToggleRow({
  label,
  description,
  value,
  onChange,
}: {
  label: string;
  description?: string;
  value: boolean;
  onChange: () => void;
}) {
  return (
    <div className="px-4 py-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
      <div className="min-w-0">
        <span className="text-sm text-foreground">{label}</span>
        {description && (
          <p className="text-xs text-muted-foreground mt-0.5">{description}</p>
        )}
      </div>
      <button
        onClick={onChange}
        className={`shrink-0 relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${
          value ? 'bg-primary' : 'bg-muted-foreground/25 dark:bg-muted-foreground/50'
        }`}
      >
        <span
          className={`inline-block h-3.5 w-3.5 transform rounded-full bg-background shadow transition-transform ${
            value ? 'translate-x-[18px]' : 'translate-x-[3px]'
          }`}
        />
      </button>
    </div>
  );
}

function SelectRow({
  label,
  value,
  options,
  onChange,
}: {
  label: string;
  value: string;
  options: { value: string; label: string }[];
  onChange: (v: string) => void;
}) {
  return (
    <div className="px-4 py-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
      <span className="text-sm text-foreground">{label}</span>
      <select
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className="h-8 rounded-md border border-input bg-background px-2.5 text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
      >
        {options.map((opt) => (
          <option key={opt.value} value={opt.value}>
            {opt.label}
          </option>
        ))}
      </select>
    </div>
  );
}
