'use client';

import { useState, useEffect, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
  User, Key, Users, Bell, Shield, Cpu,
  Eye, EyeOff, Check,
  Loader2, Save, Lock, Mail, CheckCircle2, AlertTriangle,
  GitBranch, Link2, Link2Off, LogOut, Monitor, Smartphone, Trash2,
  Wifi, WifiOff, Globe, CreditCard, Receipt, Plus, X,
  ShieldCheck, Smartphone as SmartphoneIcon, KeyRound, QrCode,
} from 'lucide-react';
import type { Project } from '../data/projectsData';
import { useSession } from '../lib/session-context';
import { api } from '../lib/api';
import { getPlanCapabilities } from '../lib/plan-access';
import CardSetupForm from './CardSetupModal';
import AdminFattureInCloud from './AdminFattureInCloud';

// ═══════════════════════════════════════════════════════════════════════════════
// TwoFASettings Component
// ═══════════════════════════════════════════════════════════════════════════════

type TwoFAMethod = 'email' | 'sms' | 'authenticator';

interface TwoFAStatus {
  enabled: boolean;
  method: TwoFAMethod | null;
}

function TwoFASettings() {
  const [status, setStatus] = useState<TwoFAStatus>({ enabled: false, method: null });
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [showSetup, setShowSetup] = useState(false);
  const [selectedMethod, setSelectedMethod] = useState<TwoFAMethod>('email');
  const [phoneNumber, setPhoneNumber] = useState('');
  const [qrUrl, setQrUrl] = useState<string | null>(null);
  const [secret, setSecret] = useState<string | null>(null);
  const [verificationCode, setVerificationCode] = useState('');
  const [error, setError] = useState('');
  const [success, setSuccess] = useState('');
  const [step, setStep] = useState<'select' | 'verify' | 'complete'>('select');

  // Load 2FA status
  useEffect(() => {
    fetch('/api/auth/2fa/setup', { credentials: 'include' })
      .then(r => r.json())
      .then(d => {
        setStatus({ enabled: d.enabled, method: d.method });
      })
      .catch(() => {})
      .finally(() => setLoading(false));
  }, []);

  const handleEnable = async () => {
    setError('');
    setSaving(true);

    try {
      if (selectedMethod === 'authenticator') {
        // Generate TOTP secret first
        const res = await fetch('/api/auth/2fa/setup', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          credentials: 'include',
          body: JSON.stringify({ action: 'generate-secret' }),
        });
        const data = await res.json();
        if (!res.ok) throw new Error(data.error);
        setSecret(data.secret);
        setQrUrl(data.otpauthUrl);
      } else if (selectedMethod === 'sms') {
        if (!phoneNumber.trim()) {
          throw new Error('Phone number required for SMS 2FA');
        }
      }

      // Move to verification step
      setStep('verify');
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to start 2FA setup');
    } finally {
      setSaving(false);
    }
  };

  const handleVerifyAndEnable = async () => {
    setError('');
    setSaving(true);

    try {
      const res = await fetch('/api/auth/2fa/setup', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({
          action: 'verify-and-enable',
          method: selectedMethod,
          code: verificationCode,
          secret,
          phoneNumber: selectedMethod === 'sms' ? phoneNumber : undefined,
        }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error);

      setStatus({ enabled: true, method: selectedMethod });
      setSuccess('2FA enabled successfully');
      setStep('complete');
      setTimeout(() => {
        setShowSetup(false);
        setStep('select');
        setVerificationCode('');
        setQrUrl(null);
        setSecret(null);
        setSuccess('');
      }, 2000);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Verification failed');
    } finally {
      setSaving(false);
    }
  };

  const handleDisable = async () => {
    setError('');
    setSaving(true);

    try {
      const res = await fetch('/api/auth/2fa/setup', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ action: 'disable' }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error);

      setStatus({ enabled: false, method: null });
      setSuccess('2FA disabled successfully');
      setTimeout(() => setSuccess(''), 3000);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to disable 2FA');
    } finally {
      setSaving(false);
    }
  };

  const getMethodIcon = (method: TwoFAMethod) => {
    switch (method) {
      case 'email': return <Mail className="w-5 h-5" />;
      case 'sms': return <SmartphoneIcon className="w-5 h-5" />;
      case 'authenticator': return <KeyRound className="w-5 h-5" />;
    }
  };

  const getMethodLabel = (method: TwoFAMethod) => {
    switch (method) {
      case 'email': return 'Email Verification';
      case 'sms': return 'SMS Verification';
      case 'authenticator': return 'Authenticator App';
    }
  };

  const getMethodDescription = (method: TwoFAMethod) => {
    switch (method) {
      case 'email': return 'Receive a 6-digit code via email at login';
      case 'sms': return 'Receive a 6-digit code via SMS at login';
      case 'authenticator': return 'Use an authenticator app like Google Authenticator or Authy';
    }
  };

  if (loading) {
    return (
      <div className="glass-light rounded-lg p-6">
        <div className="flex items-center gap-3">
          <Loader2 className="w-5 h-5 animate-spin text-muted" />
          <span className="text-sm text-muted">Loading 2FA settings...</span>
        </div>
      </div>
    );
  }

  return (
    <div className="glass-light rounded-lg p-6 space-y-4">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <div className="w-10 h-10 rounded-lg bg-accent/10 flex items-center justify-center">
            <ShieldCheck className="w-5 h-5 text-accent" />
          </div>
          <div>
            <h4 className="text-sm font-semibold text-foreground">Two-Factor Authentication</h4>
            <p className="text-xs text-muted">
              {status.enabled ? `Enabled via ${status.method ? getMethodLabel(status.method) : 'unknown'}` : 'Add an extra layer of security'}
            </p>
          </div>
        </div>
        <div className="flex items-center gap-3">
          {status.enabled ? (
            <>
              <span className="text-xs px-2.5 py-1 rounded-full bg-success/15 text-success font-medium">Enabled</span>
              <button
                onClick={handleDisable}
                disabled={saving}
                className="px-4 py-2 rounded-lg border border-danger/30 text-danger text-xs font-medium hover:bg-danger/10 transition-colors disabled:opacity-50"
              >
                {saving ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : 'Disable'}
              </button>
            </>
          ) : (
            <button
              onClick={() => setShowSetup(true)}
              className="px-4 py-2 rounded-lg gradient-accent text-white text-xs font-medium hover:opacity-90 transition-opacity"
            >
              Enable 2FA
            </button>
          )}
        </div>
      </div>

      {/* Messages */}
      {error && (
        <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-danger/10 border border-danger/25 text-danger text-xs">
          <AlertTriangle className="w-3.5 h-3.5" />
          {error}
        </div>
      )}
      {success && (
        <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-success/10 border border-success/25 text-success text-xs">
          <CheckCircle2 className="w-3.5 h-3.5" />
          {success}
        </div>
      )}

      {/* Setup Modal */}
      {showSetup && (
        <div className="border-t border-border pt-4 space-y-4">
          {step === 'select' && (
            <>
              <p className="text-sm font-medium text-foreground">Choose your 2FA method:</p>
              <div className="grid gap-3">
                {(['email', 'sms', 'authenticator'] as TwoFAMethod[]).map((method) => (
                  <label
                    key={method}
                    className={`flex items-start gap-3 p-4 rounded-lg border cursor-pointer transition-all ${
                      selectedMethod === method
                        ? 'border-accent bg-accent/5'
                        : 'border-border hover:border-accent/30'
                    }`}
                  >
                    <input
                      type="radio"
                      name="2fa-method"
                      value={method}
                      checked={selectedMethod === method}
                      onChange={() => setSelectedMethod(method)}
                      className="mt-0.5"
                    />
                    <div className="flex-1">
                      <div className="flex items-center gap-2">
                        {getMethodIcon(method)}
                        <span className="text-sm font-medium text-foreground">{getMethodLabel(method)}</span>
                      </div>
                      <p className="text-xs text-muted mt-1">{getMethodDescription(method)}</p>
                    </div>
                  </label>
                ))}
              </div>

              {selectedMethod === 'sms' && (
                <div className="space-y-2">
                  <label className="text-xs text-muted uppercase tracking-wider">Phone Number</label>
                  <input
                    type="tel"
                    value={phoneNumber}
                    onChange={(e) => setPhoneNumber(e.target.value)}
                    placeholder="+1234567890"
                    className="w-full bg-surface rounded-lg px-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/40"
                  />
                </div>
              )}

              <div className="flex gap-2 pt-2">
                <button
                  onClick={handleEnable}
                  disabled={saving || (selectedMethod === 'sms' && !phoneNumber.trim())}
                  className="flex-1 py-2.5 gradient-accent text-white rounded-lg text-sm font-medium hover:opacity-90 transition-opacity disabled:opacity-50"
                >
                  {saving ? <Loader2 className="w-4 h-4 animate-spin mx-auto" /> : 'Continue'}
                </button>
                <button
                  onClick={() => setShowSetup(false)}
                  className="px-4 py-2.5 border border-border text-muted rounded-lg text-sm font-medium hover:text-foreground transition-colors"
                >
                  Cancel
                </button>
              </div>
            </>
          )}

          {step === 'verify' && (
            <>
              {selectedMethod === 'authenticator' && qrUrl && (
                <div className="text-center space-y-3">
                  <p className="text-sm text-foreground">Scan this QR code with your authenticator app:</p>
                  <div className="inline-block p-4 bg-white rounded-lg">
                    <img
                      src={`https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${encodeURIComponent(qrUrl)}`}
                      alt="2FA QR Code"
                      className="w-36 h-36"
                    />
                  </div>
                  {secret && (
                    <div className="text-center">
                      <p className="text-xs text-muted mb-1">Or enter this code manually:</p>
                      <code className="text-xs bg-surface px-3 py-1.5 rounded font-mono">{secret}</code>
                    </div>
                  )}
                </div>
              )}

              <div className="space-y-2">
                <label className="text-xs text-muted uppercase tracking-wider">
                  {selectedMethod === 'authenticator' ? 'Enter code from app' : 'Enter verification code'}
                </label>
                <input
                  type="text"
                  inputMode="numeric"
                  maxLength={6}
                  value={verificationCode}
                  onChange={(e) => setVerificationCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
                  placeholder="000000"
                  className="w-full text-center text-2xl font-mono tracking-[0.5em] bg-surface rounded-lg px-4 py-3 text-foreground outline-none border border-transparent focus:border-accent/40"
                />
              </div>

              <div className="flex gap-2 pt-2">
                <button
                  onClick={handleVerifyAndEnable}
                  disabled={saving || verificationCode.length !== 6}
                  className="flex-1 py-2.5 gradient-accent text-white rounded-lg text-sm font-medium hover:opacity-90 transition-opacity disabled:opacity-50"
                >
                  {saving ? <Loader2 className="w-4 h-4 animate-spin mx-auto" /> : 'Verify & Enable'}
                </button>
                <button
                  onClick={() => setStep('select')}
                  className="px-4 py-2.5 border border-border text-muted rounded-lg text-sm font-medium hover:text-foreground transition-colors"
                >
                  Back
                </button>
              </div>
            </>
          )}
        </div>
      )}
    </div>
  );
}

const BASE_TABS = [
  { id: 'profile', label: 'Profile', icon: User },
  { id: 'security', label: 'Security', icon: Shield },
  { id: 'github', label: 'Connections', icon: GitBranch },
  { id: 'engine', label: 'Engine', icon: Cpu },
  { id: 'notifications', label: 'Notifications', icon: Bell },
];
const BILLING_TAB = { id: 'billing', label: 'Billing', icon: CreditCard };
const FIC_TAB = { id: 'fic', label: 'FIC Settings', icon: Receipt };

type ProviderStatus = { connected: boolean; login?: string; name?: string; avatar?: string; url?: string } | null;

interface UserData { id: string; email: string; name: string; createdAt: string; }

interface ActiveSession {
  id: string;
  current: boolean;
  ipAddress: string;
  userAgent: string;
  createdAt: string;
  expiresAt: string;
}

interface EngineLanguages {
  source: string[];
  target: string[];
}

interface EngineStatus {
  status: string;
  version?: string;
  /** Engine may send `source`/`target` or `sources`/`targets`. */
  languages?: { source?: string[]; target?: string[]; sources?: string[]; targets?: string[] };
  uptime?: number;
}

interface KbDoc {
  docId: string;
  kind: string;
  title: string;
  createdAt?: string;
}

interface DatasetItem {
  datasetId: string;
  createdAt?: string;
  size?: number;
}

interface SmtpSettings {
  host: string;
  port: string;
  username: string;
  password: string;
  fromEmail: string;
  fromName: string;
  replyTo: string;
  secure: boolean;
}

function normalizeEngineLanguages(raw: EngineStatus['languages'] | null | undefined): EngineLanguages | null {
  if (!raw) return null;
  const source = raw.source ?? raw.sources;
  const target = raw.target ?? raw.targets;
  if (!Array.isArray(source) && !Array.isArray(target)) return null;
  const out: EngineLanguages = {
    source: Array.isArray(source) ? source : [],
    target: Array.isArray(target) ? target : [],
  };
  if (out.source.length === 0 && out.target.length === 0) return null;
  return out;
}

interface SettingsProps {
  projects?: Project[];
  initialTab?: string;
  initialProviderTab?: 'github' | 'gitlab' | 'azure' | 'bitbucket';
}

