import { type FormEvent, useEffect, useMemo, useRef, useState } from 'react';
import { Navigate, useSearchParams } from 'react-router';
import { useAuthStore } from './auth-store';
import { api } from '../api/client';
import { config } from '../config';
import { Card, Input, Button, Alert, FormField } from '@cameleer/design-system';
import styles from './LoginPage.module.css';

interface OidcInfo {
  clientId: string;
  authorizationEndpoint: string;
}

/** Generate a random code_verifier for PKCE (RFC 7636). */
function generateCodeVerifier(): string {
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  return btoa(String.fromCharCode(...array))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

/** Derive the S256 code_challenge from a code_verifier. */
async function deriveCodeChallenge(verifier: string): Promise<string> {
  const data = new TextEncoder().encode(verifier);
  const digest = await crypto.subtle.digest('SHA-256', data);
  return btoa(String.fromCharCode(...new Uint8Array(digest)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

const SUBTITLES = [
  "Prove you're not a mirage",
  "Only authorized cameleers beyond this dune",
  "Halt, traveler — state your business",
  "The caravan doesn't move without credentials",
  "No hitchhikers on this caravan",
  "This oasis requires a password",
  "Camels remember faces. We use passwords.",
  "You shall not pass... without logging in",
  "The desert is vast. Your session has expired.",
  "Another day, another dune to authenticate",
  "Papers, please. The caravan master is watching.",
  "Trust, but verify — ancient cameleer proverb",
  "Even the Silk Road had checkpoints",
  "Your camel is parked outside. Now identify yourself.",
  "One does not simply walk into the dashboard",
  "The sands shift, but your password shouldn't",
  "Unauthorized access? In this economy?",
  "Welcome back, weary traveler",
  "The dashboard awaits on the other side of this dune",
  "Keep calm and authenticate",
  "Who goes there? Friend or rogue exchange?",
  "Access denied looks the same in every desert",
  "May your routes be green and your tokens valid",
  "Forgot your password? That's between you and the dunes.",
  "No ticket, no caravan",
];

export function LoginPage() {
  const { isAuthenticated, login, loading, error } = useAuthStore();
  const [searchParams] = useSearchParams();
  const forceLocal = searchParams.has('local');
  const subtitle = useMemo(() => SUBTITLES[Math.floor(Math.random() * SUBTITLES.length)], []);
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [oidc, setOidc] = useState<OidcInfo | null>(null);
  const [oidcLoading, setOidcLoading] = useState(false);
  const autoRedirected = useRef(false);

  useEffect(() => {
    api.GET('/auth/oidc/config')
      .then(({ data }) => {
        if (data?.authorizationEndpoint && data?.clientId) {
          setOidc({ clientId: data.clientId, authorizationEndpoint: data.authorizationEndpoint });
          if (data.endSessionEndpoint) {
            localStorage.setItem('cameleer-oidc-end-session', data.endSessionEndpoint);
          }
        }
      })
      .catch(() => {});
  }, []);

  // Auto-redirect to OIDC provider for SSO (skip if ?local is in URL)
  useEffect(() => {
    if (oidc && !forceLocal && !autoRedirected.current) {
      autoRedirected.current = true;
      const redirectUri = `${window.location.origin}${config.basePath}oidc/callback`;
      const verifier = generateCodeVerifier();
      sessionStorage.setItem('oidc-code-verifier', verifier);
      deriveCodeChallenge(verifier).then((challenge) => {
        const params = new URLSearchParams({
          response_type: 'code',
          client_id: oidc.clientId,
          redirect_uri: redirectUri,
          scope: 'openid email profile',
          prompt: 'none',
          code_challenge: challenge,
          code_challenge_method: 'S256',
        });
        window.location.href = `${oidc.authorizationEndpoint}?${params}`;
      });
    }
  }, [oidc, forceLocal]);

  if (isAuthenticated) return <Navigate to="/" replace />;

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    login(username, password);
  };

  const handleOidcLogin = async () => {
    if (!oidc) return;
    setOidcLoading(true);
    const redirectUri = `${window.location.origin}${config.basePath}oidc/callback`;
    const verifier = generateCodeVerifier();
    sessionStorage.setItem('oidc-code-verifier', verifier);
    const challenge = await deriveCodeChallenge(verifier);
    const params = new URLSearchParams({
      response_type: 'code',
      client_id: oidc.clientId,
      redirect_uri: redirectUri,
      scope: 'openid email profile',
      code_challenge: challenge,
      code_challenge_method: 'S256',
    });
    window.location.href = `${oidc.authorizationEndpoint}?${params}`;
  };

  return (
    <div className={styles.page}>
      <Card className={styles.card}>
        <div className={styles.loginForm}>
          <div className={styles.logo}>
            <img src={`${config.basePath}favicon.svg`} alt="" className={styles.logoImg} />
            cameleer3
          </div>
          <p className={styles.subtitle}>{subtitle}</p>

          {error && (
            <div className={styles.error}>
              <Alert variant="error">{error}</Alert>
            </div>
          )}

          {oidc && (
            <>
              <div className={styles.socialSection}>
                <Button
                  variant="secondary"
                  className={styles.ssoButton}
                  onClick={handleOidcLogin}
                  disabled={oidcLoading}
                  type="button"
                >
                  {oidcLoading ? 'Redirecting...' : 'Sign in with SSO'}
                </Button>
              </div>
              <div className={styles.divider}>
                <div className={styles.dividerLine} />
                <span className={styles.dividerText}>or</span>
                <div className={styles.dividerLine} />
              </div>
            </>
          )}

          <form className={styles.fields} onSubmit={handleSubmit} aria-label="Sign in" noValidate>
            <FormField label="Username" htmlFor="login-username">
              <Input
                id="login-username"
                value={username}
                onChange={(e) => setUsername(e.target.value)}
                placeholder="Enter your username"
                autoFocus
                autoComplete="username"
                disabled={loading}
              />
            </FormField>

            <FormField label="Password" htmlFor="login-password">
              <Input
                id="login-password"
                type="password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                placeholder="••••••••"
                autoComplete="current-password"
                disabled={loading}
              />
            </FormField>

            <Button
              variant="primary"
              type="submit"
              loading={loading}
              disabled={loading || !username || !password}
              className={styles.submitButton}
            >
              Sign in
            </Button>
          </form>
        </div>
      </Card>
    </div>
  );
}
