import { useNavigate } from '@solidjs/router';
import { Show, createMemo, createSignal, onMount } from 'solid-js';
import { isExternalIdentity, pickManagementLoginError } from '~/lib/admin-auth';
import CaptchaCanvas from '~/components/CaptchaCanvas';

type AuthMode = 'login' | 'reset';
type ResetStep = 'request' | 'verify';

/* Matches public website input exactly */
const inputCls =
  'h-11 w-full rounded-xl border border-[#E5E7EB] bg-white px-4 text-sm text-[#111827] outline-none transition placeholder:text-[#9CA3AF] focus:border-[#FF5E13] focus:ring-2 focus:ring-[#FFE6D9]';

const labelCls =
  'mb-2 block text-[12px] font-semibold uppercase tracking-[0.11em] text-[#4B5563]';

export default function LoginPage() {
  const navigate = useNavigate();
  const [mode, setMode] = createSignal<AuthMode>('login');
  const [resetStep, setResetStep] = createSignal<ResetStep>('request');
  const [email, setEmail] = createSignal('');
  const [password, setPassword] = createSignal('');
  const [showPassword, setShowPassword] = createSignal(false);
  const [resetCode, setResetCode] = createSignal('');
  const [newPassword, setNewPassword] = createSignal('');
  const [confirmPassword, setConfirmPassword] = createSignal('');
  const [maskedEmail, setMaskedEmail] = createSignal('');
  const [isSubmitting, setIsSubmitting] = createSignal(false);
  const [error, setError] = createSignal('');
  const [info, setInfo] = createSignal('');
  const [captchaId, setCaptchaId] = createSignal('');
  const [captchaChallenge, setCaptchaChallenge] = createSignal('');
  const [captchaInput, setCaptchaInput] = createSignal('');

  const canSubmitLogin = createMemo(() => email().trim().length > 0 && password().trim().length > 0);
  const canSubmitResetRequest = createMemo(() => email().trim().length > 0 && newPassword().trim().length > 0 && confirmPassword().trim().length > 0);
  const canSubmitResetVerify = createMemo(() => resetCode().trim().length === 6);

  const clearMessages = () => { setError(''); setInfo(''); };

  // The employees service (which backs /api/admin/auth/login) requires the
  // same server-side captcha challenge the public site uses — generated by
  // the users service at /api/auth/captcha and verified against shared Redis.
  // Routed through /api/gateway/* (this app's generic gateway proxy) rather
  // The admin is a plain Vite SPA — /api/* routes are proxied directly to the
  // gateway (vite.config.ts proxy: /api → http://localhost:9100), so /api/auth/captcha
  // reaches the users service correctly.  The /api/gateway prefix is only needed
  // in the SolidStart frontend where the middleware otherwise falls through to Nitro.
  const loadCaptcha = async () => {
    setCaptchaInput('');
    try {
      const r = await fetch('/api/auth/captcha', { method: 'POST', headers: { Accept: 'application/json' }, credentials: 'include' });
      const payload = await r.json().catch(() => ({}));
      setCaptchaId(String(payload?.captcha_id || ''));
      setCaptchaChallenge(String(payload?.challenge || ''));
    } catch {
      setCaptchaId('');
      setCaptchaChallenge('');
    }
  };

  onMount(() => {
    void loadCaptcha();
  });

  const switchMode = (next: AuthMode) => {
    clearMessages();
    setMode(next);
    if (next === 'login') {
      setResetStep('request');
      setResetCode(''); setMaskedEmail('');
      setNewPassword(''); setConfirmPassword('');
    }
  };

  // Note: there is no client-side "already logged in" pre-redirect here.
  // AdminShell performs the real server-verified session check
  // (/api/auth/session) on every /admin/* page load and redirects to /login
  // itself if unauthenticated, so this page doesn't need to duplicate that
  // logic with a fake client-side session gate.
  const completeAdminLogin = () => {
    const from = new URLSearchParams(window.location.search).get('from');
    let destination = '/admin';
    if (from) {
      try {
        const parsed = new URL(from, window.location.origin);
        if (parsed.origin === window.location.origin && parsed.pathname.startsWith('/admin')) {
          destination = parsed.pathname + parsed.search + parsed.hash;
        }
      } catch { /* ignore invalid URLs */ }
    }
    navigate(destination, { replace: true });
  };

  const directSignIn = async () => {
    clearMessages();
    if (!canSubmitLogin()) { setError('Email and password are required.'); return; }
    if (!captchaInput().trim()) { setError('Enter the captcha answer to continue.'); return; }
    setIsSubmitting(true);
    try {
      const body = JSON.stringify({
        email: email().trim().toLowerCase(),
        password: password(),
        loginTarget: 'admin',
        captcha_id: captchaId(),
        captcha_answer: captchaInput().trim(),
      });
      const headers = { 'Content-Type': 'application/json', Accept: 'application/json', 'x-portal-target': 'admin' };
      let payload: any = {}; let status = 500; let success = false;
       const r = await fetch('/api/admin/auth/login', { method: 'POST', headers, credentials: 'include', body });
      status = r.status; payload = await r.json().catch(() => ({}));
      if (r.ok) { success = true; }
      if (!success) {
        if (String(payload?.code || '').toUpperCase() === 'CAPTCHA_FAILED') {
          void loadCaptcha();
          throw new Error(String(payload?.error || 'Invalid or expired captcha. Please try again.'));
        }
        const fallback = status === 502 ? 'Auth service unavailable (502). Please retry in 1–2 minutes.' : 'Sign in failed.';
        throw new Error(pickManagementLoginError(payload) || fallback);
      }
      if (isExternalIdentity(payload)) throw new Error('External users cannot use this portal.');
      const token = String(payload?.access_token || payload?.accessToken || '').trim();
      if (token) sessionStorage.setItem('nxtgauge_admin_access_token', token);
      completeAdminLogin();
    } catch (e: any) { setError(String(e?.message || 'Sign in failed.')); }
    finally { setIsSubmitting(false); }
  };

  const requestResetCode = async () => {
    clearMessages();
    if (!canSubmitResetRequest()) { setError('All fields are required.'); return; }
    if (newPassword() !== confirmPassword()) { setError('Passwords do not match.'); return; }
    const trimmedEmail = email().trim().toLowerCase();
    setIsSubmitting(true);
    try {
      const r = await fetch('/api/admin/auth/forgot-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
        body: JSON.stringify({ email: trimmedEmail }),
      });
      if (!r.ok) {
        const payload = await r.json().catch(() => ({}));
        const fallback = r.status === 502 ? 'Service unavailable (502). Please retry.' : 'Failed to send reset code.';
        throw new Error(String(payload?.message || payload?.error || fallback).trim());
      }
      // The backend intentionally responds 200 whether or not the email exists,
      // to avoid account enumeration — there's no challengeId in this API.
      setMaskedEmail(trimmedEmail);
      setResetStep('verify');
      setInfo('If that email has an account, a reset code has been sent.');
    } catch (e: any) { setError(String(e?.message || 'Failed to send reset code.')); }
    finally { setIsSubmitting(false); }
  };

  const verifyResetCode = async () => {
    clearMessages();
    if (!canSubmitResetVerify()) { setError('A valid 6-digit code is required.'); return; }
    if (newPassword().trim() !== confirmPassword().trim()) { setError('Passwords do not match.'); return; }
    setIsSubmitting(true);
    try {
      const r = await fetch('/api/admin/auth/reset-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
        body: JSON.stringify({ code: resetCode().trim(), new_password: newPassword().trim() }),
      });
      const payload = await r.json().catch(() => ({}));
      if (!r.ok) {
        const fallback = r.status === 502 ? 'Service unavailable (502). Please retry.' : 'Password reset failed.';
        throw new Error(String(payload?.message || payload?.error || fallback).trim());
      }
      setPassword(''); switchMode('login');
      setInfo('Password reset successful. Please sign in with your new password.');
    } catch (e: any) { setError(String(e?.message || 'Password reset failed.')); }
    finally { setIsSubmitting(false); }
  };

  return (
    <main class="min-h-screen bg-[#F9FAFB] text-[#111827]">
      <div class="mx-auto flex min-h-screen w-full max-w-[1260px] items-center px-4 py-8 sm:px-6 lg:py-10">
        <div class="grid w-full gap-6 lg:grid-cols-[1.05fr_0.95fr]">
          <section class="relative hidden overflow-hidden rounded-3xl border border-[#E5E7EB] bg-white p-10 shadow-sm lg:flex lg:min-h-[640px] lg:flex-col lg:justify-between">
            <div class="pointer-events-none absolute -right-20 -top-20 h-72 w-72 rounded-full bg-[#FF5E13]/10 blur-3xl" />
            <div class="pointer-events-none absolute bottom-[-80px] left-[-80px] h-72 w-72 rounded-full bg-[#0D0D2A]/10 blur-3xl" />

            <div>
              <img src="/nxtgauge-logo.png" alt="NXTGAUGE" class="h-auto w-[190px] object-contain" />
            </div>

            <div class="space-y-6">
              <p class="inline-flex items-center gap-2 rounded-full border border-[#FFE4D5] bg-[#FFF3EC] px-3 py-1 text-[11px] font-bold uppercase tracking-widest text-[#FF5E13]">
                <span class="h-1.5 w-1.5 rounded-full bg-[#FF5E13]" />
                Internal Admin Portal
              </p>
              <h1 class="text-[40px] font-extrabold leading-tight text-[#0D0D2A]">
                Dashboard Access
                <br />
                For Operations Team
              </h1>
              <p class="max-w-[520px] text-[15px] leading-relaxed text-[#6B7280]">
                Sign in to manage roles, approvals, user operations, and runtime module configuration from one control center.
              </p>

              <div class="grid grid-cols-2 gap-3">
                <div class="rounded-xl border border-[#E5E7EB] bg-[#FAFAFA] px-4 py-3">
                  <p class="text-[12px] font-semibold text-[#6B7280]">Access Control</p>
                  <p class="mt-1 text-[14px] font-semibold text-[#0D0D2A]">Role Management</p>
                </div>
                <div class="rounded-xl border border-[#E5E7EB] bg-[#FAFAFA] px-4 py-3">
                  <p class="text-[12px] font-semibold text-[#6B7280]">Workflows</p>
                  <p class="mt-1 text-[14px] font-semibold text-[#0D0D2A]">Approvals & Verification</p>
                </div>
                <div class="rounded-xl border border-[#E5E7EB] bg-[#FAFAFA] px-4 py-3">
                  <p class="text-[12px] font-semibold text-[#6B7280]">Operations</p>
                  <p class="mt-1 text-[14px] font-semibold text-[#0D0D2A]">Users & Companies</p>
                </div>
                <div class="rounded-xl border border-[#E5E7EB] bg-[#FAFAFA] px-4 py-3">
                  <p class="text-[12px] font-semibold text-[#6B7280]">Runtime</p>
                  <p class="mt-1 text-[14px] font-semibold text-[#0D0D2A]">Module Visibility</p>
                </div>
              </div>
            </div>

            <p class="rounded-xl border border-[#E5E7EB] bg-[#F9FAFB] px-4 py-3 text-[13px] text-[#6B7280]">
              Secured with internal access policies. Authorized personnel only.
            </p>
          </section>

          <section class="rounded-3xl border border-[#E5E7EB] bg-white p-6 shadow-sm sm:p-7">
            <div class="mb-5 flex items-center justify-between">
              <img src="/nxtgauge-logo.png" alt="NXTGAUGE" class="h-auto w-[170px] object-contain" />
              <span class="rounded-full bg-[#FFF1EB] px-3 py-1 text-[11px] font-semibold uppercase tracking-wide text-[#FF5E13]">
                Admin
              </span>
            </div>

          <div class="mt-4">
            <h2 class="text-[30px] font-extrabold text-[#0D0D2A]">
              {mode() === 'login' ? 'Sign In' : 'Reset Password'}
            </h2>
            <p class="mt-1.5 text-sm text-[#6B7280]">
              {mode() === 'login' ? 'Internal team access only.' : 'Use your internal email to reset access.'}
            </p>
          </div>

          <div class="mt-5 space-y-3.5">

            {/* Email */}
            <div>
              <label class={labelCls}>Email</label>
              <input
                type="email"
                value={email()}
                onInput={(e) => { setEmail(e.currentTarget.value); clearMessages(); }}
                placeholder="Enter your email"
                class={inputCls}
                autocomplete="email"
              />
            </div>

            {/* Login mode */}
            <Show when={mode() === 'login'}>
              <div>
                <div class="mb-2 flex items-center justify-between">
                  <label class={labelCls} style="margin-bottom:0">Password</label>
                  <button type="button" class="text-xs font-semibold text-[#fd6216] underline" onClick={() => switchMode('reset')}>
                    Forgot?
                  </button>
                </div>
                <div class="relative">
                  <input
                    type={showPassword() ? 'text' : 'password'}
                    value={password()}
                    onInput={(e) => { setPassword(e.currentTarget.value); clearMessages(); }}
                    placeholder="Enter your password"
                    class={`${inputCls} pr-11`}
                    autocomplete="current-password"
                  />
                  <button
                    type="button"
                    onClick={() => setShowPassword(v => !v)}
                    class="absolute inset-y-0 right-0 flex items-center px-3 text-[#5b6480] transition hover:text-[#1b2440]"
                  >
                    <Show when={showPassword()} fallback={
                      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" class="h-5 w-5">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z" /><circle cx="12" cy="12" r="3" />
                      </svg>
                    }>
                      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" class="h-5 w-5">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M3 3l18 18M10.58 10.58a2 2 0 002.83 2.83" />
                        <path stroke-linecap="round" stroke-linejoin="round" d="M9.88 5.09A10.96 10.96 0 0112 4.91c5.52 0 10 4.09 10 7.09 0 1.2-.72 2.53-1.95 3.72M6.1 6.1C3.54 7.58 2 9.79 2 12c0 3 4.48 7.09 10 7.09 1.72 0 3.36-.4 4.84-1.12" />
                      </svg>
                    </Show>
                  </button>
                </div>
              </div>

              <div>
                <label class={labelCls}>Captcha</label>
                <div class="flex items-center gap-2">
                  <button
                    type="button"
                    aria-label="Refresh captcha"
                    onClick={() => void loadCaptcha()}
                    class="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl border border-[#E5E7EB] bg-white text-[#5b6480] transition hover:text-[#1b2440]"
                  >
                    ↻
                  </button>
                  <CaptchaCanvas challenge={captchaChallenge()} class="h-11 shrink-0 rounded-xl border border-[#E5E7EB]" />
                  <input
                    type="text"
                    value={captchaInput()}
                    onInput={(e) => { setCaptchaInput(e.currentTarget.value); clearMessages(); }}
                    placeholder="Enter answer"
                    class={inputCls}
                  />
                </div>
              </div>
            </Show>

            {/* Reset mode */}
            <Show when={mode() === 'reset'}>
              <div>
                <label class={labelCls}>New Password</label>
                <input type="password" value={newPassword()} onInput={(e) => { setNewPassword(e.currentTarget.value); clearMessages(); }} placeholder="Minimum 8 characters" class={inputCls} />
              </div>
              <div>
                <label class={labelCls}>Confirm Password</label>
                <input type="password" value={confirmPassword()} onInput={(e) => { setConfirmPassword(e.currentTarget.value); clearMessages(); }} placeholder="Repeat new password" class={inputCls} />
              </div>
              <Show when={resetStep() === 'verify'}>
                <div>
                  <label class={labelCls}>Verification Code</label>
                  <input
                    type="text" inputMode="numeric" maxLength={6}
                    value={resetCode()}
                    onInput={(e) => { setResetCode(e.currentTarget.value.replace(/\D/g, '').slice(0, 6)); clearMessages(); }}
                    placeholder="000000"
                    class={`${inputCls} text-center text-lg tracking-[0.3em]`}
                  />
                  <p class="mt-1.5 rounded-xl border border-emerald-200 bg-emerald-50 px-3 py-2 text-xs text-emerald-800">
                    Code sent to <span class="font-semibold">{maskedEmail() || email()}</span>
                  </p>
                </div>
              </Show>
            </Show>

            {/* Error / Info */}
            <Show when={error()}>
              <p class="rounded-xl border border-red-200 bg-red-50 px-3 py-2 text-sm font-medium text-red-600">{error()}</p>
            </Show>
            <Show when={info()}>
              <p class="rounded-xl border border-emerald-200 bg-emerald-50 px-3 py-2 text-sm text-emerald-700">{info()}</p>
            </Show>

            {/* Sign In button */}
            <Show when={mode() === 'login'}>
              <button
                type="button"
                class="h-11 w-full rounded-xl bg-[#0D0D2A] text-sm font-semibold text-white transition hover:bg-[#1A1A3A] disabled:cursor-not-allowed disabled:opacity-60"
                disabled={isSubmitting()}
                onClick={directSignIn}
              >
                {isSubmitting() ? 'Signing in…' : 'Sign In'}
              </button>
              <p class="text-xs text-[#6B7280]">Secure login with internal access policies.</p>
            </Show>

            {/* Reset buttons */}
            <Show when={mode() === 'reset'}>
              <Show when={resetStep() === 'request'} fallback={
                <button
                  type="button"
                  class="h-11 w-full rounded-xl bg-[#0D0D2A] text-sm font-semibold text-white transition hover:bg-[#1A1A3A] disabled:cursor-not-allowed disabled:opacity-60"
                  disabled={isSubmitting() || !canSubmitResetVerify()}
                  onClick={verifyResetCode}
                >
                  {isSubmitting() ? 'Resetting…' : 'Verify & Reset Password'}
                </button>
              }>
                <button
                  type="button"
                  class="h-11 w-full rounded-xl bg-[#0D0D2A] text-sm font-semibold text-white transition hover:bg-[#1A1A3A] disabled:cursor-not-allowed disabled:opacity-60"
                  disabled={isSubmitting() || !canSubmitResetRequest()}
                  onClick={requestResetCode}
                >
                  {isSubmitting() ? 'Sending Code…' : 'Send Reset Code'}
                </button>
              </Show>
              <button type="button" class="w-full text-center text-sm font-semibold text-[#fd6216] underline" onClick={() => switchMode('login')}>
                Back to sign in
              </button>
            </Show>

          </div>
        </section>
      </div>
      </div>
    </main>
  );
}
