'use client';

import { signIn } from "next-auth/react";
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import dynamic from 'next/dynamic';
import Image from 'next/image';
import { TwoFactorModal } from '@/components/auth/TwoFactorModal';
import { Button } from '@/components/ui';

// Hotfix: LoginBackground is purely decorative and uses Math.random()
// + framer-motion + RAF. Rendering it on the server creates SSR/CSR
// mismatches that abort hydration of the whole route — which leaves
// the form as raw HTML, which (without the other layers below) would
// cause the browser to do a native GET submit and put the password in
// the URL. ssr:false makes it strictly client-side, so a crash inside
// it cannot take down hydration of the form.
const LoginBackground = dynamic(() => import('@/components/auth/LoginBackground'), {
    ssr: false,
});

export default function PageContent() {
    // Hotfix: inputs are controlled by React state and the credential
    // fields below carry no `name` attribute. Without a name, a native
    // HTML form submit (which happens if React fails to hydrate for any
    // reason — e.g. an exception in a decorative client component)
    // cannot serialise these fields into the URL or POST body. This is
    // the load-bearing fix: it makes credential URL-leak structurally
    // impossible, not just unlikely.
    const [username, setUsername] = useState('admin');
    const [password, setPassword] = useState('');
    const [loading, setLoading] = useState(false);
    const [pendingToken, setPendingToken] = useState<string | null>(null);
    const [errorMessage, setErrorMessage] = useState<string>('');
    const router = useRouter();

    const handleGoogleLogin = () => {
        setLoading(true);
        signIn('google', { callbackUrl: '/dashboard' });
    };

    async function exchangeSessionToken(sessionToken: string) {
        const res = await signIn('credentials', {
            redirect: false,
            sessionToken,
        });
        if (res?.error) {
            setErrorMessage('Session exchange failed. Please try again.');
            setLoading(false);
            setPendingToken(null);
            return;
        }
        router.push('/dashboard');
    }

    // Accepts both React.FormEvent (Enter-key submit via <form onSubmit>)
    // and React.MouseEvent (button click). Values come from state, not
    // from the DOM, so there is no `form.elements` lookup that depends
    // on `name=` attributes.
    async function handleCredentialsLogin(e?: React.FormEvent | React.MouseEvent) {
        e?.preventDefault();
        if (loading) return;
        setLoading(true);
        setErrorMessage('');

        try {
            const res = await fetch('/api/auth/login', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: JSON.stringify({ username, password }),
            });
            const data = await res.json();

            if (!res.ok) {
                setErrorMessage(data?.message || data?.error || 'Sign-in failed');
                setLoading(false);
                return;
            }

            if (data.needs2FA && data.pendingToken) {
                setPendingToken(data.pendingToken);
                return;
            }

            if (data.sessionToken) {
                await exchangeSessionToken(data.sessionToken);
                return;
            }

            setErrorMessage('Unexpected response from server.');
            setLoading(false);
        } catch (err) {
            setErrorMessage(err instanceof Error ? err.message : 'Network error');
            setLoading(false);
        }
    }

    return (
        <div className="relative min-h-screen flex flex-col items-center justify-center p-4 font-sans">

            <LoginBackground />

            <div className="relative z-10 w-full max-w-md bg-white rounded-2xl shadow-[0_20px_60px_-15px_rgba(15,27,61,0.25)] p-8 border border-[#0F1B3D]/8">

                <div className="text-center mb-6">
                    <span className="inline-block px-3 py-1 rounded-full bg-[#EC008C]/10 text-[#EC008C] text-xs font-semibold tracking-wide mb-4">
                        Uptime Sentinel
                    </span>
                    <div className="flex items-center justify-center mb-3">
                        <Image
                            src="/login.png"
                            alt="Evidence Action"
                            width={160}
                            height={40}
                            priority
                            // Tailwind h-10 + w-auto control the rendered size; the explicit
                            // width/height props above set the INTRINSIC ratio. Adding
                            // height:auto in style preserves the aspect ratio per Next.js'
                            // Image warning.
                            style={{ height: 'auto' }}
                            className="h-10 w-auto object-contain"
                        />
                    </div>
                    <h1 className="text-2xl font-bold text-[#0F1B3D] tracking-tight" aria-hidden="true">{' '}</h1>
                    <p className="text-sm text-slate-500 mt-1">Sign in to monitor your network</p>
                </div>

                <div className="space-y-4">
                    {/*
                      * method="post" is belt-and-suspenders only. The form's
                      * onSubmit handler calls preventDefault before any
                      * navigation happens, AND the inputs below have no
                      * `name=` attribute, so a native fallback couldn't
                      * serialise creds anyway. method="post" is the third
                      * line of defence: if both earlier layers somehow
                      * fail, the browser would POST to the current URL with
                      * an empty body instead of GETting with creds in the
                      * query string.
                      */}
                    <form method="post" onSubmit={handleCredentialsLogin} className="space-y-3">
                        <div>
                            <label htmlFor="login-username" className="block text-xs font-semibold text-[#0F1B3D] mb-1.5">Username</label>
                            <input
                                id="login-username"
                                type="text"
                                autoComplete="username"
                                value={username}
                                onChange={(e) => setUsername(e.target.value)}
                                className="w-full h-11 px-4 rounded-xl bg-white border border-slate-200 focus:outline-none focus:ring-2 focus:ring-[#EC008C]/30 focus:border-[#EC008C] transition-all text-sm text-[#0F1B3D] placeholder:text-slate-400"
                                placeholder="Enter username"
                            />
                        </div>

                        <div>
                            <label htmlFor="login-password" className="block text-xs font-semibold text-[#0F1B3D] mb-1.5">Password</label>
                            <input
                                id="login-password"
                                type="password"
                                autoComplete="current-password"
                                value={password}
                                onChange={(e) => setPassword(e.target.value)}
                                className="w-full h-11 px-4 rounded-xl bg-white border border-slate-200 focus:outline-none focus:ring-2 focus:ring-[#EC008C]/30 focus:border-[#EC008C] transition-all text-sm text-[#0F1B3D] placeholder:text-slate-400"
                                placeholder="Enter password"
                            />
                        </div>

                        {errorMessage && (
                            <div className="text-xs text-red-600 bg-red-50 border border-red-200 rounded-lg px-3 py-2">
                                {errorMessage}
                            </div>
                        )}

                        {/*
                          * type="button" + onClick so the button is NEVER
                          * a form submitter. Combined with no name= on
                          * inputs, even a hydration failure cannot put
                          * credentials in the URL. The wrapping <form
                          * onSubmit> still fires on Enter-key for UX, but
                          * its handler calls preventDefault before any
                          * fetch begins.
                          */}
                        <Button
                            type="button"
                            variant="primary"
                            size="lg"
                            onClick={handleCredentialsLogin}
                            disabled={loading}
                            className="w-full bg-[#0F1B3D] hover:bg-[#1a2654] text-white font-semibold rounded-xl shadow-lg shadow-[#0F1B3D]/15 active:scale-[0.98] text-sm"
                        >
                            {loading ? 'Signing in...' : 'Sign In'}
                        </Button>
                    </form>

                    <div className="relative flex py-1 items-center">
                        <div className="flex-grow border-t border-slate-200"></div>
                        <span className="flex-shrink mx-3 text-slate-400 text-xs font-medium">or</span>
                        <div className="flex-grow border-t border-slate-200"></div>
                    </div>

                    <Button
                        type="button"
                        variant="outline"
                        size="lg"
                        onClick={handleGoogleLogin}
                        disabled={loading}
                        className="w-full bg-white border-slate-200 rounded-xl hover:bg-slate-50 font-semibold text-[#0F1B3D] active:scale-[0.98] text-sm"
                    >
                        {/* react-doctor-disable-next-line react-doctor/nextjs-no-img-element
                            External SVG from svgrepo.com — using next/image
                            would require adding the host to next.config's
                            images.remotePatterns. Keeping <img> as the
                            lower-friction option for a 24x24 brand glyph. */}
                        <img src="https://www.svgrepo.com/show/475656/google-color.svg" className="size-4" alt="Google" />
                        Continue with Google
                    </Button>
                </div>

                <p className="text-center text-xs text-slate-500 mt-6">
                    Don&apos;t have an account? <span className="text-[#EC008C] font-semibold cursor-pointer hover:underline">Contact Admin</span>
                </p>
            </div>

            {pendingToken && (
                <TwoFactorModal
                    pendingToken={pendingToken}
                    onSuccess={(sessionToken) => {
                        setPendingToken(null);
                        void exchangeSessionToken(sessionToken);
                    }}
                    onCancel={() => {
                        setPendingToken(null);
                        setLoading(false);
                    }}
                />
            )}

        </div>
    );
}
