import { useState } from 'react';
import type { SetupStatus } from '../../hooks/useSetupState';

// Full-screen first-run onboarding for a fresh, no-auth `docker compose up`.
// Configures the LLM connection (required) plus an optional server port and
// auth bootstrap, then applies everything in ONE call to /api/setup/apply.
// See docs/superpowers/specs/2026-06-16-browser-setup-wizard-design.md.

type ConnectionType = 'direct' | 'aao_gateway';
type AuthMode = 'none' | 'local' | 'oauth';
type OAuthProvider = 'google' | 'gitea';

interface ApplyResult {
  ok: boolean;
  restartRequired: boolean;
  adminEmail?: string;
}

const PRIMARY_BTN =
  'px-4 py-2 text-sm font-semibold bg-accent text-accent-fg rounded-lg hover:bg-accent-deep disabled:opacity-50 transition-colors';
const SECONDARY_BTN =
  'px-4 py-2 text-sm text-accent border border-accent rounded-lg hover:bg-accent-soft disabled:opacity-50 transition-colors';
const INPUT =
  'w-full px-3 py-2 text-sm border border-slate-300 rounded-lg bg-white focus:outline-none focus:ring-2 focus:ring-accent/40';
const LABEL = 'block text-sm font-medium text-slate-700 mb-1';

function restartCommand(hint: SetupStatus['deployHint']): string {
  return hint === 'docker' ? 'docker compose restart' : 'scripts/server.sh restart';
}