export default function Settings({ projects = [], initialTab = 'profile', initialProviderTab }: SettingsProps) {
  const { user: sessionUser } = useSession();
  const capabilities = getPlanCapabilities(sessionUser?.tier);
  const isOwner = sessionUser?.isOwner ?? false;
  const isAdmin = sessionUser?.role === 'admin';
  // Billing tab only visible to company owners and admins
  const tabs = [
    ...BASE_TABS,
    ...(isOwner || isAdmin ? [BILLING_TAB] : []),
    ...(isAdmin ? [FIC_TAB] : []),
  ];
  const [activeTab, setActiveTab] = useState(initialTab);

  useEffect(() => {
    setActiveTab(initialTab);
  }, [initialTab]);

  // ── Profile state ──────────────────────────────────────────────
  const [userData, setUserData] = useState<UserData | null>(null);
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [saving, setSaving] = useState(false);
  const [profileMsg, setProfileMsg] = useState<{ type: 'success' | 'error'; text: string } | null>(null);

  // ── Password state ─────────────────────────────────────────────
  const [currentPassword, setCurrentPassword] = useState('');
  const [newPassword, setNewPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const [showCurrent, setShowCurrent] = useState(false);
  const [showNew, setShowNew] = useState(false);
  const [changingPwd, setChangingPwd] = useState(false);
  const [pwdMsg, setPwdMsg] = useState<{ type: 'success' | 'error'; text: string } | null>(null);

  // ── Connections sub-tab ────────────────────────────────────────
  const [providerSubTab, setProviderSubTab] = useState<'github' | 'gitlab' | 'azure' | 'bitbucket'>(initialProviderTab ?? 'github');

  useEffect(() => {
    if (initialProviderTab) setProviderSubTab(initialProviderTab);
  }, [initialProviderTab]);

  // ── GitHub state ───────────────────────────────────────────────
  const [ghStatus, setGhStatus] = useState<ProviderStatus>(null);
  const [ghLoading, setGhLoading] = useState(false);
  const [ghDisconnecting, setGhDisconnecting] = useState(false);
  const [oauthConfigured, setOauthConfigured] = useState<boolean | null>(null);
  const [patValue, setPatValue] = useState('');
  const [patSaving, setPatSaving] = useState(false);
  const [patMsg, setPatMsg] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  const [showPat, setShowPat] = useState(false);

  // ── GitLab state ───────────────────────────────────────────────
  const [glStatus, setGlStatus] = useState<ProviderStatus>(null);
  const [glLoading, setGlLoading] = useState(false);
  const [glDisconnecting, setGlDisconnecting] = useState(false);
  const [glOauthConfigured, setGlOauthConfigured] = useState<boolean | null>(null);
  const [glPatValue, setGlPatValue] = useState('');
  const [glPatSaving, setGlPatSaving] = useState(false);
  const [glPatMsg, setGlPatMsg] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  const [glShowPat, setGlShowPat] = useState(false);

  // ── Azure DevOps state ─────────────────────────────────────────
  const [azStatus, setAzStatus] = useState<ProviderStatus>(null);
  const [azLoading, setAzLoading] = useState(false);
  const [azDisconnecting, setAzDisconnecting] = useState(false);
  const [azPatValue, setAzPatValue] = useState('');
  const [azPatSaving, setAzPatSaving] = useState(false);
  const [azPatMsg, setAzPatMsg] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  const [azShowPat, setAzShowPat] = useState(false);

  // ── Bitbucket state ────────────────────────────────────────────
  const [bbStatus, setBbStatus] = useState<ProviderStatus>(null);
  const [bbLoading, setBbLoading] = useState(false);
  const [bbDisconnecting, setBbDisconnecting] = useState(false);
  const [bbOauthConfigured, setBbOauthConfigured] = useState<boolean | null>(null);
  const [bbPatValue, setBbPatValue] = useState('');
  const [bbPatSaving, setBbPatSaving] = useState(false);
  const [bbPatMsg, setBbPatMsg] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  const [bbShowPat, setBbShowPat] = useState(false);

  // ── Security / Sessions state ──────────────────────────────────
  const [activeSessions, setActiveSessions] = useState<ActiveSession[]>([]);
  const [sessionsLoading, setSessionsLoading] = useState(false);
  const [revokingSession, setRevokingSession] = useState<string | null>(null);
  const [sessionsPage, setSessionsPage] = useState(0);
  const SESSIONS_PER_PAGE = 10;
  const [revokingAll, setRevokingAll] = useState(false);

  // ── Engine state ───────────────────────────────────────────────
  const [engineStatus, setEngineStatus] = useState<EngineStatus | null>(null);
  const [engineLanguages, setEngineLanguages] = useState<EngineLanguages | null>(null);
  const [engineLoading, setEngineLoading] = useState(false);
  const [engineError, setEngineError] = useState(false);

  // ── Webhook admin state (ML01 §7) ─────────────────────────────
  const [webhookUrl, setWebhookUrl] = useState('');
  const [webhookSaving, setWebhookSaving] = useState(false);
  const [webhookMsg, setWebhookMsg] = useState<{ type: 'success' | 'error' | 'warn'; text: string } | null>(null);

  // ── KB state (§12.1) ───────────────────────────────────────────
  const [kbEnabled, setKbEnabled] = useState<boolean | null>(null);
  const [kbDocs, setKbDocs] = useState<KbDoc[]>([]);
  const [kbLoading, setKbLoading] = useState(false);
  const [kbAddOpen, setKbAddOpen] = useState(false);
  const [kbNewKind, setKbNewKind] = useState('style-guide');
  const [kbNewTitle, setKbNewTitle] = useState('');
  const [kbNewContent, setKbNewContent] = useState('');
  const [kbAddLoading, setKbAddLoading] = useState(false);
  const [kbSearchQ, setKbSearchQ] = useState('');
  const [kbSearchResults, setKbSearchResults] = useState<KbDoc[] | null>(null);
  const [kbError, setKbError] = useState('');

  // ── Dataset state (§12.2) ──────────────────────────────────────
  const [datasetEnabled, setDatasetEnabled] = useState<boolean | null>(null);
  const [datasets, setDatasets] = useState<DatasetItem[]>([]);
  const [datasetLoading, setDatasetLoading] = useState(false);
  const [datasetAddLoading, setDatasetAddLoading] = useState(false);
  const [datasetError, setDatasetError] = useState('');

  // ── Notification prefs (localStorage) ──────────────────────────
  const defaultNotifs = {
    conversionComplete: true,
    validationWarnings: true,
    teamActivity: false,
    weeklyReports: true,
    systemUpdates: true,
  };
  const defaultSmtpSettings: SmtpSettings = {
    host: '',
    port: '587',
    username: '',
    password: '',
    fromEmail: '',
    fromName: 'Scriba',
    replyTo: '',
    secure: false,
  };
  const [notifPrefs, setNotifPrefs] = useState(defaultNotifs);
  const [smtpSettings, setSmtpSettings] = useState<SmtpSettings>(defaultSmtpSettings);
  const [smtpMsg, setSmtpMsg] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  const [showSmtpPassword, setShowSmtpPassword] = useState(false);

  useEffect(() => {
    try {
      const saved = localStorage.getItem('scriba:notif-prefs');
      if (saved) setNotifPrefs(JSON.parse(saved));
    } catch {}
  }, []);

  const toggleNotif = (key: keyof typeof defaultNotifs) => {
    setNotifPrefs(prev => {
      const next = { ...prev, [key]: !prev[key] };
      localStorage.setItem('scriba:notif-prefs', JSON.stringify(next));
      return next;
    });
  };

  useEffect(() => {
    if (!(isOwner || isAdmin)) return;
    try {
      const saved = localStorage.getItem('scriba:smtp-settings');
      if (saved) {
        const parsed = JSON.parse(saved) as Partial<SmtpSettings>;
        setSmtpSettings({
          ...defaultSmtpSettings,
          ...parsed,
        });
      }
    } catch {}
  }, [isOwner, isAdmin]);

  const handleSmtpChange = (key: keyof SmtpSettings, value: string | boolean) => {
    setSmtpSettings(prev => ({ ...prev, [key]: value }));
  };

  const handleSaveSmtp = () => {
    if (!smtpSettings.host.trim()) {
      setSmtpMsg({ type: 'error', text: 'SMTP host is required' });
      return;
    }
    if (!smtpSettings.port.trim()) {
      setSmtpMsg({ type: 'error', text: 'SMTP port is required' });
      return;
    }
    if (!smtpSettings.fromEmail.trim()) {
      setSmtpMsg({ type: 'error', text: 'From email is required' });
      return;
    }
    try {
      localStorage.setItem('scriba:smtp-settings', JSON.stringify(smtpSettings));
      setSmtpMsg({ type: 'success', text: 'SMTP settings saved' });
    } catch {
      setSmtpMsg({ type: 'error', text: 'Could not save SMTP settings' });
    }
  };

  // ── Billing state ──────────────────────────────────────────────
  interface PaymentMethod {
    id: string;
    type: string;
    // Card / wallet
    brand?: string;
    last4?: string;
    expMonth?: number;
    expYear?: number;
    // PayPal
    email?: string;
    // SEPA
    bankCode?: string;
    country?: string;
    isDefault: boolean;
  }
  interface BillingRecord {
    id: string;
    periodStart: string;
    periodEnd: string;
    totalTokens: number;
    amountCents: number;
    currency: string;
    status: string;
  }
  interface BillingEstimate {
    totalTokens: number;
    billableTokens: number;
    freeTokensApplied: number;
    amountCents: number;
    slotChargesCents?: number;
  }

  const [paymentMethods, setPaymentMethods] = useState<PaymentMethod[]>([]);
  const [billingRecords, setBillingRecords] = useState<BillingRecord[]>([]);
  const [billingEstimate, setBillingEstimate] = useState<BillingEstimate | null>(null);
  const [billingLoading, setBillingLoading] = useState(false);
  const [billingMsg, setBillingMsg] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
  const [removingPm, setRemovingPm] = useState<string | null>(null);
  const [showCardForm, setShowCardForm] = useState(false);

  const loadBilling = useCallback(() => {
    setBillingLoading(true);
    Promise.all([
      fetch('/api/billing/payment-method').then(r => r.json()).catch(() => ({ methods: [] })),
      fetch('/api/billing/history').then(r => r.json()).catch(() => ({ records: [], estimate: null })),
    ]).then(([pmData, histData]) => {
      setPaymentMethods(pmData.methods ?? []);
      setBillingRecords(histData.records ?? []);
      setBillingEstimate(histData.estimate ?? null);
    }).finally(() => setBillingLoading(false));
  }, []);

  useEffect(() => {
    if (activeTab === 'billing') loadBilling();
  }, [activeTab, loadBilling]);

  const handleRemovePaymentMethod = async (pmId: string) => {
    setRemovingPm(pmId);
    setBillingMsg(null);
    try {
      const res = await fetch('/api/billing/payment-method', {
        method: 'DELETE',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ paymentMethodId: pmId }),
      });
      const d = await res.json();
      if (!res.ok) throw new Error(d.error);
      setPaymentMethods(prev => prev.filter(m => m.id !== pmId));
      setBillingMsg({ type: 'success', text: 'Card removed' });
    } catch (err) {
      setBillingMsg({ type: 'error', text: err instanceof Error ? err.message : 'Error' });
    } finally {
      setRemovingPm(null);
    }
  };

  const handleCardSetupSuccess = (_pmId: string) => {
    setShowCardForm(false);
    setBillingMsg({ type: 'success', text: 'Payment method saved successfully' });
    loadBilling();
  };

  // Handle return from redirect-based payment method setup (e.g. PayPal)
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    if (params.get('billing_return') !== '1') return;
    // Clear the param without page reload
    const clean = window.location.pathname;
    window.history.replaceState({}, '', clean);
    setActiveTab('billing');
    setBillingMsg({ type: 'success', text: 'Payment method saved successfully' });
    loadBilling();
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const fmtEur = (cents: number) =>
    new Intl.NumberFormat('en-EU', { style: 'currency', currency: 'EUR' }).format(cents / 100);

  const statusColor = (s: string) =>
    s === 'charged' ? 'text-success' : s === 'failed' ? 'text-danger' : 'text-muted';

  // ── Load profile on mount ──────────────────────────────────────
  useEffect(() => {
    fetch('/api/user/profile').then(r => r.json()).then(d => {
      if (d.user) {
        setUserData(d.user);
        setName(d.user.name || '');
        setEmail(d.user.email || '');
      }
    }).catch(() => {});
  }, []);

  // ── Load provider statuses lazily ─────────────────────────────
  useEffect(() => {
    if (activeTab !== 'github') return;
    if (providerSubTab === 'github' && ghStatus === null) {
      setGhLoading(true);
      Promise.all([
        fetch('/api/github/status').then(r => r.json()).catch(() => ({ connected: false })),
        fetch('/api/github/oauth-config').then(r => r.json()).catch(() => ({ configured: false })),
      ]).then(([status, cfg]) => {
        setGhStatus(status);
        setOauthConfigured(cfg.configured ?? false);
        if (!cfg.configured && !status.connected) setShowPat(true);
      }).finally(() => setGhLoading(false));
    }
    if (providerSubTab === 'gitlab' && glStatus === null) {
      setGlLoading(true);
      Promise.all([
        fetch('/api/gitlab/status').then(r => r.json()).catch(() => ({ connected: false })),
        fetch('/api/gitlab/oauth-config').then(r => r.json()).catch(() => ({ configured: false })),
      ]).then(([status, cfg]) => {
        setGlStatus(status);
        setGlOauthConfigured(cfg.configured ?? false);
        if (!cfg.configured && !status.connected) setGlShowPat(true);
      }).finally(() => setGlLoading(false));
    }
    if (providerSubTab === 'azure' && azStatus === null) {
      setAzLoading(true);
      fetch('/api/azure/status').then(r => r.json()).catch(() => ({ connected: false }))
        .then(status => {
          setAzStatus(status);
          if (!status.connected) setAzShowPat(true);
        }).finally(() => setAzLoading(false));
    }
    if (providerSubTab === 'bitbucket' && bbStatus === null) {
      setBbLoading(true);
      Promise.all([
        fetch('/api/bitbucket/status').then(r => r.json()).catch(() => ({ connected: false })),
        fetch('/api/bitbucket/oauth-config').then(r => r.json()).catch(() => ({ configured: false })),
      ]).then(([status, cfg]) => {
        setBbStatus(status);
        setBbOauthConfigured(cfg.configured ?? false);
        if (!cfg.configured && !status.connected) setBbShowPat(true);
      }).finally(() => setBbLoading(false));
    }
  }, [activeTab, providerSubTab, ghStatus, glStatus, azStatus, bbStatus]);

  // ── Load sessions lazily ───────────────────────────────────────
  const loadSessions = useCallback(() => {
    setSessionsLoading(true);
    setSessionsPage(0);
    fetch('/api/user/sessions').then(r => r.json()).then(d => setActiveSessions(d.sessions || [])).catch(() => {}).finally(() => setSessionsLoading(false));
  }, []);

  useEffect(() => {
    if (activeTab === 'security') loadSessions();
  }, [activeTab, loadSessions]);

  // ── Load engine status lazily ──────────────────────────────────
  useEffect(() => {
    if (activeTab === 'engine' && engineStatus === null) {
      setEngineLoading(true);
      setEngineError(false);
      fetch('/api/engine/health', { signal: AbortSignal.timeout(5000) })
        .then(r => { if (!r.ok) throw new Error(); return r.json(); })
        .then(d => setEngineStatus(d))
        .catch(() => setEngineError(true))
        .finally(() => setEngineLoading(false));
    }
  }, [activeTab, engineStatus]);

  useEffect(() => {
    if (activeTab !== 'engine' || !engineStatus || normalizeEngineLanguages(engineStatus.languages) || engineLanguages) return;
    api.engine
      .languages()
      .then((d: { source?: string[]; target?: string[]; sources?: string[]; targets?: string[] }) => {
        const norm = normalizeEngineLanguages(d);
        if (norm && (norm.source.length > 0 || norm.target.length > 0)) setEngineLanguages(norm);
      })
      .catch(() => {});
  }, [activeTab, engineStatus, engineLanguages]);

  // ── Probe KB + dataset availability when engine tab opens ───────
  useEffect(() => {
    if (activeTab !== 'engine' || !engineStatus) return;
    const customerId = sessionUser?.companyId ?? sessionUser?.id ?? 'default';
    if (kbEnabled === null) {
      setKbLoading(true);
      api.engine.customerKb.list(customerId).then((data) => {
        if (data === null) { setKbEnabled(false); setKbLoading(false); return; }
        setKbEnabled(true);
        const docs = Array.isArray(data?.docs) ? data.docs : Array.isArray(data) ? data : [];
        setKbDocs(docs as KbDoc[]);
        setKbLoading(false);
      }).catch(() => { setKbEnabled(false); setKbLoading(false); });
    }
    if (datasetEnabled === null) {
      setDatasetLoading(true);
      api.engine.customerDataset.list(customerId).then((data) => {
        if (data === null) { setDatasetEnabled(false); setDatasetLoading(false); return; }
        setDatasetEnabled(true);
        const items = Array.isArray(data?.datasets) ? data.datasets : Array.isArray(data) ? data : [];
        setDatasets(items as DatasetItem[]);
        setDatasetLoading(false);
      }).catch(() => { setDatasetEnabled(false); setDatasetLoading(false); });
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeTab, engineStatus]);

  const kbCustomerId = sessionUser?.companyId ?? sessionUser?.id ?? 'default';

  const handleKbAdd = async () => {
    if (!kbNewTitle.trim() || !kbNewContent.trim()) return;
    setKbAddLoading(true);
    setKbError('');
    try {
      await api.engine.customerKb.add(kbCustomerId, { kind: kbNewKind, title: kbNewTitle, content: kbNewContent });
      const refreshed = await api.engine.customerKb.list(kbCustomerId);
      if (refreshed !== null) {
        const docs = Array.isArray(refreshed?.docs) ? refreshed.docs : Array.isArray(refreshed) ? refreshed : [];
        setKbDocs(docs as KbDoc[]);
      }
      setKbNewTitle('');
      setKbNewContent('');
      setKbNewKind('style-guide');
      setKbAddOpen(false);
    } catch (err) {
      setKbError(err instanceof Error ? err.message : 'Failed to add document');
    } finally {
      setKbAddLoading(false);
    }
  };

  const handleKbRemove = async (docId: string) => {
    setKbError('');
    try {
      await api.engine.customerKb.remove(kbCustomerId, docId);
      setKbDocs(prev => prev.filter(d => d.docId !== docId));
      if (kbSearchResults) setKbSearchResults(prev => prev ? prev.filter(d => d.docId !== docId) : null);
    } catch (err) {
      setKbError(err instanceof Error ? err.message : 'Failed to remove document');
    }
  };

  const handleKbSearch = async () => {
    if (!kbSearchQ.trim()) { setKbSearchResults(null); return; }
    try {
      const data = await api.engine.customerKb.search(kbCustomerId, kbSearchQ);
      if (data === null) { setKbSearchResults(null); return; }
      const results = Array.isArray(data?.results) ? data.results : Array.isArray(data) ? data : [];
      setKbSearchResults(results as KbDoc[]);
    } catch {
      setKbSearchResults(null);
    }
  };

  const handleDatasetUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setDatasetAddLoading(true);
    setDatasetError('');
    try {
      const base64 = await new Promise<string>((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => resolve((reader.result as string).split(',')[1] ?? '');
        reader.onerror = reject;
        reader.readAsDataURL(file);
      });
      await api.engine.customerDataset.upload(kbCustomerId, base64);
      const refreshed = await api.engine.customerDataset.list(kbCustomerId);
      if (refreshed !== null) {
        const items = Array.isArray(refreshed?.datasets) ? refreshed.datasets : Array.isArray(refreshed) ? refreshed : [];
        setDatasets(items as DatasetItem[]);
      }
    } catch (err) {
      setDatasetError(err instanceof Error ? err.message : 'Upload failed');
    } finally {
      setDatasetAddLoading(false);
      e.target.value = '';
    }
  };

  const handleDatasetRemove = async (datasetId: string) => {
    setDatasetError('');
    try {
      await api.engine.customerDataset.remove(kbCustomerId, datasetId);
      setDatasets(prev => prev.filter(d => d.datasetId !== datasetId));
    } catch (err) {
      setDatasetError(err instanceof Error ? err.message : 'Failed to remove dataset');
    }
  };

  // ── Handlers ───────────────────────────────────────────────────
  const handleSaveProfile = async (e: React.FormEvent) => {
    e.preventDefault();
    setSaving(true);
    setProfileMsg(null);
    try {
      const res = await fetch('/api/user/profile', {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name, email }),
      });
      const d = await res.json();
      if (!res.ok) throw new Error(d.error);
      setUserData(d.user);
      setProfileMsg({ type: 'success', text: 'Profile updated' });
    } catch (err) {
      setProfileMsg({ type: 'error', text: err instanceof Error ? err.message : 'Error' });
    } finally {
      setSaving(false);
    }
  };

  const handleChangePassword = async (e: React.FormEvent) => {
    e.preventDefault();
    setPwdMsg(null);
    if (newPassword !== confirmPassword) { setPwdMsg({ type: 'error', text: 'Passwords do not match' }); return; }
    if (newPassword.length < 6) { setPwdMsg({ type: 'error', text: 'Password must be at least 6 characters' }); return; }
    setChangingPwd(true);
    try {
      const res = await fetch('/api/user/password', {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ currentPassword, newPassword }),
      });
      const d = await res.json();
      if (!res.ok) throw new Error(d.error);
      setCurrentPassword(''); setNewPassword(''); setConfirmPassword('');
      setPwdMsg({ type: 'success', text: 'Password updated successfully' });
    } catch (err) {
      setPwdMsg({ type: 'error', text: err instanceof Error ? err.message : 'Error' });
    } finally {
      setChangingPwd(false);
    }
  };

  const handleGhDisconnect = async () => {
    setGhDisconnecting(true);
    await fetch('/api/github/disconnect', { method: 'DELETE' });
    setGhStatus({ connected: false });
    setGhDisconnecting(false);
  };

  const handlePatSave = async () => {
    if (!patValue.trim()) return;
    setPatSaving(true);
    setPatMsg(null);
    try {
      const res = await fetch('/api/github/pat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token: patValue.trim() }),
      });
      const data = await res.json();
      if (!res.ok) {
        setPatMsg({ type: 'error', text: data.error ?? 'Failed to save token' });
      } else {
        setGhStatus(data);
        setPatValue('');
        setShowPat(false);
        setPatMsg({ type: 'success', text: `Connected as ${data.login}` });
      }
    } catch {
      setPatMsg({ type: 'error', text: 'Network error — please try again' });
    }
    setPatSaving(false);
  };

  const handleGlDisconnect = async () => {
    setGlDisconnecting(true);
    await fetch('/api/gitlab/disconnect', { method: 'DELETE' });
    setGlStatus({ connected: false });
    setGlDisconnecting(false);
  };

  const handleGlPatSave = async () => {
    if (!glPatValue.trim()) return;
    setGlPatSaving(true); setGlPatMsg(null);
    try {
      const res = await fetch('/api/gitlab/pat', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token: glPatValue.trim() }),
      });
      const data = await res.json();
      if (!res.ok) { setGlPatMsg({ type: 'error', text: data.error ?? 'Failed to save token' }); }
      else { setGlStatus(data); setGlPatValue(''); setGlShowPat(false); setGlPatMsg({ type: 'success', text: `Connected as ${data.login}` }); }
    } catch { setGlPatMsg({ type: 'error', text: 'Network error — please try again' }); }
    setGlPatSaving(false);
  };

  const handleAzDisconnect = async () => {
    setAzDisconnecting(true);
    await fetch('/api/azure/disconnect', { method: 'DELETE' });
    setAzStatus({ connected: false });
    setAzDisconnecting(false);
  };

  const handleAzPatSave = async () => {
    if (!azPatValue.trim()) return;
    setAzPatSaving(true); setAzPatMsg(null);
    try {
      const res = await fetch('/api/azure/pat', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token: azPatValue.trim() }),
      });
      const data = await res.json();
      if (!res.ok) { setAzPatMsg({ type: 'error', text: data.error ?? 'Failed to save token' }); }
      else { setAzStatus(data); setAzPatValue(''); setAzShowPat(false); setAzPatMsg({ type: 'success', text: `Connected as ${data.name || data.login}` }); }
    } catch { setAzPatMsg({ type: 'error', text: 'Network error — please try again' }); }
    setAzPatSaving(false);
  };

  const handleBbDisconnect = async () => {
    setBbDisconnecting(true);
    await fetch('/api/bitbucket/disconnect', { method: 'DELETE' });
    setBbStatus({ connected: false });
    setBbDisconnecting(false);
  };

  const handleBbPatSave = async () => {
    if (!bbPatValue.trim()) return;
    setBbPatSaving(true); setBbPatMsg(null);
    try {
      const res = await fetch('/api/bitbucket/pat', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token: bbPatValue.trim() }),
      });
      const data = await res.json();
      if (!res.ok) { setBbPatMsg({ type: 'error', text: data.error ?? 'Failed to save token' }); }
      else { setBbStatus(data); setBbPatValue(''); setBbShowPat(false); setBbPatMsg({ type: 'success', text: `Connected as ${data.login}` }); }
    } catch { setBbPatMsg({ type: 'error', text: 'Network error — please try again' }); }
    setBbPatSaving(false);
  };

  const handleRevokeSession = async (targetId: string) => {
    setRevokingSession(targetId);
    try {
      await fetch('/api/user/sessions', {
        method: 'DELETE',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ targetSessionId: targetId }),
      });
      setActiveSessions(prev => prev.filter(s => s.id !== targetId));
    } catch {}
    setRevokingSession(null);
  };

  const handleRevokeAllSessions = async () => {
    setRevokingAll(true);
    try {
      await fetch('/api/user/sessions', {
        method: 'DELETE',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ revokeAll: true }),
      });
      setActiveSessions(prev => prev.filter(s => s.current));
      setSessionsPage(0);
    } catch {}
    setRevokingAll(false);
  };

  const handleSignOut = async () => {
    await fetch('/api/auth/signout', { method: 'POST', credentials: 'include' });
    window.location.href = '/';
  };

  // ── Helper: parse user-agent ───────────────────────────────────
  const parseUA = (ua: string) => {
    if (ua.includes('curl')) return { device: 'CLI', browser: 'curl' };
    const isMobile = /Mobile|Android|iPhone/i.test(ua);
    let browser = 'Browser';
    if (ua.includes('Chrome') && !ua.includes('Edg')) browser = 'Chrome';
    else if (ua.includes('Safari') && !ua.includes('Chrome')) browser = 'Safari';
    else if (ua.includes('Firefox')) browser = 'Firefox';
    else if (ua.includes('Edg')) browser = 'Edge';
    return { device: isMobile ? 'Mobile' : 'Desktop', browser };
  };

  // ── Render helpers ─────────────────────────────────────────────
  const FeedbackBanner = ({ msg }: { msg: { type: 'success' | 'error'; text: string } | null }) => (
    <AnimatePresence>
      {msg && (
        <motion.div initial={{ opacity: 0, height: 0 }} animate={{ opacity: 1, height: 'auto' }} exit={{ opacity: 0, height: 0 }}
          className={`flex items-center gap-2 px-3 py-2 rounded-lg border text-xs ${
            msg.type === 'success' ? 'bg-success/10 border-success/25 text-success' : 'bg-danger/10 border-danger/25 text-danger'
          }`}>
          {msg.type === 'success' ? <CheckCircle2 className="w-3.5 h-3.5 shrink-0" /> : <AlertTriangle className="w-3.5 h-3.5 shrink-0" />}
          {msg.text}
        </motion.div>
      )}
    </AnimatePresence>
  );

  return (
    <div className="space-y-6">
      <motion.div initial={{ opacity: 0, y: -10 }} animate={{ opacity: 1, y: 0 }}>
        <h2 className="text-2xl font-bold text-foreground">Settings</h2>
        <p className="text-sm text-muted mt-1">Manage your account and platform configuration</p>
      </motion.div>

      <div className="flex gap-6">
        {/* ── Tab sidebar ─────────────────────────────────────── */}
        <div className="w-52 space-y-1">
          {tabs.map((tab) => {
            const Icon = tab.icon;
            return (
              <button
                key={tab.id}
                onClick={() => setActiveTab(tab.id)}
                className={`w-full flex items-center gap-2.5 px-3 py-2 rounded-lg text-sm transition-all cursor-pointer ${
                  activeTab === tab.id
                    ? 'bg-accent/15 text-accent-light border border-accent/20'
                    : 'text-muted hover:text-foreground hover:bg-surface-light border border-transparent'
                }`}
              >
                <Icon className="w-4 h-4" />
                <span className="font-medium">{tab.label}</span>
              </button>
            );
          })}

          <div className="pt-3 mt-3 border-t border-border">
            <button
              onClick={handleSignOut}
              className="w-full flex items-center gap-2.5 px-3 py-2 rounded-lg text-sm text-danger hover:bg-danger/10 transition-colors cursor-pointer"
            >
              <LogOut className="w-4 h-4" />
              <span className="font-medium">Sign Out</span>
            </button>
          </div>
        </div>

        {/* ── Content area ────────────────────────────────────── */}
        <div className="flex-1 glass rounded-xl p-6">

          {/* ════════════════ PROFILE ════════════════ */}
          {activeTab === 'profile' && (
            <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="space-y-6">
              <h3 className="text-base font-semibold text-foreground">Profile</h3>

              <div className="flex items-center gap-4">
                <div className="w-14 h-14 rounded-full gradient-accent flex items-center justify-center text-white text-lg font-bold shrink-0">
                  {(userData?.name || name || sessionUser?.name || 'U').charAt(0).toUpperCase()}
                </div>
                <div>
                  <p className="text-sm font-medium text-foreground">{userData?.name || sessionUser?.name || 'User'}</p>
                  <p className="text-xs text-muted">{userData?.email || sessionUser?.email || ''}</p>
                  {userData?.createdAt && (
                    <p className="text-[10px] text-accent-light mt-0.5">Member since {new Date(userData.createdAt).toLocaleDateString('en-GB', { month: 'short', year: 'numeric' })}</p>
                  )}
                </div>
              </div>

              <form onSubmit={handleSaveProfile} className="space-y-4">
                <FeedbackBanner msg={profileMsg} />
                <div className="grid grid-cols-2 gap-4">
                  <div>
                    <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">Full Name</label>
                    <div className="relative">
                      <User className="absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-foreground/60" />
                      <input type="text" value={name} onChange={e => setName(e.target.value)}
                        className="w-full glass-light rounded-lg pl-9 pr-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors" />
                    </div>
                  </div>
                  <div>
                    <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">Email</label>
                    <div className="relative">
                      <Mail className="absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-foreground/60" />
                      <input type="email" value={email} onChange={e => setEmail(e.target.value)}
                        className="w-full glass-light rounded-lg pl-9 pr-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors" />
                    </div>
                  </div>
                </div>
                <button type="submit" disabled={saving}
                  className="flex items-center gap-2 px-5 py-2 rounded-lg gradient-accent text-white text-sm font-semibold hover:opacity-90 transition-opacity cursor-pointer disabled:opacity-50">
                  {saving ? <Loader2 className="w-4 h-4 animate-spin" /> : <Save className="w-4 h-4" />}
                  Save Changes
                </button>
              </form>

              <div className="border-t border-border pt-5">
                <h4 className="text-sm font-semibold text-foreground mb-4 flex items-center gap-2">
                  <CheckCircle2 className="w-4 h-4 text-muted" />
                  Plan & Access
                </h4>
                <div className="grid grid-cols-3 gap-3">
                  <div className="glass-light rounded-lg p-4">
                    <p className="text-[10px] text-muted uppercase tracking-wider mb-1">Plan</p>
                    <p className="text-sm font-medium text-foreground capitalize">{capabilities.tier}</p>
                  </div>
                  <div className="glass-light rounded-lg p-4">
                    <p className="text-[10px] text-muted uppercase tracking-wider mb-1">Support SLA</p>
                    <p className="text-sm font-medium text-foreground">{capabilities.supportSla}</p>
                  </div>
                  <div className="glass-light rounded-lg p-4">
                    <p className="text-[10px] text-muted uppercase tracking-wider mb-1">Conversion quality report</p>
                    <p className="text-sm font-medium text-foreground">{capabilities.hasQualityReport ? 'Included' : 'Upgrade required'}</p>
                  </div>
                </div>
                <div className="grid grid-cols-2 gap-3 mt-4">
                  {([
                    ['Token dashboard', capabilities.hasTokenDashboard],
                    ['SSO', capabilities.hasSso],
                    ['SOC 2 / ISO 27001', capabilities.hasSoc2Iso27001],
                    ['EU AI Act', capabilities.hasEuAiAct],
                    ['Granular RBAC', capabilities.hasGranularRbac],
                    ['On-prem / air-gapped', capabilities.hasOnPrem],
                    ['Dedicated Slack/Teams', capabilities.hasDedicatedChannel],
                    ['Dedicated account manager', capabilities.hasAccountManager],
                  ] as Array<[string, boolean]>).map(([label, enabled]) => (
                    <div key={label} className="glass-light rounded-lg px-4 py-3 flex items-center justify-between">
                      <span className="text-xs text-foreground">{label}</span>
                      <span className={`text-[11px] font-medium ${enabled ? 'text-success' : 'text-muted'}`}>
                        {enabled ? 'Available' : 'Not in plan'}
                      </span>
                    </div>
                  ))}
                </div>
              </div>

              <div className="border-t border-border pt-5">
                <h4 className="text-sm font-semibold text-foreground mb-4 flex items-center gap-2">
                  <Lock className="w-4 h-4 text-muted" />
                  Change Password
                </h4>
                <form onSubmit={handleChangePassword} className="space-y-4">
                  <FeedbackBanner msg={pwdMsg} />
                  <div className="grid grid-cols-1 gap-3">
                    <div>
                      <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">Current Password</label>
                      <div className="relative">
                        <Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted" />
                        <input type={showCurrent ? 'text' : 'password'} value={currentPassword} onChange={e => setCurrentPassword(e.target.value)}
                          className="w-full glass-light rounded-lg pl-9 pr-9 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors" />
                        <button type="button" onClick={() => setShowCurrent(!showCurrent)} className="absolute right-2.5 top-1/2 -translate-y-1/2 text-muted hover:text-foreground cursor-pointer">
                          {showCurrent ? <EyeOff className="w-3.5 h-3.5" /> : <Eye className="w-3.5 h-3.5" />}
                        </button>
                      </div>
                    </div>
                    <div className="grid grid-cols-2 gap-3">
                      <div>
                        <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">New Password</label>
                        <div className="relative">
                          <Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted" />
                          <input type={showNew ? 'text' : 'password'} value={newPassword} onChange={e => setNewPassword(e.target.value)}
                            className="w-full glass-light rounded-lg pl-9 pr-9 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors" />
                          <button type="button" onClick={() => setShowNew(!showNew)} className="absolute right-2.5 top-1/2 -translate-y-1/2 text-muted hover:text-foreground cursor-pointer">
                            {showNew ? <EyeOff className="w-3.5 h-3.5" /> : <Eye className="w-3.5 h-3.5" />}
                          </button>
                        </div>
                      </div>
                      <div>
                        <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">Confirm Password</label>
                        <div className="relative">
                          <Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted" />
                          <input type="password" value={confirmPassword} onChange={e => setConfirmPassword(e.target.value)}
                            className="w-full glass-light rounded-lg pl-9 pr-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors" />
                        </div>
                      </div>
                    </div>
                  </div>
                  <button type="submit" disabled={changingPwd}
                    className="flex items-center gap-2 px-5 py-2 rounded-lg gradient-accent text-white text-sm font-semibold hover:opacity-90 transition-opacity cursor-pointer disabled:opacity-50">
                    {changingPwd ? <Loader2 className="w-4 h-4 animate-spin" /> : <Save className="w-4 h-4" />}
                    Update Password
                  </button>
                </form>
              </div>
            </motion.div>
          )}

          {/* ════════════════ SECURITY ════════════════ */}
          {activeTab === 'security' && (
            <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="space-y-6">
              <h3 className="text-base font-semibold text-foreground">Security</h3>

              {/* 2FA Section */}
              <TwoFASettings />

              {/* Account overview */}
              <div className="grid grid-cols-3 gap-4">
                <div className="glass-light rounded-lg p-4">
                  <p className="text-[10px] text-muted uppercase tracking-wider mb-1">Authentication</p>
                  <p className="text-sm font-medium text-foreground">{capabilities.hasSso ? 'Email + Password / SSO' : 'Email + Password'}</p>
                </div>
                <div className="glass-light rounded-lg p-4">
                  <p className="text-[10px] text-muted uppercase tracking-wider mb-1">GitHub</p>
                  <div className="flex items-center gap-1.5">
                    <div className={`w-2 h-2 rounded-full ${ghStatus?.connected ? 'bg-success' : 'bg-muted'}`} />
                    <p className="text-sm font-medium text-foreground">{ghStatus?.connected ? 'Connected' : 'Not connected'}</p>
                  </div>
                </div>
                <div className="glass-light rounded-lg p-4">
                  <p className="text-[10px] text-muted uppercase tracking-wider mb-1">RBAC</p>
                  <p className="text-sm font-medium text-foreground">{capabilities.hasGranularRbac ? 'Enterprise controls enabled' : 'Basic roles only'}</p>
                </div>
              </div>

              <div className="glass-light rounded-lg p-4">
                <h4 className="text-sm font-semibold text-foreground mb-3">Enterprise Security Options</h4>
                <div className="grid grid-cols-2 gap-3">
                  <div className="flex items-center justify-between">
                    <span className="text-xs text-foreground">SAML / Okta / Azure AD SSO</span>
                    <span className={`text-[11px] ${capabilities.hasSso ? 'text-success' : 'text-muted'}`}>{capabilities.hasSso ? 'Enabled' : 'Professional+'}</span>
                  </div>
                  <div className="flex items-center justify-between">
                    <span className="text-xs text-foreground">Granular RBAC</span>
                    <span className={`text-[11px] ${capabilities.hasGranularRbac ? 'text-success' : 'text-muted'}`}>{capabilities.hasGranularRbac ? 'Enabled' : 'Enterprise only'}</span>
                  </div>
                  <div className="flex items-center justify-between">
                    <span className="text-xs text-foreground">On-prem / air-gapped</span>
                    <span className={`text-[11px] ${capabilities.hasOnPrem ? 'text-success' : 'text-muted'}`}>{capabilities.hasOnPrem ? 'Enabled' : 'Enterprise only'}</span>
                  </div>
                  <div className="flex items-center justify-between">
                    <span className="text-xs text-foreground">Audit log package</span>
                    <span className="text-[11px] text-success">Included</span>
                  </div>
                </div>
              </div>

              {/* Active sessions */}
              <div>
                <div className="flex items-center justify-between mb-3">
                  <h4 className="text-sm font-semibold text-foreground flex items-center gap-2">
                    <Monitor className="w-4 h-4 text-muted" />
                    Active Sessions
                  </h4>
                  <div className="flex items-center gap-3">
                    {activeSessions.filter(s => !s.current).length > 0 && (
                      <button
                        onClick={handleRevokeAllSessions}
                        disabled={revokingAll}
                        className="flex items-center gap-1.5 text-xs text-danger hover:text-danger/80 disabled:opacity-50 cursor-pointer disabled:cursor-not-allowed transition-colors"
                      >
                        {revokingAll ? <Loader2 className="w-3 h-3 animate-spin" /> : <Trash2 className="w-3 h-3" />}
                        Revoke all others
                      </button>
                    )}
                    <button onClick={loadSessions} disabled={sessionsLoading} className="text-xs text-muted hover:text-foreground cursor-pointer">
                      {sessionsLoading ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : 'Refresh'}
                    </button>
                  </div>
                </div>

                {sessionsLoading && activeSessions.length === 0 ? (
                  <div className="flex items-center gap-3 py-6 justify-center">
                    <Loader2 className="w-5 h-5 animate-spin text-muted" />
                    <span className="text-sm text-muted">Loading sessions...</span>
                  </div>
                ) : (
                  <>
                    <div className="space-y-2">
                      {activeSessions.slice(sessionsPage * SESSIONS_PER_PAGE, (sessionsPage + 1) * SESSIONS_PER_PAGE).map(s => {
                        const { device, browser } = parseUA(s.userAgent);
                        const DeviceIcon = device === 'Mobile' ? Smartphone : device === 'CLI' ? Globe : Monitor;
                        return (
                          <div key={s.id} className={`glass-light rounded-lg p-4 flex items-center gap-4 ${s.current ? 'border border-accent/20' : ''}`}>
                            <DeviceIcon className="w-5 h-5 text-muted shrink-0" />
                            <div className="flex-1 min-w-0">
                              <div className="flex items-center gap-2">
                                <p className="text-sm font-medium text-foreground">{browser} on {device}</p>
                                {s.current && <span className="text-[10px] px-2 py-0.5 rounded-full bg-accent/15 text-accent-light font-medium">Current</span>}
                              </div>
                              <p className="text-[11px] text-muted">
                                IP: {s.ipAddress} · Created {new Date(s.createdAt).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' })}
                                {' · Expires '}{new Date(s.expiresAt).toLocaleDateString('en-GB', { day: 'numeric', month: 'short' })}
                              </p>
                            </div>
                            {!s.current && (
                              <button
                                onClick={() => handleRevokeSession(s.id)}
                                disabled={revokingSession === s.id}
                                className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-danger/30 text-danger text-xs font-medium hover:bg-danger/10 transition-colors cursor-pointer disabled:opacity-50"
                              >
                                {revokingSession === s.id ? <Loader2 className="w-3 h-3 animate-spin" /> : <Trash2 className="w-3 h-3" />}
                                Revoke
                              </button>
                            )}
                          </div>
                        );
                      })}
                    </div>

                    {activeSessions.length > SESSIONS_PER_PAGE && (
                      <div className="flex items-center justify-between mt-3 pt-3 border-t border-border/40">
                        <span className="text-[11px] text-muted">
                          {sessionsPage * SESSIONS_PER_PAGE + 1}–{Math.min((sessionsPage + 1) * SESSIONS_PER_PAGE, activeSessions.length)} of {activeSessions.length} sessions
                        </span>
                        <div className="flex items-center gap-1">
                          <button
                            onClick={() => setSessionsPage(p => p - 1)}
                            disabled={sessionsPage === 0}
                            className="px-2.5 py-1 rounded-md text-xs text-muted hover:text-foreground hover:bg-surface-elevated transition-colors disabled:opacity-30 disabled:cursor-not-allowed cursor-pointer"
                          >
                            ← Prev
                          </button>
                          {Array.from({ length: Math.ceil(activeSessions.length / SESSIONS_PER_PAGE) }, (_, i) => (
                            <button
                              key={i}
                              onClick={() => setSessionsPage(i)}
                              className={`w-6 h-6 rounded-md text-xs font-medium transition-colors cursor-pointer ${i === sessionsPage ? 'bg-accent/20 text-accent-light' : 'text-muted hover:text-foreground hover:bg-surface-elevated'}`}
                            >
                              {i + 1}
                            </button>
                          ))}
                          <button
                            onClick={() => setSessionsPage(p => p + 1)}
                            disabled={sessionsPage >= Math.ceil(activeSessions.length / SESSIONS_PER_PAGE) - 1}
                            className="px-2.5 py-1 rounded-md text-xs text-muted hover:text-foreground hover:bg-surface-elevated transition-colors disabled:opacity-30 disabled:cursor-not-allowed cursor-pointer"
                          >
                            Next →
                          </button>
                        </div>
                      </div>
                    )}
                  </>
                )}
              </div>

              {/* Security headers info */}
              <div className="glass-light rounded-lg p-4">
                <h4 className="text-sm font-semibold text-foreground mb-3">Platform Security</h4>
                <div className="grid grid-cols-2 gap-3">
                  {[
                    { label: 'Content-Security-Policy', ok: true },
                    { label: 'HTTP Strict Transport Security', ok: true },
                    { label: 'X-Frame-Options: DENY', ok: true },
                    { label: 'Rate Limiting (auth)', ok: true },
                    { label: 'Input Validation (Zod)', ok: true },
                    { label: 'Session: httpOnly cookie', ok: true },
                  ].map(item => (
                    <div key={item.label} className="flex items-center gap-2">
                      <CheckCircle2 className="w-3.5 h-3.5 text-success shrink-0" />
                      <span className="text-xs text-foreground">{item.label}</span>
                    </div>
                  ))}
                </div>
              </div>
            </motion.div>
          )}

          {/* ════════════════ CONNECTIONS ════════════════ */}
          {activeTab === 'github' && (
            <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="space-y-5">
              <div>
                <h3 className="text-base font-semibold text-foreground">Git Provider Connections</h3>
                <p className="text-sm text-muted mt-1">Connect your accounts to browse and access repositories for migrations.</p>
              </div>

              {/* Provider sub-tabs */}
              <div className="flex gap-1 p-1 bg-surface rounded-lg">
                {([
                  { id: 'github', label: 'GitHub', icon: '🐙' },
                  { id: 'gitlab', label: 'GitLab', icon: '🦊' },
                  { id: 'azure', label: 'Azure DevOps', icon: '🔷' },
                  { id: 'bitbucket', label: 'Bitbucket', icon: '🪣' },
                ] as const).map(p => (
                  <button
                    key={p.id}
                    onClick={() => setProviderSubTab(p.id)}
                    className={`flex-1 py-1.5 px-2 text-xs font-medium rounded-md transition-colors cursor-pointer flex items-center justify-center gap-1.5 ${
                      providerSubTab === p.id ? 'bg-accent text-white shadow-sm' : 'text-muted hover:text-foreground'
                    }`}
                  >
                    <span>{p.icon}</span>
                    <span className="hidden sm:inline">{p.label}</span>
                  </button>
                ))}
              </div>

              {/* ── GitHub ── */}
              {providerSubTab === 'github' && (
                <div className="space-y-4">
                  {ghLoading ? (
                    <div className="flex items-center gap-3 py-4">
                      <Loader2 className="w-5 h-5 animate-spin text-muted" />
                      <span className="text-sm text-muted">Checking connection...</span>
                    </div>
                  ) : ghStatus?.connected ? (
                    <div className="space-y-4">
                      <div className="glass-light rounded-xl p-5 flex items-center gap-4">
                        {ghStatus.avatar ? (
                          <img src={ghStatus.avatar} alt={ghStatus.login} className="w-12 h-12 rounded-full" />
                        ) : (
                          <div className="w-12 h-12 rounded-full bg-surface flex items-center justify-center">
                            <GitBranch className="w-6 h-6 text-muted" />
                          </div>
                        )}
                        <div className="flex-1">
                          <div className="flex items-center gap-2">
                            <p className="text-sm font-semibold text-foreground">{ghStatus.name || ghStatus.login}</p>
                            <span className="text-[10px] px-2 py-0.5 rounded-full bg-success/15 text-success font-medium">Connected</span>
                          </div>
                          {ghStatus.url && <a href={ghStatus.url} target="_blank" rel="noopener noreferrer" className="text-xs text-accent-light hover:underline">@{ghStatus.login}</a>}
                        </div>
                        <button onClick={handleGhDisconnect} disabled={ghDisconnecting}
                          className="flex items-center gap-2 px-4 py-2 rounded-lg border border-danger/30 text-danger text-xs font-semibold hover:bg-danger/10 transition-colors cursor-pointer disabled:opacity-50">
                          {ghDisconnecting ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Link2Off className="w-3.5 h-3.5" />}
                          Disconnect
                        </button>
                      </div>
                      <div className="glass-light rounded-lg p-4">
                        <p className="text-[11px] text-muted uppercase tracking-wider mb-2">Granted scopes</p>
                        <div className="flex gap-2 flex-wrap">
                          {['read:user', 'repo'].map(s => (
                            <span key={s} className="text-xs px-2.5 py-1 rounded-full bg-accent/10 text-accent-light font-medium">{s}</span>
                          ))}
                        </div>
                      </div>
                    </div>
                  ) : (
                    <div className="glass-light rounded-xl p-6 flex flex-col items-center text-center gap-4">
                      <div className="w-14 h-14 rounded-full bg-surface flex items-center justify-center">
                        <GitBranch className="w-7 h-7 text-muted" />
                      </div>
                      <div>
                        <p className="text-sm font-medium text-foreground">No GitHub account connected</p>
                        <p className="text-xs text-muted mt-1">Connect to access private repositories and enable automated migrations.</p>
                      </div>
                      {oauthConfigured && (
                        <a href="/api/auth/github" className="flex items-center gap-2 px-5 py-2.5 gradient-accent text-white rounded-lg text-sm font-semibold hover:opacity-90 transition-opacity">
                          <Link2 className="w-4 h-4" />Connect GitHub
                        </a>
                      )}
                    </div>
                  )}
                  {!ghLoading && (
                    <div className="glass-light rounded-xl p-5 space-y-3">
                      <div className="flex items-center justify-between">
                        <div>
                          <p className="text-sm font-medium text-foreground">Personal Access Token</p>
                          <p className="text-xs text-muted mt-0.5">
                            {oauthConfigured ? 'Use a PAT to access private org repos without OAuth app approval.' : 'Paste a GitHub token — no app configuration needed.'}
                          </p>
                        </div>
                        {oauthConfigured && (
                          <button onClick={() => { setShowPat(v => !v); setPatMsg(null); }} className="text-xs text-accent-light hover:text-accent font-medium cursor-pointer">
                            {showPat ? 'Cancel' : 'Use PAT'}
                          </button>
                        )}
                      </div>
                      {(showPat || !oauthConfigured) && (
                        <div className="space-y-2">
                          <p className="text-[11px] text-muted">Generate a <a href="https://github.com/settings/tokens/new?scopes=repo&description=Scriba" target="_blank" rel="noopener noreferrer" className="text-accent-light hover:underline">classic token with <code className="bg-surface px-1 rounded">repo</code> scope</a> on GitHub, then paste it below.</p>
                          <div className="flex gap-2">
                            <input type="password" value={patValue} onChange={e => setPatValue(e.target.value)} placeholder="ghp_••••••••••••••••••••••••••••••••••••" className="flex-1 bg-surface rounded-lg px-3 py-2 text-xs text-foreground outline-none border border-transparent focus:border-accent/40 font-mono" />
                            <button onClick={handlePatSave} disabled={patSaving || !patValue.trim()} className="px-4 py-2 rounded-lg gradient-accent text-white text-xs font-semibold hover:opacity-90 transition-opacity disabled:opacity-50 cursor-pointer">
                              {patSaving ? 'Saving…' : 'Save'}
                            </button>
                          </div>
                          {patMsg && <p className={`text-xs ${patMsg.type === 'success' ? 'text-success' : 'text-danger'}`}>{patMsg.text}</p>}
                        </div>
                      )}
                    </div>
                  )}
                </div>
              )}

              {/* ── GitLab ── */}
              {providerSubTab === 'gitlab' && (
                <div className="space-y-4">
                  {glLoading ? (
                    <div className="flex items-center gap-3 py-4"><Loader2 className="w-5 h-5 animate-spin text-muted" /><span className="text-sm text-muted">Checking connection...</span></div>
                  ) : glStatus?.connected ? (
                    <div className="space-y-4">
                      <div className="glass-light rounded-xl p-5 flex items-center gap-4">
                        {glStatus.avatar ? (
                          <img src={glStatus.avatar} alt={glStatus.login} className="w-12 h-12 rounded-full" />
                        ) : (
                          <div className="w-12 h-12 rounded-full bg-surface flex items-center justify-center text-xl">🦊</div>
                        )}
                        <div className="flex-1">
                          <div className="flex items-center gap-2">
                            <p className="text-sm font-semibold text-foreground">{glStatus.name || glStatus.login}</p>
                            <span className="text-[10px] px-2 py-0.5 rounded-full bg-success/15 text-success font-medium">Connected</span>
                          </div>
                          {glStatus.url && <a href={glStatus.url} target="_blank" rel="noopener noreferrer" className="text-xs text-accent-light hover:underline">@{glStatus.login}</a>}
                        </div>
                        <button onClick={handleGlDisconnect} disabled={glDisconnecting}
                          className="flex items-center gap-2 px-4 py-2 rounded-lg border border-danger/30 text-danger text-xs font-semibold hover:bg-danger/10 transition-colors cursor-pointer disabled:opacity-50">
                          {glDisconnecting ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Link2Off className="w-3.5 h-3.5" />}Disconnect
                        </button>
                      </div>
                      <div className="glass-light rounded-lg p-4">
                        <p className="text-[11px] text-muted uppercase tracking-wider mb-2">Granted scopes</p>
                        <div className="flex gap-2 flex-wrap">
                          {['read_user', 'read_api', 'read_repository'].map(s => (
                            <span key={s} className="text-xs px-2.5 py-1 rounded-full bg-accent/10 text-accent-light font-medium">{s}</span>
                          ))}
                        </div>
                      </div>
                    </div>
                  ) : (
                    <div className="glass-light rounded-xl p-6 flex flex-col items-center text-center gap-4">
                      <div className="w-14 h-14 rounded-full bg-surface flex items-center justify-center text-2xl">🦊</div>
                      <div>
                        <p className="text-sm font-medium text-foreground">No GitLab account connected</p>
                        <p className="text-xs text-muted mt-1">Connect to access GitLab repositories for migrations.</p>
                      </div>
                      {glOauthConfigured && (
                        <a href="/api/auth/gitlab" className="flex items-center gap-2 px-5 py-2.5 gradient-accent text-white rounded-lg text-sm font-semibold hover:opacity-90 transition-opacity">
                          <Link2 className="w-4 h-4" />Connect GitLab
                        </a>
                      )}
                    </div>
                  )}
                  {!glLoading && (
                    <div className="glass-light rounded-xl p-5 space-y-3">
                      <div className="flex items-center justify-between">
                        <div>
                          <p className="text-sm font-medium text-foreground">Personal Access Token</p>
                          <p className="text-xs text-muted mt-0.5">
                            {glOauthConfigured ? 'Use a PAT as an alternative to OAuth.' : 'Paste a GitLab token to connect — no app configuration needed.'}
                          </p>
                        </div>
                        {glOauthConfigured && (
                          <button onClick={() => { setGlShowPat(v => !v); setGlPatMsg(null); }} className="text-xs text-accent-light hover:text-accent font-medium cursor-pointer">
                            {glShowPat ? 'Cancel' : 'Use PAT'}
                          </button>
                        )}
                      </div>
                      {(glShowPat || !glOauthConfigured) && (
                        <div className="space-y-2">
                          <p className="text-[11px] text-muted">Generate a <a href="https://gitlab.com/-/user_settings/personal_access_tokens" target="_blank" rel="noopener noreferrer" className="text-accent-light hover:underline">Personal Access Token with <code className="bg-surface px-1 rounded">read_api</code> scope</a> on GitLab, then paste it below.</p>
                          <div className="flex gap-2">
                            <input type="password" value={glPatValue} onChange={e => setGlPatValue(e.target.value)} placeholder="glpat-••••••••••••••••••••" className="flex-1 bg-surface rounded-lg px-3 py-2 text-xs text-foreground outline-none border border-transparent focus:border-accent/40 font-mono" />
                            <button onClick={handleGlPatSave} disabled={glPatSaving || !glPatValue.trim()} className="px-4 py-2 rounded-lg gradient-accent text-white text-xs font-semibold hover:opacity-90 transition-opacity disabled:opacity-50 cursor-pointer">
                              {glPatSaving ? 'Saving…' : 'Save'}
                            </button>
                          </div>
                          {glPatMsg && <p className={`text-xs ${glPatMsg.type === 'success' ? 'text-success' : 'text-danger'}`}>{glPatMsg.text}</p>}
                        </div>
                      )}
                    </div>
                  )}
                </div>
              )}

              {/* ── Azure DevOps ── */}
              {providerSubTab === 'azure' && (
                <div className="space-y-4">
                  {azLoading ? (
                    <div className="flex items-center gap-3 py-4"><Loader2 className="w-5 h-5 animate-spin text-muted" /><span className="text-sm text-muted">Checking connection...</span></div>
                  ) : azStatus?.connected ? (
                    <div className="space-y-4">
                      <div className="glass-light rounded-xl p-5 flex items-center gap-4">
                        <div className="w-12 h-12 rounded-full bg-surface flex items-center justify-center text-xl">🔷</div>
                        <div className="flex-1">
                          <div className="flex items-center gap-2">
                            <p className="text-sm font-semibold text-foreground">{azStatus.name || azStatus.login}</p>
                            <span className="text-[10px] px-2 py-0.5 rounded-full bg-success/15 text-success font-medium">Connected</span>
                          </div>
                          <p className="text-xs text-muted">{azStatus.login}</p>
                        </div>
                        <button onClick={handleAzDisconnect} disabled={azDisconnecting}
                          className="flex items-center gap-2 px-4 py-2 rounded-lg border border-danger/30 text-danger text-xs font-semibold hover:bg-danger/10 transition-colors cursor-pointer disabled:opacity-50">
                          {azDisconnecting ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Link2Off className="w-3.5 h-3.5" />}Disconnect
                        </button>
                      </div>
                    </div>
                  ) : (
                    <div className="glass-light rounded-xl p-6 flex flex-col items-center text-center gap-4">
                      <div className="w-14 h-14 rounded-full bg-surface flex items-center justify-center text-2xl">🔷</div>
                      <div>
                        <p className="text-sm font-medium text-foreground">No Azure DevOps account connected</p>
                        <p className="text-xs text-muted mt-1">Connect using a Personal Access Token to access Azure DevOps repositories.</p>
                      </div>
                    </div>
                  )}
                  {!azLoading && (
                    <div className="glass-light rounded-xl p-5 space-y-3">
                      <div className="flex items-center justify-between">
                        <div>
                          <p className="text-sm font-medium text-foreground">Personal Access Token</p>
                          <p className="text-xs text-muted mt-0.5">Paste an Azure DevOps PAT with Code (Read) scope.</p>
                        </div>
                        {azStatus?.connected && (
                          <button onClick={() => { setAzShowPat(v => !v); setAzPatMsg(null); }} className="text-xs text-accent-light hover:text-accent font-medium cursor-pointer">
                            {azShowPat ? 'Cancel' : 'Update PAT'}
                          </button>
                        )}
                      </div>
                      {(azShowPat || !azStatus?.connected) && (
                        <div className="space-y-2">
                          <p className="text-[11px] text-muted">Generate a <a href="https://dev.azure.com" target="_blank" rel="noopener noreferrer" className="text-accent-light hover:underline">PAT in Azure DevOps</a> under User Settings → Personal Access Tokens with <code className="bg-surface px-1 rounded">Code (Read)</code> scope.</p>
                          <div className="flex gap-2">
                            <input type="password" value={azPatValue} onChange={e => setAzPatValue(e.target.value)} placeholder="Azure DevOps PAT" className="flex-1 bg-surface rounded-lg px-3 py-2 text-xs text-foreground outline-none border border-transparent focus:border-accent/40 font-mono" />
                            <button onClick={handleAzPatSave} disabled={azPatSaving || !azPatValue.trim()} className="px-4 py-2 rounded-lg gradient-accent text-white text-xs font-semibold hover:opacity-90 transition-opacity disabled:opacity-50 cursor-pointer">
                              {azPatSaving ? 'Saving…' : 'Save'}
                            </button>
                          </div>
                          {azPatMsg && <p className={`text-xs ${azPatMsg.type === 'success' ? 'text-success' : 'text-danger'}`}>{azPatMsg.text}</p>}
                        </div>
                      )}
                    </div>
                  )}
                </div>
              )}

              {/* ── Bitbucket ── */}
              {providerSubTab === 'bitbucket' && (
                <div className="space-y-4">
                  {bbLoading ? (
                    <div className="flex items-center gap-3 py-4"><Loader2 className="w-5 h-5 animate-spin text-muted" /><span className="text-sm text-muted">Checking connection...</span></div>
                  ) : bbStatus?.connected ? (
                    <div className="space-y-4">
                      <div className="glass-light rounded-xl p-5 flex items-center gap-4">
                        {bbStatus.avatar ? (
                          <img src={bbStatus.avatar} alt={bbStatus.login} className="w-12 h-12 rounded-full" />
                        ) : (
                          <div className="w-12 h-12 rounded-full bg-surface flex items-center justify-center text-xl">🪣</div>
                        )}
                        <div className="flex-1">
                          <div className="flex items-center gap-2">
                            <p className="text-sm font-semibold text-foreground">{bbStatus.name || bbStatus.login}</p>
                            <span className="text-[10px] px-2 py-0.5 rounded-full bg-success/15 text-success font-medium">Connected</span>
                          </div>
                          {bbStatus.url && <a href={bbStatus.url} target="_blank" rel="noopener noreferrer" className="text-xs text-accent-light hover:underline">@{bbStatus.login}</a>}
                        </div>
                        <button onClick={handleBbDisconnect} disabled={bbDisconnecting}
                          className="flex items-center gap-2 px-4 py-2 rounded-lg border border-danger/30 text-danger text-xs font-semibold hover:bg-danger/10 transition-colors cursor-pointer disabled:opacity-50">
                          {bbDisconnecting ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Link2Off className="w-3.5 h-3.5" />}Disconnect
                        </button>
                      </div>
                    </div>
                  ) : (
                    <div className="glass-light rounded-xl p-6 flex flex-col items-center text-center gap-4">
                      <div className="w-14 h-14 rounded-full bg-surface flex items-center justify-center text-2xl">🪣</div>
                      <div>
                        <p className="text-sm font-medium text-foreground">No Bitbucket account connected</p>
                        <p className="text-xs text-muted mt-1">Connect to access Bitbucket repositories for migrations.</p>
                      </div>
                      {bbOauthConfigured && (
                        <a href="/api/auth/bitbucket" className="flex items-center gap-2 px-5 py-2.5 gradient-accent text-white rounded-lg text-sm font-semibold hover:opacity-90 transition-opacity">
                          <Link2 className="w-4 h-4" />Connect Bitbucket
                        </a>
                      )}
                    </div>
                  )}
                  {!bbLoading && (
                    <div className="glass-light rounded-xl p-5 space-y-3">
                      <div className="flex items-center justify-between">
                        <div>
                          <p className="text-sm font-medium text-foreground">HTTP Access Token</p>
                          <p className="text-xs text-muted mt-0.5">
                            {bbOauthConfigured ? 'Use a token as an alternative to OAuth.' : 'Paste a Bitbucket HTTP access token or username:app_password.'}
                          </p>
                        </div>
                        {bbOauthConfigured && (
                          <button onClick={() => { setBbShowPat(v => !v); setBbPatMsg(null); }} className="text-xs text-accent-light hover:text-accent font-medium cursor-pointer">
                            {bbShowPat ? 'Cancel' : 'Use Token'}
                          </button>
                        )}
                      </div>
                      {(bbShowPat || !bbOauthConfigured) && (
                        <div className="space-y-2">
                          <p className="text-[11px] text-muted">Generate an <a href="https://bitbucket.org/account/settings/app-passwords/" target="_blank" rel="noopener noreferrer" className="text-accent-light hover:underline">HTTP access token</a> in Bitbucket workspace settings, or use <code className="bg-surface px-1 rounded">username:app_password</code> format.</p>
                          <div className="flex gap-2">
                            <input type="password" value={bbPatValue} onChange={e => setBbPatValue(e.target.value)} placeholder="HTTP access token or username:app_password" className="flex-1 bg-surface rounded-lg px-3 py-2 text-xs text-foreground outline-none border border-transparent focus:border-accent/40 font-mono" />
                            <button onClick={handleBbPatSave} disabled={bbPatSaving || !bbPatValue.trim()} className="px-4 py-2 rounded-lg gradient-accent text-white text-xs font-semibold hover:opacity-90 transition-opacity disabled:opacity-50 cursor-pointer">
                              {bbPatSaving ? 'Saving…' : 'Save'}
                            </button>
                          </div>
                          {bbPatMsg && <p className={`text-xs ${bbPatMsg.type === 'success' ? 'text-success' : 'text-danger'}`}>{bbPatMsg.text}</p>}
                        </div>
                      )}
                    </div>
                  )}
                </div>
              )}
            </motion.div>
          )}

          {/* ════════════════ ENGINE ════════════════ */}
          {activeTab === 'engine' && (
            <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="space-y-6">
              <div className="flex items-center justify-between">
                <h3 className="text-base font-semibold text-foreground">Translation Engine</h3>
                <div className="flex items-center gap-2">
                  {engineLoading ? (
                    <Loader2 className="w-4 h-4 animate-spin text-muted" />
                  ) : engineError ? (
                    <span className="flex items-center gap-1.5 text-xs text-danger">
                      <WifiOff className="w-3.5 h-3.5" /> Offline
                    </span>
                  ) : engineStatus ? (
                    <span className="flex items-center gap-1.5 text-xs text-success">
                      <Wifi className="w-3.5 h-3.5" /> Connected
                    </span>
                  ) : null}
                  <button
                    onClick={() => { setEngineStatus(null); setEngineError(false); }}
                    className="text-xs text-muted hover:text-foreground cursor-pointer"
                  >
                    Refresh
                  </button>
                </div>
              </div>

              {engineLoading ? (
                <div className="flex items-center gap-3 py-8 justify-center">
                  <Loader2 className="w-5 h-5 animate-spin text-muted" />
                  <span className="text-sm text-muted">Connecting to engine...</span>
                </div>
              ) : engineError ? (
                <div className="glass-light rounded-xl p-6 flex flex-col items-center text-center gap-3">
                  <div className="w-14 h-14 rounded-full bg-danger/10 flex items-center justify-center">
                    <WifiOff className="w-7 h-7 text-danger" />
                  </div>
                  <div>
                    <p className="text-sm font-medium text-foreground">Engine not reachable</p>
                    <p className="text-xs text-muted mt-1">
                      The Scriba Engine is not responding. Make sure it is running and <code className="text-accent-light">SCRIBA_ENGINE_URL</code> is set correctly.
                    </p>
                  </div>
                  <button
                    onClick={() => { setEngineStatus(null); setEngineLanguages(null); setEngineError(false); }}
                    className="flex items-center gap-2 px-4 py-2 rounded-lg border border-border text-sm text-foreground hover:bg-surface-light cursor-pointer transition-colors"
                  >
                    <Wifi className="w-4 h-4" />
                    Retry Connection
                  </button>
                </div>
              ) : engineStatus ? (
                <>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="glass-light rounded-lg p-4">
                      <p className="text-[10px] text-muted uppercase tracking-wider mb-1">Status</p>
                      <p className="text-sm font-medium text-success capitalize">{engineStatus.status}</p>
                    </div>
                    <div className="glass-light rounded-lg p-4">
                      <p className="text-[10px] text-muted uppercase tracking-wider mb-1">Version</p>
                      <p className="text-sm font-medium text-foreground">{engineStatus.version || 'Unknown'}</p>
                    </div>
                    {engineStatus.uptime !== undefined && (
                      <div className="glass-light rounded-lg p-4">
                        <p className="text-[10px] text-muted uppercase tracking-wider mb-1">Uptime</p>
                        <p className="text-sm font-medium text-foreground">{Math.floor(engineStatus.uptime / 3600)}h {Math.floor((engineStatus.uptime % 3600) / 60)}m</p>
                      </div>
                    )}
                  </div>

                  {(() => {
                    const langs = normalizeEngineLanguages(engineStatus.languages) ?? engineLanguages;
                    if (!langs || (langs.source.length === 0 && langs.target.length === 0)) {
                      return (
                        <p className="text-xs text-muted">
                          No language catalog returned yet. Ensure the Scriba Engine is running and{' '}
                          <code className="text-accent-light">SCRIBA_ENGINE_URL</code> points to it so{' '}
                          <code className="text-accent-light">GET /scriba/languages</code> can load the list.
                        </p>
                      );
                    }
                    return (
                      <>
                        <div className="glass-light rounded-lg p-4">
                          <p className="text-sm font-medium text-foreground mb-2">Source Languages</p>
                          <div className="flex flex-wrap gap-2">
                            {langs.source.map(l => (
                              <span key={l} className="text-xs px-2.5 py-1 rounded-full bg-accent/10 text-accent-light font-medium">{l}</span>
                            ))}
                          </div>
                        </div>
                        <div className="glass-light rounded-lg p-4">
                          <p className="text-sm font-medium text-foreground mb-2">Target Languages</p>
                          <div className="flex flex-wrap gap-2">
                            {langs.target.map(l => (
                              <span key={l} className="text-xs px-2.5 py-1 rounded-full bg-success/10 text-success font-medium">{l}</span>
                            ))}
                          </div>
                        </div>
                      </>
                    );
                  })()}
                </>
              ) : null}

              {/* §12.1 — Knowledge Base CRUD (opt-in, hidden when engine returns 503) */}
              {kbEnabled && (
                <div className="glass-light rounded-xl p-5 space-y-4">
                  <div className="flex items-center justify-between">
                    <div>
                      <p className="text-sm font-medium text-foreground">Knowledge Base</p>
                      <p className="text-[11px] text-muted mt-0.5">Style guides, naming conventions, and decision rules injected into translations.</p>
                    </div>
                    <button
                      onClick={() => { setKbAddOpen(o => !o); setKbError(''); }}
                      className="flex items-center gap-1.5 text-xs font-medium px-3 py-1.5 rounded-lg border border-border hover:bg-surface-light transition-colors cursor-pointer text-foreground"
                    >
                      <Plus className="w-3.5 h-3.5" />
                      Add doc
                    </button>
                  </div>

                  {/* Search */}
                  <div className="flex gap-2">
                    <input
                      type="text"
                      value={kbSearchQ}
                      onChange={e => { setKbSearchQ(e.target.value); if (!e.target.value.trim()) setKbSearchResults(null); }}
                      onKeyDown={e => e.key === 'Enter' && handleKbSearch()}
                      placeholder="Search knowledge base…"
                      className="flex-1 text-xs px-3 py-2 rounded-lg border border-border bg-transparent text-foreground placeholder:text-muted focus:outline-none focus:ring-1 focus:ring-accent"
                    />
                    <button
                      onClick={handleKbSearch}
                      className="text-xs px-3 py-2 rounded-lg border border-border hover:bg-surface-light transition-colors cursor-pointer text-foreground"
                    >
                      Search
                    </button>
                    {kbSearchResults !== null && (
                      <button
                        onClick={() => setKbSearchResults(null)}
                        className="text-xs px-2 py-2 rounded-lg border border-border hover:bg-surface-light transition-colors cursor-pointer text-muted"
                      >
                        <X className="w-3.5 h-3.5" />
                      </button>
                    )}
                  </div>

                  {/* Add form */}
                  {kbAddOpen && (
                    <div className="space-y-3 p-4 rounded-lg border border-border bg-surface/40">
                      <div className="flex gap-3">
                        <div className="flex-1">
                          <label className="text-[10px] text-muted uppercase tracking-wider">Kind</label>
                          <select
                            value={kbNewKind}
                            onChange={e => setKbNewKind(e.target.value)}
                            className="w-full mt-1 text-xs px-2 py-1.5 rounded-lg border border-border bg-transparent text-foreground focus:outline-none"
                          >
                            {['style-guide', 'dependency-list', 'naming-convention', 'decision', 'other'].map(k => (
                              <option key={k} value={k}>{k}</option>
                            ))}
                          </select>
                        </div>
                        <div className="flex-[2]">
                          <label className="text-[10px] text-muted uppercase tracking-wider">Title</label>
                          <input
                            type="text"
                            value={kbNewTitle}
                            onChange={e => setKbNewTitle(e.target.value)}
                            placeholder="Java naming conventions…"
                            className="w-full mt-1 text-xs px-2 py-1.5 rounded-lg border border-border bg-transparent text-foreground placeholder:text-muted focus:outline-none focus:ring-1 focus:ring-accent"
                          />
                        </div>
                      </div>
                      <div>
                        <label className="text-[10px] text-muted uppercase tracking-wider">Content (markdown)</label>
                        <textarea
                          value={kbNewContent}
                          onChange={e => setKbNewContent(e.target.value)}
                          rows={5}
                          placeholder="Classes PascalCase, methods camelCase…"
                          className="w-full mt-1 text-xs px-3 py-2 rounded-lg border border-border bg-transparent text-foreground placeholder:text-muted focus:outline-none focus:ring-1 focus:ring-accent resize-y font-mono"
                        />
                      </div>
                      <div className="flex items-center gap-2 justify-end">
                        <button
                          onClick={() => { setKbAddOpen(false); setKbNewTitle(''); setKbNewContent(''); setKbError(''); }}
                          className="text-xs px-3 py-1.5 rounded-lg border border-border hover:bg-surface-light cursor-pointer text-muted"
                        >Cancel</button>
                        <button
                          onClick={handleKbAdd}
                          disabled={kbAddLoading || !kbNewTitle.trim() || !kbNewContent.trim()}
                          className="flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-lg bg-accent text-white hover:bg-accent/90 disabled:opacity-50 cursor-pointer transition-colors"
                        >
                          {kbAddLoading ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Save className="w-3.5 h-3.5" />}
                          Save
                        </button>
                      </div>
                    </div>
                  )}

                  {kbError && <p className="text-xs text-danger">{kbError}</p>}

                  {/* Doc list (search results or full list) */}
                  {kbLoading ? (
                    <div className="flex items-center gap-2 text-xs text-muted py-2">
                      <Loader2 className="w-3.5 h-3.5 animate-spin" /> Loading…
                    </div>
                  ) : (kbSearchResults ?? kbDocs).length === 0 ? (
                    <p className="text-xs text-muted py-1">{kbSearchResults !== null ? 'No results.' : 'No documents yet.'}</p>
                  ) : (
                    <ul className="space-y-2">
                      {(kbSearchResults ?? kbDocs).map(doc => (
                        <li key={doc.docId} className="flex items-center justify-between gap-3 px-3 py-2.5 rounded-lg border border-border bg-surface/30">
                          <div className="min-w-0">
                            <p className="text-xs font-medium text-foreground truncate">{doc.title}</p>
                            <p className="text-[10px] text-muted">{doc.kind}</p>
                          </div>
                          <button
                            onClick={() => handleKbRemove(doc.docId)}
                            className="shrink-0 text-muted hover:text-danger cursor-pointer transition-colors"
                            title="Remove"
                          >
                            <Trash2 className="w-3.5 h-3.5" />
                          </button>
                        </li>
                      ))}
                    </ul>
                  )}
                </div>
              )}

              {/* §12.2 — Dataset upload (opt-in, hidden when engine returns 503) */}
              {datasetEnabled && (
                <div className="glass-light rounded-xl p-5 space-y-4">
                  <div className="flex items-center justify-between">
                    <div>
                      <p className="text-sm font-medium text-foreground">Replay Datasets</p>
                      <p className="text-[11px] text-muted mt-0.5">Upload real I/O dumps for equivalence testing. Stored encrypted engine-side.</p>
                    </div>
                    <label className="flex items-center gap-1.5 text-xs font-medium px-3 py-1.5 rounded-lg border border-border hover:bg-surface-light transition-colors cursor-pointer text-foreground">
                      {datasetAddLoading ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Plus className="w-3.5 h-3.5" />}
                      Upload
                      <input type="file" className="hidden" onChange={handleDatasetUpload} disabled={datasetAddLoading} />
                    </label>
                  </div>

                  {datasetError && <p className="text-xs text-danger">{datasetError}</p>}

                  {datasetLoading ? (
                    <div className="flex items-center gap-2 text-xs text-muted py-2">
                      <Loader2 className="w-3.5 h-3.5 animate-spin" /> Loading…
                    </div>
                  ) : datasets.length === 0 ? (
                    <p className="text-xs text-muted py-1">No datasets uploaded yet.</p>
                  ) : (
                    <ul className="space-y-2">
                      {datasets.map(ds => (
                        <li key={ds.datasetId} className="flex items-center justify-between gap-3 px-3 py-2.5 rounded-lg border border-border bg-surface/30">
                          <div className="min-w-0">
                            <p className="text-xs font-medium text-foreground font-mono truncate">{ds.datasetId}</p>
                            {ds.size !== undefined && <p className="text-[10px] text-muted">{(ds.size / 1024).toFixed(1)} KB</p>}
                          </div>
                          <button
                            onClick={() => handleDatasetRemove(ds.datasetId)}
                            className="shrink-0 text-muted hover:text-danger cursor-pointer transition-colors"
                            title="Remove"
                          >
                            <Trash2 className="w-3.5 h-3.5" />
                          </button>
                        </li>
                      ))}
                    </ul>
                  )}
                </div>
              )}

              {/* §1 — Scalar interactive API docs (admin/dev DX link) */}
              <div className="glass-light rounded-xl p-4 flex items-center justify-between">
                <div>
                  <p className="text-sm font-medium text-foreground">Interactive API Docs (Scalar)</p>
                  <p className="text-[11px] text-muted mt-0.5">
                    Browse and try all engine endpoints live. Only available when the engine is running.
                  </p>
                </div>
                <a
                  href={`${typeof window !== 'undefined' ? '' : 'http://localhost:3100'}/api/engine/docs`}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="flex items-center gap-1.5 text-xs font-medium text-accent-light hover:underline cursor-pointer"
                >
                  <Globe className="w-3.5 h-3.5" />
                  Open Scalar UI
                </a>
              </div>

              {/* ML01 §7 — Webhook admin */}
              <div className="glass-light rounded-xl p-4 space-y-4">
                <div>
                  <p className="text-sm font-medium text-foreground">Webhook Configuration</p>
                  <p className="text-[11px] text-muted mt-0.5">
                    The engine posts to this URL on every terminal run status (<code className="text-accent-light">completed</code> / <code className="text-accent-light">failed</code> / <code className="text-accent-light">cancelled</code>).
                    Payloads are signed with HMAC-SHA256 (<code className="text-accent-light">X-Scriba-Signature</code>).
                  </p>
                </div>
                <div className="space-y-2">
                  <label className="text-[10px] text-muted uppercase tracking-wider">Webhook URL</label>
                  <div className="flex gap-2">
                    <input
                      type="url"
                      value={webhookUrl}
                      onChange={(e) => setWebhookUrl(e.target.value)}
                      placeholder="https://your-server.example/scriba/webhook"
                      className="flex-1 bg-surface rounded-md px-3 py-2 text-xs text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors placeholder-muted"
                    />
                    <button
                      disabled={webhookSaving}
                      onClick={async () => {
                        if (!webhookUrl.trim()) return;
                        setWebhookSaving(true);
                        setWebhookMsg(null);
                        try {
                          const res = await fetch('/api/engine/webhook-config', {
                            method: 'POST',
                            headers: { 'Content-Type': 'application/json' },
                            body: JSON.stringify({ url: webhookUrl.trim() }),
                          });
                          if (res.status === 404 || res.status === 501) {
                            setWebhookMsg({ type: 'warn', text: 'Per-tenant webhook config is not yet supported by this engine version. Set SCRIBA_WEBHOOK_URL on the engine server instead.' });
                          } else if (!res.ok) {
                            const d = await res.json().catch(() => ({}));
                            setWebhookMsg({ type: 'error', text: (d as { error?: string }).error ?? 'Save failed' });
                          } else {
                            setWebhookMsg({ type: 'success', text: 'Webhook URL saved.' });
                          }
                        } catch {
                          setWebhookMsg({ type: 'error', text: 'Network error — could not save.' });
                        } finally {
                          setWebhookSaving(false);
                        }
                      }}
                      className="px-3 py-2 rounded-md text-xs font-medium bg-accent text-white hover:opacity-90 transition-opacity disabled:opacity-50 cursor-pointer"
                    >
                      {webhookSaving ? 'Saving…' : 'Save'}
                    </button>
                  </div>
                  {webhookMsg && (
                    <p className={`text-[10px] ${webhookMsg.type === 'success' ? 'text-success' : webhookMsg.type === 'warn' ? 'text-amber-400' : 'text-danger'}`}>
                      {webhookMsg.text}
                    </p>
                  )}
                </div>
                <div className="rounded-md border border-amber-400/25 bg-amber-500/8 p-3">
                  <p className="text-[10px] text-amber-400 font-medium mb-1">Important: 4xx delivery failures are fatal</p>
                  <p className="text-[10px] text-muted">
                    The engine retries on 5xx and network errors (exponential backoff, max 5 attempts) but stops permanently on any 4xx response.
                    If deliveries are failing, check your endpoint and fix the response code before runs complete.
                  </p>
                </div>
              </div>
            </motion.div>
          )}

          {/* ════════════════ NOTIFICATIONS ════════════════ */}
          {activeTab === 'notifications' && (
            <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="space-y-6">
              <h3 className="text-base font-semibold text-foreground">Notifications</h3>
              <p className="text-xs text-muted">Preferences are saved locally.</p>
              {([
                { key: 'conversionComplete' as const, label: 'Conversion completed', desc: 'Get notified when a conversion finishes' },
                { key: 'validationWarnings' as const, label: 'Validation warnings', desc: 'Receive alerts for conversion warnings' },
                { key: 'teamActivity' as const, label: 'Team activity', desc: 'Updates when team members make changes' },
                { key: 'weeklyReports' as const, label: 'Weekly reports', desc: 'Weekly summary of all conversion activity' },
                { key: 'systemUpdates' as const, label: 'System updates', desc: 'Engine updates and maintenance notices' },
              ]).map(n => (
                <div key={n.key} className="glass-light rounded-lg p-4 flex items-center justify-between">
                  <div>
                    <p className="text-sm font-medium text-foreground">{n.label}</p>
                    <p className="text-[11px] text-muted">{n.desc}</p>
                  </div>
                  <button
                    onClick={() => toggleNotif(n.key)}
                    className={`w-10 h-5 rounded-full flex items-center transition-colors cursor-pointer ${notifPrefs[n.key] ? 'bg-accent justify-end' : 'bg-surface justify-start'}`}
                  >
                    <div className="w-4 h-4 rounded-full bg-white mx-0.5 shadow-sm" />
                  </button>
                </div>
              ))}

              {(isOwner || isAdmin) && (
                <div className="glass-light rounded-xl p-5 space-y-4 border border-accent/20">
                  <div>
                    <h4 className="text-sm font-semibold text-foreground">Admin Email SMTP</h4>
                    <p className="text-[11px] text-muted mt-0.5">
                      Configure SMTP for platform emails, OAuth notices, and notification delivery.
                    </p>
                  </div>

                  <FeedbackBanner msg={smtpMsg} />

                  <div className="grid grid-cols-2 gap-3">
                    <div>
                      <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">SMTP Host</label>
                      <input
                        type="text"
                        value={smtpSettings.host}
                        onChange={(e) => handleSmtpChange('host', e.target.value)}
                        placeholder="smtp.mailgun.org"
                        className="w-full glass-light rounded-lg px-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors"
                      />
                    </div>
                    <div>
                      <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">Port</label>
                      <input
                        type="number"
                        value={smtpSettings.port}
                        onChange={(e) => handleSmtpChange('port', e.target.value)}
                        placeholder="587"
                        className="w-full glass-light rounded-lg px-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors"
                      />
                    </div>
                    <div>
                      <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">Username</label>
                      <input
                        type="text"
                        value={smtpSettings.username}
                        onChange={(e) => handleSmtpChange('username', e.target.value)}
                        placeholder="postmaster@domain.tld"
                        className="w-full glass-light rounded-lg px-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors"
                      />
                    </div>
                    <div>
                      <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">Password</label>
                      <div className="relative">
                        <input
                          type={showSmtpPassword ? 'text' : 'password'}
                          value={smtpSettings.password}
                          onChange={(e) => handleSmtpChange('password', e.target.value)}
                          placeholder="SMTP password"
                          className="w-full glass-light rounded-lg px-3 py-2.5 pr-10 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors"
                        />
                        <button
                          type="button"
                          onClick={() => setShowSmtpPassword(v => !v)}
                          className="absolute right-3 top-1/2 -translate-y-1/2 text-muted hover:text-foreground cursor-pointer"
                        >
                          {showSmtpPassword ? <EyeOff className="w-3.5 h-3.5" /> : <Eye className="w-3.5 h-3.5" />}
                        </button>
                      </div>
                    </div>
                    <div>
                      <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">From Email</label>
                      <input
                        type="email"
                        value={smtpSettings.fromEmail}
                        onChange={(e) => handleSmtpChange('fromEmail', e.target.value)}
                        placeholder="noreply@scriba.ai"
                        className="w-full glass-light rounded-lg px-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors"
                      />
                    </div>
                    <div>
                      <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">From Name</label>
                      <input
                        type="text"
                        value={smtpSettings.fromName}
                        onChange={(e) => handleSmtpChange('fromName', e.target.value)}
                        placeholder="Scriba Notifications"
                        className="w-full glass-light rounded-lg px-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors"
                      />
                    </div>
                  </div>

                  <div>
                    <label className="text-[11px] text-muted uppercase tracking-wider block mb-1.5">Reply-To (Optional)</label>
                    <input
                      type="email"
                      value={smtpSettings.replyTo}
                      onChange={(e) => handleSmtpChange('replyTo', e.target.value)}
                      placeholder="support@scriba.ai"
                      className="w-full glass-light rounded-lg px-3 py-2.5 text-sm text-foreground outline-none border border-transparent focus:border-accent/30 transition-colors"
                    />
                  </div>

                  <div className="flex items-center justify-between rounded-lg bg-surface/60 px-3 py-2.5 border border-border">
                    <div>
                      <p className="text-sm font-medium text-foreground">Use secure connection (TLS/SSL)</p>
                      <p className="text-[11px] text-muted">Enable for port 465 or providers requiring implicit TLS.</p>
                    </div>
                    <button
                      onClick={() => handleSmtpChange('secure', !smtpSettings.secure)}
                      className={`w-10 h-5 rounded-full flex items-center transition-colors cursor-pointer ${smtpSettings.secure ? 'bg-accent justify-end' : 'bg-surface justify-start'}`}
                    >
                      <div className="w-4 h-4 rounded-full bg-white mx-0.5 shadow-sm" />
                    </button>
                  </div>

                  <div className="flex justify-end">
                    <button
                      onClick={handleSaveSmtp}
                      className="flex items-center gap-2 px-4 py-2 rounded-lg gradient-accent text-white text-xs font-semibold hover:opacity-90 transition-opacity cursor-pointer"
                    >
                      <Save className="w-3.5 h-3.5" />
                      Save SMTP Settings
                    </button>
                  </div>
                </div>
              )}
            </motion.div>
          )}

          {/* ════════════════ BILLING ════════════════ */}
          {activeTab === 'billing' && (
            <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="space-y-6">
              <div className="flex items-center justify-between">
                <div>
                  <h3 className="text-base font-semibold text-foreground">Billing</h3>
                  <p className="text-xs text-muted mt-0.5">Token usage is billed on the 1st of each month.</p>
                </div>
                <button onClick={loadBilling} disabled={billingLoading} className="text-xs text-muted hover:text-foreground cursor-pointer">
                  {billingLoading ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : 'Refresh'}
                </button>
              </div>

              <FeedbackBanner msg={billingMsg} />

              {/* Current period estimate */}
              {billingEstimate && (
                <div className="glass-light rounded-xl p-5 space-y-4">
                  <p className="text-[10px] text-muted uppercase tracking-wider">Current billing period estimate</p>
                  <div className="flex items-end gap-6">
                    <div>
                      <p className="text-2xl font-bold text-foreground">{fmtEur(billingEstimate.amountCents)}</p>
                      <p className="text-xs text-muted mt-0.5">billed 1st of next month</p>
                    </div>
                    <div className="text-xs text-muted">
                      Plan: <span className="text-foreground capitalize">{capabilities.tier}</span>
                    </div>
                  </div>
                  {/* Token breakdown */}
                  <div className="grid grid-cols-3 gap-3">
                    <div className="rounded-lg bg-surface p-3">
                      <p className="text-[10px] text-muted uppercase tracking-wider mb-1">Total Used</p>
                      <p className="text-sm font-semibold text-foreground tabular-nums">{billingEstimate.totalTokens.toLocaleString()}</p>
                    </div>
                    <div className="rounded-lg bg-sky-500/10 p-3">
                      <p className="text-[10px] text-sky-400 uppercase tracking-wider mb-1">Credits Applied</p>
                      <p className="text-sm font-semibold text-sky-400 tabular-nums">-{billingEstimate.freeTokensApplied.toLocaleString()}</p>
                    </div>
                    <div className="rounded-lg bg-red-500/10 p-3">
                      <p className="text-[10px] text-red-400 uppercase tracking-wider mb-1">Billable</p>
                      <p className="text-sm font-semibold text-red-400 tabular-nums">{billingEstimate.billableTokens.toLocaleString()}</p>
                    </div>
                  </div>
                  {billingEstimate.freeTokensApplied > 0 && (
                    <p className="text-[10px] text-sky-400">{billingEstimate.freeTokensApplied.toLocaleString()} plan credits applied — only billable tokens are charged</p>
                  )}
                  {/* Slot purchases this month */}
                  {(billingEstimate.slotChargesCents ?? 0) > 0 && (
                    <div className="flex items-center justify-between rounded-lg bg-amber-500/10 border border-amber-500/20 px-4 py-3">
                      <div>
                        <p className="text-xs font-semibold text-amber-400">Extra Conversion Slots</p>
                        <p className="text-[10px] text-muted mt-0.5">Purchased this billing period</p>
                      </div>
                      <p className="text-sm font-bold text-amber-400 tabular-nums">{fmtEur(billingEstimate.slotChargesCents ?? 0)}</p>
                    </div>
                  )}
                </div>
              )}

              {/* Payment methods */}
              <div>
                <div className="flex items-center justify-between mb-3">
                  <h4 className="text-sm font-semibold text-foreground flex items-center gap-2">
                    <CreditCard className="w-4 h-4 text-muted" />
                    Payment Methods
                  </h4>
                  {!showCardForm && (
                    <button
                      onClick={() => { setShowCardForm(true); setBillingMsg(null); }}
                      className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg gradient-accent text-white text-xs font-semibold hover:opacity-90 transition-opacity cursor-pointer"
                    >
                      <Plus className="w-3 h-3" />
                      Add Payment Method
                    </button>
                  )}
                </div>

                {billingLoading && paymentMethods.length === 0 ? (
                  <div className="flex items-center gap-3 py-6 justify-center">
                    <Loader2 className="w-5 h-5 animate-spin text-muted" />
                    <span className="text-sm text-muted">Loading payment methods...</span>
                  </div>
                ) : paymentMethods.length === 0 ? (
                  <div className="glass-light rounded-xl p-6 flex flex-col items-center text-center gap-3">
                    <CreditCard className="w-8 h-8 text-muted" />
                    <div>
                      <p className="text-sm font-medium text-foreground">No payment method on file</p>
                      <p className="text-xs text-muted mt-1">Add a payment method to enable automatic monthly billing.</p>
                    </div>
                  </div>
                ) : (
                  <div className="space-y-2">
                    {paymentMethods.length === 1 && (
                      <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-warning/10 border border-warning/20 text-warning text-xs">
                        <AlertTriangle className="w-4 h-4 shrink-0" />
                        <span>You must add a second method before removing this one.</span>
                      </div>
                    )}
                    {paymentMethods.map(pm => {
                      const isCard = pm.type === 'card' || pm.type === 'link';
                      const isSepa = pm.type === 'sepa_debit';
                      const isPaypal = pm.type === 'paypal';
                      const label = isCard
                        ? `${pm.brand ? pm.brand.charAt(0).toUpperCase() + pm.brand.slice(1) : 'Card'} ···· ${pm.last4}`
                        : isSepa
                          ? `Bank account ···· ${pm.last4 ?? '—'}`
                          : isPaypal
                            ? `PayPal${pm.email ? ` (${pm.email})` : ''}`
                            : pm.type;
                      const sub = isCard
                        ? `Expires ${pm.expMonth}/${pm.expYear}`
                        : isSepa
                          ? `${pm.country ?? ''} ${pm.bankCode ?? ''}`.trim() || 'SEPA Direct Debit'
                          : isPaypal
                            ? 'PayPal account'
                            : '';
                      return (
                        <div key={pm.id} className={`glass-light rounded-lg p-4 flex items-center gap-4 ${pm.isDefault ? 'border border-accent/20' : ''}`}>
                          <CreditCard className="w-5 h-5 text-muted shrink-0" />
                          <div className="flex-1">
                            <div className="flex items-center gap-2">
                              <p className="text-sm font-medium text-foreground capitalize">{label}</p>
                              {pm.isDefault && <span className="text-[10px] px-2 py-0.5 rounded-full bg-accent/15 text-accent-light font-medium">Default</span>}
                            </div>
                            {sub && <p className="text-[11px] text-muted">{sub}</p>}
                          </div>
                          <button
                            onClick={() => handleRemovePaymentMethod(pm.id)}
                            disabled={removingPm === pm.id || paymentMethods.length === 1}
                            className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-danger/30 text-danger text-xs font-medium hover:bg-danger/10 transition-colors cursor-pointer disabled:opacity-50"
                          >
                            {removingPm === pm.id ? <Loader2 className="w-3 h-3 animate-spin" /> : <X className="w-3 h-3" />}
                            Remove
                          </button>
                        </div>
                      );
                    })}
                  </div>
                )}


              {/* Inline card setup form */}
              <AnimatePresence>
                {showCardForm && (
                  <CardSetupForm
                    onSuccess={handleCardSetupSuccess}
                    onCancel={() => setShowCardForm(false)}
                  />
                )}
              </AnimatePresence>
              </div>

              {/* Billing history */}
              <div>
                <h4 className="text-sm font-semibold text-foreground flex items-center gap-2 mb-3">
                  <Receipt className="w-4 h-4 text-muted" />
                  Billing History
                </h4>

                {billingRecords.length === 0 ? (
                  <p className="text-xs text-muted py-4 text-center">No billing records yet.</p>
                ) : (
                  <div className="overflow-x-auto">
                    <table className="w-full text-xs">
                      <thead>
                        <tr className="text-muted border-b border-border">
                          <th className="text-left pb-2 font-medium">Period</th>
                          <th className="text-right pb-2 font-medium">Tokens</th>
                          <th className="text-right pb-2 font-medium">Amount</th>
                          <th className="text-right pb-2 font-medium">Status</th>
                        </tr>
                      </thead>
                      <tbody className="divide-y divide-border">
                        {billingRecords.map(r => (
                          <tr key={r.id} className="hover:bg-surface-light/30 transition-colors">
                            <td className="py-2.5 text-foreground">
                              {new Date(r.periodStart).toLocaleDateString('en-GB', { month: 'short', year: 'numeric' })}
                            </td>
                            <td className="py-2.5 text-right text-foreground">{r.totalTokens.toLocaleString()}</td>
                            <td className="py-2.5 text-right text-foreground">{fmtEur(r.amountCents)}</td>
                            <td className={`py-2.5 text-right font-medium capitalize ${statusColor(r.status)}`}>{r.status}</td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}
              </div>

              {/* Pricing info */}
              <div className="glass-light rounded-xl p-5">
                <p className="text-[10px] text-muted uppercase tracking-wider mb-3">Token pricing (your plan)</p>
                <div className="space-y-1.5">
                  {([
                    ['Modern languages (Group 1)', '1.0x multiplier'],
                    ['Legacy & Mainframe (Group 2)', '2.5x multiplier'],
                    ['Mainframe+ (Group 3)', '3.0x multiplier'],
                  ] as const).map(([label, mult]) => (
                    <div key={label} className="flex items-center justify-between">
                      <span className="text-xs text-foreground">{label}</span>
                      <span className="text-xs text-muted">{mult}</span>
                    </div>
                  ))}
                </div>
                <p className="text-[11px] text-muted mt-3">Complexity multipliers are applied to the base rate per million tokens for your plan tier.</p>
              </div>
            </motion.div>
          )}

          {/* ════════════════ FIC SETTINGS ════════════════ */}
          {activeTab === 'fic' && isAdmin && (
            <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
              <AdminFattureInCloud />
            </motion.div>
          )}

        </div>
      </div>
    </div>
  );
}
