"use client";

import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import Image from "next/image";
import { ArrowLeft, RefreshCw, X, Delete, Server, CheckCircle2, AlertCircle, EyeIcon, EyeOffIcon } from "lucide-react";
import { AuthApi, getApiBase, setApiBase, getApiBaseSource, normaliseApiBase } from "@/lib/api";
import { electronApi, useIsDesktop } from "@/lib/desktop";
import BrandMark from "@/app/components/BrandMark";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { Skeleton } from "@/components/ui/skeleton";
import { toast } from "@/components/ui/toast";

// ─── Supermarket-Grade PIN Keypad ─────────────────────────────────────────────
function PinKeypad({ pin, onChange }: { pin: string; onChange: (pin: string) => void }) {
    const keys = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];

    const handleKey = (k: string) => {
        if (k === "DEL") {
            onChange(pin.slice(0, -1));
        } else {
            // Allow up to 32 characters (supports both PIN and full passwords)
            if (pin.length < 32) onChange(pin + k);
        }
    };

    return (
        <div className="w-full">
            {/* PIN Display */}
            <div className="flex items-center justify-center gap-2 mb-5 min-h-[48px]">
                {pin.length === 0 ? (
                    <span className="text-gray-300 text-sm font-medium tracking-widest">Enter password</span>
                ) : (
                    pin.split("").map((_, i) => (
                        <div
                            key={i}
                            className="w-3.5 h-3.5 rounded-full bg-gray-800 shadow-sm transition-all duration-150 scale-100"
                        />
                    ))
                )}
            </div>

            {/* Number Grid */}
            <div className="grid grid-cols-3 gap-3">
                {keys.map((k) => (
                    <button
                        key={k}
                        type="button"
                        onClick={() => handleKey(k)}
                        className={`
                            flex items-center justify-center rounded-2xl text-2xl font-bold text-gray-800
                            bg-white border border-gray-100 shadow-sm
                            hover:bg-gray-50 hover:border-gray-200 hover:shadow-md
                            active:scale-95 active:bg-gray-100
                            transition-all duration-100 select-none
                            ${k === "0" ? "col-start-2" : ""}
                        `}
                        style={{ height: "68px" }}
                    >
                        {k}
                    </button>
                ))}

                {/* Backspace — col 3, row 4 */}
                <button
                    type="button"
                    onClick={() => handleKey("DEL")}
                    className="flex items-center justify-center rounded-2xl text-gray-400 bg-white border border-gray-100 shadow-sm hover:bg-red-50 hover:text-red-500 hover:border-red-100 active:scale-95 transition-all duration-100 select-none"
                    style={{ height: "68px" }}
                >
                    <Delete className="w-6 h-6" />
                </button>
            </div>
        </div>
    );
}

// ─── Main Login Page ──────────────────────────────────────────────────────────
/**
 * Lets an installed desktop app be pointed at a different API server without rebuilding it.
 * Lives on the login screen because a wrong URL means you cannot sign in to reach Settings.
 */
