/**
 * LoginPage — standalone /login route (Phase 19, D-04).
 *
 * UI-SPEC §Surface Architecture Surfaces 1–10:
 *   Surface 1: Full-page standalone route (no AppNav/BottomTabBar/SetupBanner)
 *   Surface 2: BrandSlot — app logo placeholder + name + tagline (Phase 17 seam)
 *   Surface 3: Login card — "Sign in" heading
 *   Surface 4: Username field (id="login-username", spellCheck/autoCapitalize/autoCorrect off)
 *   Surface 5: Password field with show/hide toggle (Eye/EyeOff, 44px tap target)
 *   Surface 6: Error/lockout banner (role="status", aria-live="polite", 4 error variants)
 *   Surface 7: Primary "Sign in" / "Signing in…" submit button (full-width)
 *   Surface 8: Method divider ("or") — rendered only when oidcEnabled
 *   Surface 9: "Login with OIDC" outlined button — rendered only when oidcEnabled
 *   Surface 10: "Forgot your password? Ask your admin." helper (informational only)
 *
 * Auth gate: App.tsx renders this route when meQuery returns 401 AND localEnabled.
 * On success: window.location.replace('/') — the cookie is set by the API server.
 *
 * Security:
 *   T-19-18: password field is controlled state only; never written to localStorage/sessionStorage
 *   T-19-19: single shared "Incorrect username or password." — no field-level blame
 *   T-19-20: plain-text JSX children; no dangerouslySetInnerHTML (T-05-24)
 *   T-19-21: D-06 — UI never renders the provider name; uses generic "Login with OIDC"
 */

import { useState, useRef, useEffect } from 'react';
import { useMutation } from '@tanstack/react-query';
import { AlertCircle, Eye, EyeOff, Loader2, ShieldCheck } from 'lucide-react';
import { fetchLocalLogin, LoginError } from '../api/client.js';
import { BrandSlot } from '../components/BrandSlot.js';

// ── Types ─────────────────────────────────────────────────────────────────────

export interface LoginPageProps {
  authMode?: { localEnabled: boolean; oidcEnabled: boolean };
}

// ── Styles (copied from SetupPage.tsx — UI-SPEC §Design System) ───────────────

const pageStyle: React.CSSProperties = {
  minHeight: '100dvh',
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'center',
  justifyContent: 'flex-start',
  background: 'var(--color-surface, #ffffff)',
  fontFamily: 'var(--font-family-base)',
  color: 'var(--color-text-primary, #111318)',
};

const contentColStyle: React.CSSProperties = {
  maxWidth: '400px', // login card is narrower than setup wizard (UI-SPEC Surface 1)
  width: '100%',
  margin: '0 auto',
  padding: 'var(--space-12, 48px) var(--space-6, 24px)',
};

const cardStyle: React.CSSProperties = {
  background: 'var(--color-surface, #ffffff)',
  border: '1px solid var(--color-border, #e2e4e9)',
  borderRadius: '8px',
  padding: 'var(--space-6, 24px)',
  boxShadow: '0 1px 4px rgba(0,0,0,0.06)',
};

const primaryBtnStyle = (disabled: boolean): React.CSSProperties => ({
  background: disabled ? 'var(--color-border, #e2e4e9)' : 'var(--color-member-0, #4a90d9)',
  color: '#ffffff',
  border: 'none',
  cursor: disabled ? 'default' : 'pointer',
  fontSize: 'var(--text-label-size, 13px)',
  fontWeight: 600,
  minHeight: '44px',
  minWidth: '44px',
  width: '100%',
  padding: '0 var(--space-6, 24px)',
  borderRadius: 'var(--space-1, 4px)',
  fontFamily: 'var(--font-family-base)',
  transition: 'background 0.15s ease',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  gap: 'var(--space-2, 8px)',
});

const inputStyle = (hasError: boolean): React.CSSProperties => ({
  width: '100%',
  boxSizing: 'border-box',
  padding: 'var(--space-3, 12px) var(--space-4, 16px)',
  border: `1px solid ${hasError ? 'var(--color-destructive, #dc2626)' : 'var(--color-border, #e2e4e9)'}`,
  borderRadius: 'var(--space-1, 4px)',
  fontSize: 'var(--text-body-size, 15px)',
  color: 'var(--color-text-primary, #111318)',
  background: 'var(--color-surface, #ffffff)',
  fontFamily: 'var(--font-family-base)',
  outline: 'none',
});

const labelStyle: React.CSSProperties = {
  display: 'block',
  fontSize: 'var(--text-label-size, 13px)',
  fontWeight: 600,
  color: 'var(--color-text-primary, #111318)',
  marginBottom: 'var(--space-1, 4px)',
};

// ── LoginPage ─────────────────────────────────────────────────────────────────

