"use client";

import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { AuditApi } from "@/lib/api";
import { PanelError } from "@/components/medora/errors";
import { MedoraPageHeader } from "@/components/medora/page-header";
import { ListTable, Tag, type Col } from "@/components/medora/record-lists";
import { Button } from "@/components/ui/button";
import { Field, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { toast } from "@/components/ui/toast";
import { Loading } from "@/components/medora/loading";

/**
 * SuperAdmin → Login logs (plan O: the SuperAdmin pages on the design). Sign-ins, wrong passwords and lockouts in
 * every pharmacy, from the audit log (`action` matches LOGIN_SUCCESS, LOGIN_FAILED and LOGIN_LOCKED). As the design's
 * activity log does, the dates are fetched from the server and the search and filters narrow what is loaded.
 */

interface AuditLog {
    id: number;
    userName: string;
    action: string;
    ipAddress: string;
    details: string;
    createdAt: string;
    pharmacy?: { id: number; name: string } | null;
}

const LIMIT = 1000;
const pad = (n: number) => String(n).padStart(2, "0");
const when = (s: string) => {
    const d = new Date(s);
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
};
const EVENTS: Record<string, { label: string; tone: "ok" | "warn" | "bad" | "neutral" }> = {
    LOGIN_SUCCESS: { label: "Signed in", tone: "ok" },
    LOGIN_FAILED: { label: "Wrong password", tone: "warn" },
    LOGIN_LOCKED: { label: "Locked out", tone: "bad" },
};
const event = (action: string) => EVENTS[action] ?? { label: action.toLowerCase().replace(/_/g, " ").replace(/^./, (c) => c.toUpperCase()), tone: "neutral" as const };
const pharmacyOf = (l: AuditLog) => l.pharmacy?.name ?? "No pharmacy";

const cols: Col<AuditLog>[] = [
    { key: "at", header: "When", cell: (l) => <span className="tabular-nums whitespace-nowrap">{when(l.createdAt)}</span> },
    { key: "pharmacy", header: "Pharmacy", cell: (l) => (l.pharmacy ? l.pharmacy.name : <span className="text-muted-foreground">No pharmacy</span>) },
    { key: "user", header: "User", cell: (l) => l.userName || "—" },
    { key: "event", header: "Event", cell: (l) => <Tag tone={event(l.action).tone}>{event(l.action).label}</Tag> },
    { key: "ip", header: "IP address", cell: (l) => <span className="font-mono text-xs">{l.ipAddress || "—"}</span> },
    { key: "details", header: "Details", cell: (l) => <span className="block max-w-xs truncate text-muted-foreground" title={l.details}>{l.details}</span> },
];

export default function LoginLogsPage() {
    const router = useRouter();
    const [logs, setLogs] = useState<AuditLog[] | null>(null);
    const [failed, setFailed] = useState(false); // R12 (card 037): a failed load says so, with Try again
    const [attempt, setAttempt] = useState(0);
    const [total, setTotal] = useState(0);
    const [from, setFrom] = useState("");
    const [to, setTo] = useState("");

    useEffect(() => {
        // Guard: only SuperAdmin can access this page
        if (typeof window !== "undefined") {
            const userStr = localStorage.getItem("user");
            const user = userStr ? JSON.parse(userStr) : null;
            if (!user || user.role !== "SuperAdmin") router.push("/login");
        }
    }, [router]);

    // Changing the dates shows the loading state at once; the effect sets state only when the request answers
    const pick = (f: string, t: string) => { setLogs(null); setFrom(f); setTo(t); };

    useEffect(() => {
        let live = true;
        AuditApi.getAll({ action: "LOGIN", from: from || undefined, to: to || undefined, limit: LIMIT, page: 1 })
            .then((res) => {
                if (!live) return;
                setLogs(res.logs ?? []);
                setTotal(res.total ?? 0);
                setFailed(false);
            })
            .catch((e) => {
                if (!live) return;
                setLogs([]);
                setFailed(true);
                const m = (e as { response?: { data?: { message?: string } } })?.response?.data?.message;
                toast.add({ type: "error", title: "Couldn't load the login logs", description: m || "Try again." });
            });
        return () => { live = false; };
    }, [from, to, attempt]);

    const capped = logs !== null && total > logs.length;

    return (
        <div className="space-y-6">
            <MedoraPageHeader
                title="Login logs"
                description="Sign-ins, wrong passwords and lockouts in every pharmacy."
                meta={logs ? [capped ? `Latest ${logs.length.toLocaleString()} of ${total.toLocaleString()}` : `${logs.length.toLocaleString()} entries`] : []}
                metaLoading={logs === null}
            />

            <div className="flex flex-wrap items-end gap-3">
                <Field className="w-auto">
                    <FieldLabel htmlFor="ll-from">From</FieldLabel>
                    <Input id="ll-from" type="date" value={from} max={to || undefined} onChange={(e) => pick(e.target.value, to)} />
                </Field>
                <Field className="w-auto">
                    <FieldLabel htmlFor="ll-to">To</FieldLabel>
                    <Input id="ll-to" type="date" value={to} min={from || undefined} onChange={(e) => pick(from, e.target.value)} />
                </Field>
                {(from || to) && <Button variant="ghost" onClick={() => pick("", "")}>Clear dates</Button>}
            </div>

            {failed ? (
                <PanelError framed what="the login logs" onRetry={() => setAttempt((n) => n + 1)} />
            ) : logs === null ? (
                <Loading what="login logs" columns={6} rows={8} toolbar={2} />
            ) : (
                <>
                    <ListTable
                        rows={logs}
                        cols={cols}
                        rowKey={(l) => String(l.id)}
                        search={{ placeholder: "Search user, IP or details", text: (l) => [l.userName, l.ipAddress, l.details, pharmacyOf(l)].join(" ") }}
                        filters={[
                            { label: "Pharmacy", all: "All pharmacies", value: pharmacyOf },
                            { label: "Event", all: "All events", value: (l) => event(l.action).label },
                        ]}
                        empty={logs.length ? "No entry matches." : "No sign-ins recorded for these dates."}
                        minWidth="min-w-[860px]"
                    />
                    {capped && <p className="text-xs text-muted-foreground">Showing the latest {LIMIT.toLocaleString()}. Choose dates to look further back.</p>}
                </>
            )}
        </div>
    );
}