function ServerSettings({ onClose }: { onClose: () => void }) {
    // Opened only on a click, so reading the browser here can't differ from a server render
    const [value, setValue] = useState(() => getApiBase());
    const [source, setSource] = useState<string>(() => getApiBaseSource());
    const [configPath, setConfigPath] = useState("");
    const [testing, setTesting] = useState(false);
    const [result, setResult] = useState<{ ok: boolean; message: string } | null>(null);

    useEffect(() => {
        electronApi()?.getConfigPath?.().then(setConfigPath).catch(() => {});
    }, []);

    // Any HTTP reply proves we reached the API; only a network failure means unreachable.
    const test = async (url: string) => {
        const target = normaliseApiBase(url);
        if (!target) return { ok: false, message: "That does not look like a valid address." };
        try {
            const res = await fetch(`${target}/auth/cashiers`, { method: "GET" });
            return res.status >= 200 && res.status < 500
                ? { ok: true, message: `Reached the server at ${target}` }
                : { ok: false, message: `Server answered with an error (${res.status}).` };
        } catch {
            return { ok: false, message: "Could not reach that server. Check the address and that the API is running." };
        }
    };

    const handleTest = async () => {
        setTesting(true);
        setResult(await test(value));
        setTesting(false);
    };

    const handleSave = async () => {
        setTesting(true);
        const check = await test(value);
        setResult(check);
        setTesting(false);
        if (!check.ok) return;
        setApiBase(value);
        setSource(getApiBaseSource());
        setTimeout(onClose, 700);
    };

    const handleReset = () => {
        setApiBase("");
        setValue(getApiBase());
        setSource(getApiBaseSource());
        setResult(null);
    };

    const sourceLabel: Record<string, string> = {
        saved: "saved on this machine",
        desktop: "from the desktop config file",
        build: "built into this app",
        default: "the default server",
    };

    return (
        <Dialog open onOpenChange={(open) => { if (!open) onClose(); }}>
            <DialogContent className="sm:max-w-md">
                <DialogHeader>
                    <DialogTitle>Server settings</DialogTitle>
                    <DialogDescription>The Medora server this app signs in to.</DialogDescription>
                </DialogHeader>
                <Field>
                    <FieldLabel htmlFor="server-address">API address</FieldLabel>
                    <Input
                        id="server-address"
                        value={value}
                        onChange={e => { setValue(e.target.value); setResult(null); }}
                        placeholder="http://192.168.1.10:3001/api"
                        spellCheck={false}
                        autoFocus
                        className="font-mono"
                    />
                    <FieldDescription>
                        Currently using {sourceLabel[source]}. Leave off <span className="font-mono">http://</span> and it will be added.
                    </FieldDescription>
                </Field>
                {result && (
                    <Alert variant={result.ok ? "default" : "destructive"}>
                        {result.ok ? <CheckCircle2 /> : <AlertCircle />}
                        <AlertDescription>{result.message}</AlertDescription>
                    </Alert>
                )}
                {configPath && <p className="break-all text-xs text-muted-foreground">Config file: {configPath}</p>}
                <DialogFooter className="sm:justify-between">
                    <Button variant="ghost" onClick={handleReset}>Reset to the default server</Button>
                    <div className="flex gap-2">
                        <Button variant="outline" onClick={handleTest} disabled={testing}>{testing ? "Checking…" : "Test connection"}</Button>
                        <Button onClick={handleSave} disabled={testing}>Save</Button>
                    </div>
                </DialogFooter>
            </DialogContent>
        </Dialog>
    );
}

// Shown until the client has mounted and detected web vs desktop, so the form never flashes the wrong layout.
function LoginSkeleton() {
    return (
        <div className="grid min-h-dvh grid-cols-1 md:grid-cols-2" role="status" aria-busy="true" aria-label="Loading login">
            <div className="hidden bg-primary md:block" />
            <div className="flex items-center justify-center p-8">
                <div className="w-full max-w-sm space-y-5">
                    <div className="space-y-2"><Skeleton className="h-7 w-24" /><Skeleton className="h-4 w-56" /></div>
                    <div className="space-y-2"><Skeleton className="h-4 w-36" /><Skeleton className="h-9 w-full" /></div>
                    <div className="space-y-2"><Skeleton className="h-4 w-20" /><Skeleton className="h-9 w-full" /></div>
                    <Skeleton className="h-10 w-full" />
                </div>
            </div>
        </div>
    );
}

/** A profile remembered on this desktop for the picker (pharmapos_cached_users): no password or hash. */
type CachedUser = { id?: number; name: string; username: string; role?: string; initials?: string };