export function LoginPage({ authMode }: LoginPageProps) {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [showPassword, setShowPassword] = useState(false);
  const [loginError, setLoginError] = useState<
    'invalid' | 'rate-limit' | 'locked' | 'server' | null
  >(null);

  // Ref for moving focus to the error heading on error (UI-SPEC §Focus Management)
  const errorHeadingRef = useRef<HTMLDivElement>(null);
  // Ref for password field so Enter in username moves focus there
  const passwordRef = useRef<HTMLInputElement>(null);

  const oidcEnabled = authMode?.oidcEnabled ?? false;

  // Move focus to error banner heading when error state activates
  useEffect(() => {
    if (loginError && errorHeadingRef.current) {
      errorHeadingRef.current.focus();
    }
  }, [loginError]);

  const loginMutation = useMutation({
    mutationFn: () => fetchLocalLogin({ username, password }),
    onSuccess: () => {
      // Cookie is set by the API; replace to clear the /login URL from history
      window.location.replace('/');
    },
    onError: (err) => {
      if (err instanceof LoginError) {
        setLoginError(err.code);
      } else {
        setLoginError('server');
      }
    },
  });

  const isLoading = loginMutation.isPending;
  const bothNonEmpty = username.trim().length > 0 && password.length > 0;
  const submitDisabled =
    isLoading ||
    !bothNonEmpty ||
    loginError === 'rate-limit' ||
    loginError === 'locked';

  // Derive whether inputs should show error state
  const inputHasError = loginError === 'invalid';

  function handleSubmit() {
    if (submitDisabled) return;
    setLoginError(null);
    loginMutation.mutate();
  }

  function handleUsernameKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
    if (e.key === 'Enter') {
      e.preventDefault();
      passwordRef.current?.focus();
    }
  }

  function handlePasswordKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
    if (e.key === 'Enter') {
      e.preventDefault();
      handleSubmit();
    }
  }

  return (
    <div style={pageStyle}>
      <div style={contentColStyle} role="main">
        {/* Surface 2 — Brand Slot (above the login card, in the flow) */}
        <BrandSlot />

        {/* Surface 3 — Login Card */}
        <div style={cardStyle}>
          <h2
            style={{
              margin: '0 0 var(--space-6, 24px) 0',
              fontSize: 'var(--text-heading-size, 18px)',
              fontWeight: 600,
              lineHeight: 'var(--text-heading-line-height, 1.25)',
              color: 'var(--color-text-primary, #111318)',
            }}
          >
            Sign in
          </h2>

          {/* Surface 4 — Username field */}
          <div style={{ marginBottom: 'var(--space-4, 16px)' }}>
            <label htmlFor="login-username" style={labelStyle}>
              Username
            </label>
            <input
              id="login-username"
              type="text"
              autoFocus
              autoComplete="username"
              spellCheck={false}
              autoCapitalize="none"
              autoCorrect="off"
              value={username}
              onChange={(e) => setUsername(e.target.value)}
              onKeyDown={handleUsernameKeyDown}
              aria-describedby={loginError ? 'login-error' : undefined}
              style={inputStyle(inputHasError)}
            />
          </div>

          {/* Surface 5 — Password field with show/hide toggle */}
          <div style={{ marginBottom: 'var(--space-4, 16px)' }}>
            <label htmlFor="login-password" style={labelStyle}>
              Password
            </label>
            <div style={{ position: 'relative' }}>
              <input
                id="login-password"
                ref={passwordRef}
                type={showPassword ? 'text' : 'password'}
                autoComplete="current-password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                onKeyDown={handlePasswordKeyDown}
                onBlur={() => setShowPassword(false)}
                aria-describedby={loginError ? 'login-error' : undefined}
                style={{ ...inputStyle(inputHasError), paddingRight: '44px' }}
              />
              {/* Show/hide toggle button — 44px tap target (UI-SPEC Surface 5) */}
              <button
                type="button"
                aria-label={showPassword ? 'Hide password' : 'Show password'}
                aria-pressed={showPassword}
                onClick={() => setShowPassword((v) => !v)}
                style={{
                  position: 'absolute',
                  right: 0,
                  top: 0,
                  height: '100%',
                  minWidth: '44px',
                  background: 'none',
                  border: 'none',
                  cursor: 'pointer',
                  color: 'var(--color-text-muted, #9ca3af)',
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  padding: 0,
                }}
              >
                {showPassword ? (
                  <EyeOff size={16} aria-hidden="true" />
                ) : (
                  <Eye size={16} aria-hidden="true" />
                )}
              </button>
            </div>
          </div>

          {/* Surface 6 — Error / lockout banner */}
          {loginError && (
            <div
              id="login-error"
              role="status"
              aria-live="polite"
              aria-atomic="true"
              style={{ marginBottom: 'var(--space-4, 16px)' }}
            >
              {loginError === 'invalid' && (
                <div
                  ref={errorHeadingRef}
                  tabIndex={-1}
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: 'var(--space-2, 8px)',
                    fontSize: 'var(--text-body-size, 15px)',
                    fontWeight: 400,
                    color: 'var(--color-destructive, #dc2626)',
                    outline: 'none',
                  }}
                >
                  <AlertCircle size={16} aria-hidden="true" style={{ flexShrink: 0 }} />
                  Incorrect username or password.
                </div>
              )}

              {loginError === 'rate-limit' && (
                <div
                  ref={errorHeadingRef}
                  tabIndex={-1}
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: 'var(--space-2, 8px)',
                    background: 'var(--color-surface-dim, #f7f7f8)',
                    borderRadius: 'var(--space-1, 4px)',
                    padding: 'var(--space-3, 12px) var(--space-4, 16px)',
                    fontSize: 'var(--text-label-size, 13px)',
                    fontWeight: 400,
                    color: 'var(--color-destructive, #dc2626)',
                    outline: 'none',
                  }}
                >
                  <AlertCircle size={16} aria-hidden="true" style={{ flexShrink: 0 }} />
                  Too many attempts. Please wait a moment and try again.
                </div>
              )}

              {loginError === 'locked' && (
                <div
                  ref={errorHeadingRef}
                  tabIndex={-1}
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: 'var(--space-2, 8px)',
                    background: 'var(--color-surface-dim, #f7f7f8)',
                    borderRadius: 'var(--space-1, 4px)',
                    padding: 'var(--space-3, 12px) var(--space-4, 16px)',
                    fontSize: 'var(--text-label-size, 13px)',
                    fontWeight: 400,
                    color: 'var(--color-destructive, #dc2626)',
                    outline: 'none',
                  }}
                >
                  <AlertCircle size={16} aria-hidden="true" style={{ flexShrink: 0 }} />
                  This account is temporarily locked. Contact your admin to reset access.
                </div>
              )}

              {loginError === 'server' && (
                <div
                  ref={errorHeadingRef}
                  tabIndex={-1}
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: 'var(--space-2, 8px)',
                    fontSize: 'var(--text-body-size, 15px)',
                    fontWeight: 400,
                    color: 'var(--color-destructive, #dc2626)',
                    outline: 'none',
                  }}
                >
                  <AlertCircle size={16} aria-hidden="true" style={{ flexShrink: 0 }} />
                  Something went wrong. Please try again.
                </div>
              )}
            </div>
          )}

          {/* Surface 7 — Primary submit button */}
          <button
            type="button"
            onClick={handleSubmit}
            disabled={submitDisabled}
            style={primaryBtnStyle(submitDisabled)}
          >
            {isLoading && (
              <Loader2
                size={16}
                aria-hidden="true"
                style={{ animation: 'spin 1s linear infinite', flexShrink: 0 }}
              />
            )}
            {isLoading ? 'Signing in…' : 'Sign in'}
          </button>

          {/* Surface 10 — Forgot password helper (informational only, not interactive) */}
          <p
            style={{
              margin: 0,
              marginTop: 'var(--space-4, 16px)',
              fontSize: 'var(--text-label-size, 13px)',
              fontWeight: 400,
              color: 'var(--color-text-secondary, #6b7280)',
              textAlign: 'center',
              lineHeight: 'var(--text-label-line-height, 1.4)',
            }}
          >
            Forgot your password? Ask your admin.
          </p>
        </div>

        {/* Surfaces 8 & 9 — Method divider + OIDC button (only when oidcEnabled) */}
        {oidcEnabled && (
          <>
            {/* Surface 8 — Method divider */}
            <div
              aria-hidden="true"
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: 'var(--space-3, 12px)',
                marginTop: 'var(--space-4, 16px)',
                marginBottom: 'var(--space-4, 16px)',
              }}
            >
              <div
                style={{
                  flex: 1,
                  height: '1px',
                  background: 'var(--color-border, #e2e4e9)',
                }}
              />
              <span
                style={{
                  fontSize: 'var(--text-label-size, 13px)',
                  fontWeight: 400,
                  color: 'var(--color-text-secondary, #6b7280)',
                  flexShrink: 0,
                }}
              >
                or
              </span>
              <div
                style={{
                  flex: 1,
                  height: '1px',
                  background: 'var(--color-border, #e2e4e9)',
                }}
              />
            </div>

            {/* Surface 9 — OIDC login button — uses generic copy per D-06 */}
            <button
              type="button"
              onClick={() => {
                // Initiate OIDC authorization-code flow (same redirect as today's OIDC-only mode)
                window.location.href = '/api/login';
              }}
              style={{
                width: '100%',
                minHeight: '44px',
                background: 'transparent',
                border: '1px solid var(--color-member-0, #4a90d9)',
                color: 'var(--color-member-0, #4a90d9)',
                borderRadius: 'var(--space-1, 4px)',
                cursor: 'pointer',
                fontSize: 'var(--text-label-size, 13px)',
                fontWeight: 600,
                fontFamily: 'var(--font-family-base)',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                gap: 'var(--space-2, 8px)',
              }}
            >
              <ShieldCheck size={16} aria-hidden="true" />
              Login with OIDC
            </button>
          </>
        )}
      </div>
    </div>
  );
}