export function SetupWizard({ status, onComplete }: { status: SetupStatus; onComplete: () => void }) {
  const tokenRequired = status.tokenRequired;

  const [token, setToken] = useState('');

  // Step 1 — LLM (required)
  const [connectionType, setConnectionType] = useState<ConnectionType>('direct');
  const [endpoint, setEndpoint] = useState('http://localhost:11434/v1');
  const [apiKey, setApiKey] = useState('');
  const [model, setModel] = useState('');
  const [models, setModels] = useState<string[]>([]);
  const [probing, setProbing] = useState(false);
  const [probeError, setProbeError] = useState<string | null>(null);

  // Step 2 — port (optional)
  const [port, setPort] = useState('');

  // Step 3 — auth (optional)
  const [authMode, setAuthMode] = useState<AuthMode>('none');
  const [localEmail, setLocalEmail] = useState('');
  const [localPassword, setLocalPassword] = useState('');
  const [oauthProvider, setOauthProvider] = useState<OAuthProvider>('gitea');
  const [clientId, setClientId] = useState('');
  const [clientSecret, setClientSecret] = useState('');
  const [callbackUrl, setCallbackUrl] = useState('');
  const [baseUrl, setBaseUrl] = useState('');
  const [oauthAdminEmail, setOauthAdminEmail] = useState('');

  const [applying, setApplying] = useState(false);
  const [applyError, setApplyError] = useState<string | null>(null);
  const [result, setResult] = useState<ApplyResult | null>(null);

  function headers(): Record<string, string> {
    const h: Record<string, string> = { 'content-type': 'application/json' };
    if (tokenRequired && token.trim()) h['x-setup-token'] = token.trim();
    return h;
  }

  async function runProbe() {
    setProbing(true);
    setProbeError(null);
    setModels([]);
    try {
      const res = await fetch('/api/setup/probe', {
        method: 'POST',
        headers: headers(),
        body: JSON.stringify({ connectionType, endpoint, apiKey: apiKey || undefined }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok || !data.ok) {
        setProbeError(data.error || `connection failed (HTTP ${res.status})`);
        return;
      }
      const list: string[] = Array.isArray(data.models) ? data.models : [];
      setModels(list);
      if (list.length && !model) setModel(list[0]);
      if (!list.length) setProbeError('connected, but no models were returned — enter a model name manually');
    } catch (e) {
      setProbeError(String(e));
    } finally {
      setProbing(false);
    }
  }

  function authBlock(): unknown | undefined {
    if (authMode === 'local') {
      return { mode: 'local', local: { email: localEmail.trim(), password: localPassword } };
    }
    if (authMode === 'oauth') {
      return {
        mode: 'oauth',
        oauth: {
          provider: oauthProvider,
          clientId: clientId.trim(),
          clientSecret: clientSecret.trim(),
          callbackUrl: callbackUrl.trim(),
          adminEmail: oauthAdminEmail.trim(),
          ...(oauthProvider === 'gitea' ? { baseUrl: baseUrl.trim() } : {}),
        },
      };
    }
    return undefined;
  }

  const canApply =
    (!tokenRequired || token.trim().length > 0) &&
    endpoint.trim().length > 0 &&
    model.trim().length > 0 &&
    (connectionType !== 'aao_gateway' || apiKey.trim().length > 0) &&
    (authMode !== 'local' || (localEmail.trim().length > 0 && localPassword.length >= 8)) &&
    (authMode !== 'oauth' ||
      (clientId.trim() &&
        clientSecret.trim() &&
        callbackUrl.trim() &&
        oauthAdminEmail.trim().includes('@') &&
        (oauthProvider !== 'gitea' || baseUrl.trim())));

  async function runApply() {
    setApplying(true);
    setApplyError(null);
    try {
      const body: Record<string, unknown> = {
        llm: { connectionType, endpoint: endpoint.trim(), model: model.trim(), apiKey: apiKey || undefined },
      };
      if (port.trim()) body.port = Number(port.trim());
      const auth = authBlock();
      if (auth) body.auth = auth;

      const res = await fetch('/api/setup/apply', {
        method: 'POST',
        headers: headers(),
        body: JSON.stringify(body),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok || !data.ok) {
        setApplyError(data.error || `apply failed (HTTP ${res.status})`);
        return;
      }
      const r: ApplyResult = { ok: true, restartRequired: !!data.restartRequired, adminEmail: data.adminEmail };
      setResult(r);
      if (!r.restartRequired) {
        // LLM-only: the wizard's job is done — refresh into the app.
        onComplete();
      }
    } catch (e) {
      setApplyError(String(e));
    } finally {
      setApplying(false);
    }
  }

  // --- Finish screen (restart required) ---
  if (result?.restartRequired) {
    return (
      <Shell>
        <h1 className="text-xl font-semibold text-slate-800 mb-2">Almost there — one restart needed</h1>
        <p className="text-sm text-slate-600 mb-4">
          Your LLM connection is live. The port and/or authentication changes take effect after a restart.
        </p>
        <div className="bg-slate-900 text-slate-100 text-sm rounded-lg px-4 py-3 font-mono mb-4 select-all">
          {restartCommand(status.deployHint)}
        </div>
        {result.adminEmail && (
          <p className="text-sm text-slate-600">
            After restart, sign in as <span className="font-semibold">{result.adminEmail}</span> with the password you
            just set. Change it from <span className="font-medium">Settings → Account</span> afterwards.
          </p>
        )}
      </Shell>
    );
  }

  // --- Wizard form ---
  return (
    <Shell>
      <h1 className="text-xl font-semibold text-slate-800 mb-1">Welcome — let's get you set up</h1>
      <p className="text-sm text-slate-600 mb-6">
        Connect a language model to start running tasks. Optionally set the server port and turn on sign-in.
      </p>

      {tokenRequired && (
        <Section title="Setup token" subtitle="Find it in the server logs: “open the UI and enter this setup token”.">
          <input className={INPUT} value={token} onChange={(e) => setToken(e.target.value)} placeholder="paste the setup token" />
        </Section>
      )}

      <Section title="1 · Language model" subtitle="Required. This is reflected immediately — no restart.">
        <label className={LABEL}>Connection</label>
        <select
          className={`${INPUT} mb-3`}
          value={connectionType}
          onChange={(e) => setConnectionType(e.target.value as ConnectionType)}
        >
          <option value="direct">Direct (Ollama / vLLM / OpenAI-compatible)</option>
          <option value="aao_gateway">AAO gateway</option>
        </select>

        <label className={LABEL}>Endpoint URL</label>
        <input className={`${INPUT} mb-3`} value={endpoint} onChange={(e) => setEndpoint(e.target.value)} placeholder="http://localhost:11434/v1" />

        {connectionType === 'aao_gateway' && (
          <>
            <label className={LABEL}>API key</label>
            <input className={`${INPUT} mb-3`} type="password" value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="sk-aao-…" />
          </>
        )}

        <div className="flex items-center gap-3 mb-3">
          <button className={SECONDARY_BTN} onClick={runProbe} disabled={probing || !endpoint.trim() || (tokenRequired && !token.trim())}>
            {probing ? 'Testing…' : 'Test connection'}
          </button>
          {probeError && <span className="text-sm text-red-600">{probeError}</span>}
          {!probeError && models.length > 0 && <span className="text-sm text-green-600">Found {models.length} model(s)</span>}
        </div>

        <label className={LABEL}>Model</label>
        {models.length > 0 ? (
          <select className={INPUT} value={model} onChange={(e) => setModel(e.target.value)}>
            {!models.includes(model) && model && <option value={model}>{model}</option>}
            {models.map((m) => (
              <option key={m} value={m}>
                {m}
              </option>
            ))}
          </select>
        ) : (
          <input className={INPUT} value={model} onChange={(e) => setModel(e.target.value)} placeholder="e.g. llama3.1:8b" />
        )}
      </Section>

      <Section title="2 · Server port" subtitle="Optional. Leave blank to keep the current port. Takes effect after a restart.">
        <input className={INPUT} value={port} onChange={(e) => setPort(e.target.value)} placeholder={String(status.port)} inputMode="numeric" />
      </Section>

      <Section title="3 · Sign-in" subtitle="Optional. Leave off to stay open (no login). Takes effect after a restart.">
        <select className={`${INPUT} mb-3`} value={authMode} onChange={(e) => setAuthMode(e.target.value as AuthMode)}>
          <option value="none">No sign-in (open)</option>
          <option value="local">Email + password (first admin)</option>
          <option value="oauth">OAuth (Google / Gitea)</option>
        </select>

        {authMode === 'local' && (
          <>
            <label className={LABEL}>Admin email</label>
            <input className={`${INPUT} mb-3`} value={localEmail} onChange={(e) => setLocalEmail(e.target.value)} placeholder="admin@example.com" />
            <label className={LABEL}>Admin password (min 8 chars)</label>
            <input className={INPUT} type="password" value={localPassword} onChange={(e) => setLocalPassword(e.target.value)} />
          </>
        )}

        {authMode === 'oauth' && (
          <>
            <label className={LABEL}>Provider</label>
            <select className={`${INPUT} mb-3`} value={oauthProvider} onChange={(e) => setOauthProvider(e.target.value as OAuthProvider)}>
              <option value="gitea">Gitea</option>
              <option value="google">Google</option>
            </select>
            <label className={LABEL}>Client ID</label>
            <input className={`${INPUT} mb-3`} value={clientId} onChange={(e) => setClientId(e.target.value)} />
            <label className={LABEL}>Client secret</label>
            <input className={`${INPUT} mb-3`} type="password" value={clientSecret} onChange={(e) => setClientSecret(e.target.value)} />
            <label className={LABEL}>Callback URL</label>
            <input className={`${INPUT} mb-3`} value={callbackUrl} onChange={(e) => setCallbackUrl(e.target.value)} placeholder="https://your-host/auth/gitea/callback" />
            <label className={LABEL}>Admin email</label>
            <input className={`${INPUT} mb-3`} value={oauthAdminEmail} onChange={(e) => setOauthAdminEmail(e.target.value)} placeholder="you@example.com — becomes admin on first login" />
            {oauthProvider === 'gitea' && (
              <>
                <label className={LABEL}>Gitea base URL</label>
                <input className={INPUT} value={baseUrl} onChange={(e) => setBaseUrl(e.target.value)} placeholder="https://gitea.example.com" />
              </>
            )}
          </>
        )}
      </Section>

      {applyError && <p className="text-sm text-red-600 mb-3">{applyError}</p>}

      <div className="flex justify-end pt-2">
        <button className={PRIMARY_BTN} onClick={runApply} disabled={applying || !canApply}>
          {applying ? 'Applying…' : 'Apply & start'}
        </button>
      </div>
    </Shell>
  );
}

function Shell({ children }: { children: React.ReactNode }) {
  return (
    <div className="h-dvh overflow-y-auto bg-slate-50 flex items-start justify-center py-10 px-4">
      <div className="w-full max-w-xl bg-white border border-slate-200 rounded-2xl shadow-sm p-8">{children}</div>
    </div>
  );
}

function Section({ title, subtitle, children }: { title: string; subtitle?: string; children: React.ReactNode }) {
  return (
    <div className="mb-6 pb-6 border-b border-slate-100 last:border-b-0">
      <h2 className="text-sm font-semibold text-slate-800">{title}</h2>
      {subtitle && <p className="text-xs text-slate-500 mb-3">{subtitle}</p>}
      {children}
    </div>
  );
}