function LoginPageInner({ onServer }: { onServer?: () => void }) {
    const router = useRouter();
    const [username, setUsername] = useState("");
    const [password, setPassword] = useState("");
    const [showPw, setShowPw] = useState(false);
    const [loading, setLoading] = useState(false);
    // Shown inline on the desktop PIN pad; the form shows sign-in failures as a toast (the design's Toaster)
    const [error, setError] = useState("");
    const [mounted, setMounted] = useState(false);

    // Desktop UI states
    const isDesktop = useIsDesktop();
    const [cachedUsers, setCachedUsers] = useState<CachedUser[]>([]);
    const [pharmacyName, setPharmacyName] = useState("");
    const [selectedUser, setSelectedUser] = useState<CachedUser | null>(null);
    const [useManualLogin, setUseManualLogin] = useState(false);
    const [currentTime, setCurrentTime] = useState("");
    const [pin, setPin] = useState("");

    useEffect(() => {
        if (typeof window !== "undefined") {
            setMounted(true);

            try {
                const users = JSON.parse(localStorage.getItem("pharmapos_cached_users") || "[]");
                setCachedUsers(users);
                setPharmacyName(localStorage.getItem("pharmapos_pharmacy_name") || "PrismPOS");
            } catch {}
        }
    }, []);

    useEffect(() => {
        const updateClock = () => {
            const now = new Date();
            setCurrentTime(
                now.toLocaleDateString("en-GB", { weekday: "short", day: "2-digit", month: "short", year: "numeric" }) +
                " · " +
                now.toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit", second: "2-digit" })
            );
        };
        updateClock();
        const timer = setInterval(updateClock, 1000);
        return () => clearInterval(timer);
    }, []);

    // The design keeps Sign in disabled until both fields are filled, so there is nothing to validate per field
    const ready = username.trim() !== "" && password.trim() !== "";
    const handleFormSubmit = (e: React.FormEvent) => {
        e.preventDefault();
        if (loading || !ready) return;
        handleLogin();
    };

    const handleLogin = async (e?: React.FormEvent, directUsername?: string, directPassword?: string) => {
        if (e) e.preventDefault();
        setError("");
        setLoading(true);

        const targetUser = (directUsername || username).trim();
        const targetPass = (directPassword || password).trim();

        try {
            const { access_token, user } = await AuthApi.login(targetUser, targetPass);
            localStorage.setItem("token", access_token);
            localStorage.setItem("user", JSON.stringify(user));

            if (typeof window !== "undefined") {
                try {
                    const cached = JSON.parse(localStorage.getItem("pharmapos_cached_users") || "[]");
                    const exists = cached.some((u: CachedUser) => u.username === user.username);
                    if (!exists) {
                        const initials = user.name
                            ? user.name.split(" ").map((w: string) => w[0]).join("").slice(0, 2).toUpperCase()
                            : user.username.slice(0, 2).toUpperCase();
                        const updated = [...cached, { id: user.id, name: user.name || user.username, username: user.username, role: user.role, initials }];
                        localStorage.setItem("pharmapos_cached_users", JSON.stringify(updated));
                        setCachedUsers(updated);
                    }
                } catch {}
            }

            if (user.role === "SuperAdmin") {
                router.push("/admin/pharmacies");
            } else {
                router.push("/dashboard");
            }
        } catch (err) {
            const message = (err as { response?: { data?: { message?: string } } })?.response?.data?.message || "Invalid credentials or password";
            setError(message);
            // The form shows it as a toast; the PIN pad shows `error` inline
            if (!selectedUser) toast.add({ type: "error", title: "Couldn't sign in", description: message });
            setPassword("");
            setPin("");
        } finally {
            setLoading(false);
        }
    };

    const handleRemoveProfile = (usernameToRemove: string) => {
        const updated = cachedUsers.filter((u) => u.username !== usernameToRemove);
        setCachedUsers(updated);
        if (typeof window !== "undefined") {
            localStorage.setItem("pharmapos_cached_users", JSON.stringify(updated));
        }
        if (selectedUser?.username === usernameToRemove) {
            setSelectedUser(null);
            setPin("");
        }
    };

    // Auto-submit when pin reaches a reasonable length (optional: 6+ chars)
    const handlePinChange = (newPin: string) => {
        setPin(newPin);
        setError("");
    };

    const handlePinSubmit = () => {
        if (!selectedUser || !pin) return;
        handleLogin(undefined, selectedUser.username, pin);
    };

    if (!mounted) return <LoginSkeleton />;

    // ─── Desktop: Cashier Profile Selector ────────────────────────────────────
    if (isDesktop && !useManualLogin && cachedUsers.length > 0) {

        // ── Password Entry view (PIN keypad) ───────────────────────────────────
        if (selectedUser) {
            const initials = selectedUser.initials || (selectedUser.name
                ? selectedUser.name.split(" ").map((w: string) => w[0]).join("").slice(0, 2).toUpperCase()
                : selectedUser.username.slice(0, 2).toUpperCase());

            return (
                <div
                    className="min-h-screen w-screen flex flex-col select-none"
                    style={{ background: "radial-gradient(ellipse at 50% 0%, #fee2e2 0%, #fef2f2 30%, #ffffff 70%)" }}
                >
                    <header className="bg-white/80 backdrop-blur-md border-b border-gray-100 px-8 py-4 flex items-center justify-between shrink-0 shadow-sm">
                        <div className="flex items-center gap-3">
                            <BrandMark size={36} className="shadow-sm rounded-xl" />
                            <div>
                                <h2 className="text-sm font-black tracking-wide text-gray-900">{pharmacyName}</h2>
                                <p className="text-[10px] text-gray-500 -mt-0.5">PrismPOS Terminals</p>
                            </div>
                        </div>
                        <span className="text-xs font-mono text-gray-500 font-semibold">{currentTime}</span>
                    </header>

                    <div className="flex-1 flex items-center justify-center p-6">
                        <div className="w-full max-w-xs">
                            {/* Back */}
                            <button
                                onClick={() => { setSelectedUser(null); setPin(""); setError(""); }}
                                className="flex items-center gap-1.5 text-sm text-gray-400 hover:text-gray-700 font-semibold mb-6 transition"
                            >
                                <ArrowLeft className="w-4 h-4" />
                                <span>All Profiles</span>
                            </button>

                            {/* User card */}
                            <div className="text-center mb-6">
                                <div className="w-20 h-20 rounded-full bg-red-50 border-2 border-red-100 text-red-600 flex items-center justify-center text-2xl font-black mx-auto mb-3 shadow-sm">
                                    {initials}
                                </div>
                                <h2 className="text-xl font-black text-gray-900">{selectedUser.name || selectedUser.username}</h2>
                                <p className="text-sm text-gray-400 font-medium">{selectedUser.role}</p>
                            </div>

                            {/* Error */}
                            {error && (
                                <div className="bg-red-50 border border-red-200 text-red-700 text-xs rounded-xl px-4 py-2.5 mb-4 text-center font-semibold">
                                    {error}
                                </div>
                            )}

                            {/* PIN Keypad */}
                            <PinKeypad pin={pin} onChange={handlePinChange} />

                            {/* Login Button */}
                            <button
                                onClick={handlePinSubmit}
                                disabled={loading || !pin}
                                className="mt-4 w-full bg-red-600 hover:bg-red-700 disabled:opacity-40 text-white font-black py-4 rounded-2xl text-base transition flex items-center justify-center gap-2 shadow-md active:scale-[0.98]"
                            >
                                {loading ? (
                                    <div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
                                ) : "Sign In"}
                            </button>

                            <button
                                onClick={() => setUseManualLogin(true)}
                                className="mt-4 w-full text-center text-xs text-gray-400 hover:text-gray-600 font-semibold transition"
                            >
                                Use keyboard instead
                            </button>
                        </div>
                    </div>
                    {onServer && <FloatingServerButton onClick={onServer} />}
                </div>
            );
        }

        // ── Profile Grid view ──────────────────────────────────────────────────
        return (
            <div
                className="min-h-screen w-screen flex flex-col select-none"
                style={{ background: "radial-gradient(ellipse at 50% 0%, #fee2e2 0%, #fef2f2 30%, #ffffff 70%)" }}
            >
                <header className="bg-white/80 backdrop-blur-md border-b border-gray-100 px-8 py-4 flex items-center justify-between shrink-0 shadow-sm">
                    <div className="flex items-center gap-3">
                        <BrandMark size={36} className="shadow-sm rounded-xl" />
                        <div>
                            <h2 className="text-sm font-black tracking-wide text-gray-900">{pharmacyName}</h2>
                            <p className="text-[10px] text-gray-500 -mt-0.5">PrismPOS Terminals</p>
                        </div>
                    </div>
                    <span className="text-xs font-mono text-gray-500 font-semibold">{currentTime}</span>
                </header>

                <div className="flex-1 flex flex-col items-center justify-center p-8">
                    <h1 className="text-2xl font-black text-gray-900 mb-1">Select Your Profile</h1>
                    <p className="text-sm text-gray-400 mb-10 font-medium">Tap your name to log in</p>

                    {/* Large Profile Cards Grid */}
                    <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-5 w-full max-w-3xl">
                        {cachedUsers.map((u) => {
                            const initials = u.initials || (u.name
                                ? u.name.split(" ").map((w: string) => w[0]).join("").slice(0, 2).toUpperCase()
                                : u.username.slice(0, 2).toUpperCase());
                            return (
                                <div key={u.username} className="relative group">
                                    <button
                                        onClick={() => { setSelectedUser(u); setPin(""); setError(""); }}
                                        className="w-full bg-white border border-gray-100 hover:border-red-100 hover:shadow-lg rounded-3xl p-7 flex flex-col items-center justify-center transition-all duration-200 active:scale-95 shadow-sm group-hover:-translate-y-1"
                                    >
                                        {/* Large Avatar */}
                                        <div className="w-20 h-20 rounded-full bg-red-50 text-red-600 group-hover:bg-red-100 group-hover:text-red-700 flex items-center justify-center mb-4 text-2xl font-black border-2 border-red-100 transition-colors shadow-sm">
                                            {initials}
                                        </div>
                                        <span className="text-base font-black text-gray-900 truncate w-full block text-center leading-tight">{u.name || u.username}</span>
                                        <span className="text-xs text-red-500 font-bold mt-1.5 bg-red-50 px-2.5 py-0.5 rounded-full">{u.role}</span>
                                    </button>

                                    {/* Remove badge */}
                                    <button
                                        onClick={(e) => { e.stopPropagation(); handleRemoveProfile(u.username); }}
                                        title="Remove saved profile"
                                        className="absolute -top-2 -right-2 w-7 h-7 bg-white hover:bg-red-50 hover:text-red-600 border border-gray-200 rounded-full flex items-center justify-center text-gray-400 transition opacity-0 group-hover:opacity-100 focus:opacity-100 z-10 shadow-md"
                                    >
                                        <X className="w-3.5 h-3.5" />
                                    </button>
                                </div>
                            );
                        })}
                    </div>

                    <button
                        onClick={() => setUseManualLogin(true)}
                        className="mt-12 text-sm text-gray-400 hover:text-red-600 font-bold transition flex items-center gap-2 mx-auto"
                    >
                        <RefreshCw className="w-4 h-4" />
                        <span>Login with username & password</span>
                    </button>
                </div>
                {onServer && <FloatingServerButton onClick={onServer} />}
            </div>
        );
    }

    // ─── Web / Manual Login: the design's login layout (design system → Layout and screens → Login, D-4) ───
    return (
        <div className="grid min-h-dvh grid-cols-1 md:grid-cols-2">
            <div className="hidden flex-col justify-between border-r border-border bg-primary p-10 text-primary-foreground md:flex">
                <Image src="/medora-teal-logo.svg" alt="Medora" width={884} height={238} priority unoptimized className="h-9 w-auto self-start" />
                <div className="space-y-2">
                    <p className="text-2xl leading-8 font-semibold">Run the till, the shelves and the books from one place.</p>
                    <p className="text-sm opacity-80">Point of sale, inventory with batch expiry, prescriptions and accounts.</p>
                </div>
                <p className="text-xs opacity-70">© Medora systems {new Date().getFullYear()}</p>
            </div>
            <div className="flex items-center justify-center p-8">
                <form className="w-full max-w-sm space-y-5" onSubmit={handleFormSubmit} noValidate>
                    {isDesktop && (
                        <button
                            type="button"
                            onClick={() => { setUseManualLogin(false); setError(""); }}
                            className="flex cursor-pointer items-center gap-1 text-sm text-muted-foreground hover:text-foreground"
                        >
                            <ArrowLeft className="size-4" />Profiles
                        </button>
                    )}
                    <Image src="/medora-logo.svg" alt="Medora" width={884} height={238} unoptimized className="h-8 w-auto md:hidden" />
                    <div>
                        <h1 className="text-xl font-semibold">Sign in</h1>
                        <p className="mt-1 text-sm text-muted-foreground">Use your email or username.</p>
                    </div>
                    <Field>
                        <FieldLabel htmlFor="login-username">Email or username</FieldLabel>
                        <Input id="login-username" autoComplete="username" autoFocus value={username} disabled={loading} onChange={(e) => setUsername(e.target.value)} />
                    </Field>
                    <Field>
                        <FieldLabel htmlFor="login-password">Password</FieldLabel>
                        <div className="relative">
                            <Input id="login-password" type={showPw ? "text" : "password"} autoComplete="current-password" value={password} disabled={loading} onChange={(e) => setPassword(e.target.value)} className="pr-10" />
                            <button
                                type="button"
                                onClick={() => setShowPw(!showPw)}
                                aria-label={showPw ? "Hide password" : "Show password"}
                                disabled={loading}
                                className="absolute inset-y-0 right-0 flex cursor-pointer items-center px-3 text-muted-foreground hover:text-foreground disabled:cursor-not-allowed"
                            >
                                {showPw ? <EyeOffIcon className="size-4" /> : <EyeIcon className="size-4" />}
                            </button>
                        </div>
                    </Field>
                    <Button type="submit" size="lg" className="w-full" disabled={!ready || loading}>{loading ? "Signing in…" : "Sign in"}</Button>
                    <div className="flex items-center justify-between text-sm">
                        <button
                            type="button"
                            onClick={() => toast.add({ title: "Forgot your password?", description: "Ask your administrator to reset it." })}
                            className="cursor-pointer text-muted-foreground underline-offset-4 hover:underline"
                        >
                            Forgot password?
                        </button>
                        {/* Desktop only: the web build is pointed at its server by its deployment (see LoginPage below) */}
                        {onServer && (
                            <button type="button" onClick={onServer} className="flex cursor-pointer items-center gap-1 text-muted-foreground hover:text-foreground">
                                <Server className="size-4" />Server
                            </button>
                        )}
                    </div>
                </form>
            </div>
        </div>
    );
}

/** The design's Server link, floated over the desktop profile picker and PIN pad, which have no form to hold it. */
function FloatingServerButton({ onClick }: { onClick: () => void }) {
    return (
        <button
            onClick={onClick}
            className="fixed bottom-4 right-4 z-40 flex items-center gap-1.5 px-3 py-1.5 text-[11px] font-semibold text-gray-500 bg-white/80 backdrop-blur border border-gray-200 rounded-full shadow-sm hover:text-gray-900 hover:border-gray-300 transition"
        >
            <Server className="w-3.5 h-3.5" /> Server
        </button>
    );
}

/**
 * Three layouts: the sign-in form (on the design, D-4) and, on desktop with saved profiles, the profile picker and
 * the PIN pad (unchanged: the design has no screen for them yet, as passcode sign-in waits for its design input,
 * plan C Q2). The Server setting is desktop only: the web build is pointed by its own deployment, and a stray server
 * field would only confuse pharmacy staff. The form shows it as the design's link; the other two float it.
 */
export default function LoginPage() {
    const isDesktop = useIsDesktop();
    const [showServer, setShowServer] = useState(false);

    return (
        <>
            <LoginPageInner onServer={isDesktop ? () => setShowServer(true) : undefined} />
            {showServer && <ServerSettings onClose={() => setShowServer(false)} />}
        </>
    );
}
