"use client";

import * as React from "react";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import { Ban, Check, LogOut, MoreHorizontal, Save, Trash2, UserCheck, UserX, Minus, RotateCcw, Smartphone, Monitor, Tablet } from "lucide-react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Card, CardHeader, CardContent } from "@/components/ui/card";
import { Tooltip } from "@/components/ui/primitives";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { useConfirm } from "@/components/ui/confirm";
import { EmptyState } from "@/components/ui/states";
import { PERMISSIONS, PERMISSION_MODULES } from "@/lib/permissions";
import { relativeTime, fmtDateTime } from "@/lib/dates";
import { setWorkerStatus, deleteWorker, setUserPermissionOverrides, revokeSession } from "@/lib/actions/workers";

export function WorkerStatusControls({ worker, isAdmin }: { worker: { id: string; fullName: string; status: string; roleKey: string }; isAdmin: boolean }) {
  const router = useRouter();
  const confirm = useConfirm();
  async function setStatus(s: "ACTIVE" | "INACTIVE" | "SUSPENDED") {
    const { ok, reason } = await confirm({ title: `${s === "ACTIVE" ? "Activate" : s === "INACTIVE" ? "Deactivate" : "Suspend"} ${worker.fullName}?`, description: s === "ACTIVE" ? "The worker can sign in again." : "All sessions are signed out immediately. History is kept.", destructive: s !== "ACTIVE", requireReason: true, consequences: s !== "ACTIVE" ? ["Active sessions are revoked.", "Pending commissions stay pending until handled."] : undefined });
    if (!ok) return;
    const res = await setWorkerStatus(worker.id, s, reason ?? "");
    if (!res.ok) return toast.error(res.error);
    toast.success("Status updated");
    router.refresh();
  }
  async function remove() {
    const { ok, reason } = await confirm({ title: `Delete ${worker.fullName}?`, description: "The account is archived; reservations, commissions and audit entries remain attributed.", destructive: true, requireReason: true, confirmLabel: "Delete account" });
    if (!ok) return;
    const res = await deleteWorker(worker.id, reason ?? "");
    if (!res.ok) return toast.error(res.error);
    toast.success("Worker deleted");
    router.push("/workers");
  }
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="secondary" size="icon" aria-label="Worker actions">
          <MoreHorizontal />
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end" className="w-52">
        {worker.status !== "ACTIVE" ? (
          <DropdownMenuItem onSelect={() => setStatus("ACTIVE")}>
            <UserCheck /> Activate
          </DropdownMenuItem>
        ) : null}
        {worker.status !== "INACTIVE" ? (
          <DropdownMenuItem onSelect={() => setStatus("INACTIVE")}>
            <UserX /> Deactivate
          </DropdownMenuItem>
        ) : null}
        {worker.status !== "SUSPENDED" ? (
          <DropdownMenuItem destructive onSelect={() => setStatus("SUSPENDED")}>
            <Ban /> Suspend
          </DropdownMenuItem>
        ) : null}
        {isAdmin && worker.roleKey !== "ADMIN" ? (
          <>
            <DropdownMenuSeparator />
            <DropdownMenuItem destructive onSelect={remove}>
              <Trash2 /> Delete account
            </DropdownMenuItem>
          </>
        ) : null}
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

type Tri = true | false | null;

export function PermissionsEditor({ userId, isAdminRole, roleName, rolePerms, overrides }: { userId: string; isAdminRole: boolean; roleName: string; rolePerms: string[]; overrides: Record<string, boolean> }) {
  const router = useRouter();
  const confirm = useConfirm();
  const roleSet = React.useMemo(() => new Set(rolePerms), [rolePerms]);
  const [state, setState] = React.useState<Record<string, Tri>>(() => Object.fromEntries(PERMISSIONS.map((p) => [p.key, p.key in overrides ? overrides[p.key] : null])));
  const [busy, setBusy] = React.useState(false);
  const dirty = PERMISSIONS.some((p) => (state[p.key] ?? null) !== (p.key in overrides ? overrides[p.key] : null));
  const effective = (k: string) => (state[k] === null || state[k] === undefined ? roleSet.has(k) : state[k]);

  async function save() {
    const changed = Object.fromEntries(PERMISSIONS.filter((p) => (state[p.key] ?? null) !== (p.key in overrides ? overrides[p.key] : null)).map((p) => [p.key, state[p.key]]));
    const { ok, reason } = await confirm({ title: "Apply permission changes?", description: `${Object.keys(changed).length} permission${Object.keys(changed).length > 1 ? "s" : ""} will change for this worker. The admin is notified and the change is audited.`, requireReason: true, confirmLabel: "Apply" });
    if (!ok) return;
    setBusy(true);
    const res = await setUserPermissionOverrides(userId, changed, reason);
    setBusy(false);
    if (!res.ok) return toast.error(res.error);
    toast.success("Permissions updated");
    router.refresh();
  }

  if (isAdminRole) return <Card padded><EmptyState compact title="Administrators have every permission" description="Admin access cannot be restricted. Change the role to limit access." /></Card>;

  return (
    <Card>
      <CardHeader
        title="Permission overrides"
        description={`Inherited from the ${roleName} role. Grant extra permissions or revoke inherited ones for this worker only.`}
        action={
          <div className="flex items-center gap-2">
            {dirty ? (
              <Button variant="ghost" size="sm" onClick={() => setState(Object.fromEntries(PERMISSIONS.map((p) => [p.key, p.key in overrides ? overrides[p.key] : null])))}>
                <RotateCcw /> Reset
              </Button>
            ) : null}
            <Button size="sm" onClick={save} disabled={!dirty} loading={busy}>
              <Save /> Save changes
            </Button>
          </div>
        }
      />
      <CardContent>
        <div className="mb-3 flex flex-wrap gap-3 text-2xs text-fg-muted">
          <span className="flex items-center gap-1"><span className="size-3 rounded border border-border bg-surface" /> Inherit from role</span>
          <span className="flex items-center gap-1"><span className="size-3 rounded bg-positive-500" /> Granted</span>
          <span className="flex items-center gap-1"><span className="size-3 rounded bg-negative-500" /> Revoked</span>
        </div>
        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          {PERMISSION_MODULES.map((m) => {
            const perms = PERMISSIONS.filter((p) => p.module === m.key);
            if (!perms.length) return null;
            return (
              <div key={m.key} className="rounded-lg border border-border">
                <div className="flex items-center justify-between border-b border-border bg-surface-2/60 px-3 py-2">
                  <span className="text-xs font-semibold">{m.label}</span>
                  <span className="text-2xs text-fg-muted">{perms.filter((p) => effective(p.key)).length}/{perms.length}</span>
                </div>
                <ul className="divide-y divide-border">
                  {perms.map((p) => {
                    const v = state[p.key] ?? null;
                    const inherited = roleSet.has(p.key);
                    const eff = effective(p.key);
                    return (
                      <li key={p.key} className={cn("flex items-center gap-2 px-3 py-1.5 text-xs", eff ? "text-fg" : "text-fg-muted")}>
                        <span className="min-w-0 flex-1">
                          <span className="block">{p.label}</span>
                          <span className="block text-2xs text-fg-subtle">
                            {inherited ? "in role" : "not in role"}
                            {p.sensitive ? " · sensitive" : ""}
                          </span>
                        </span>
                        <div className="flex overflow-hidden rounded-md border border-border">
                          <Tooltip content="Inherit">
                            <button type="button" onClick={() => setState({ ...state, [p.key]: null })} className={cn("px-1.5 py-1", v === null ? "bg-surface-3" : "hover:bg-surface-2")} aria-label="Inherit">
                              <Minus className="size-3" />
                            </button>
                          </Tooltip>
                          <Tooltip content="Grant">
                            <button type="button" onClick={() => setState({ ...state, [p.key]: true })} className={cn("px-1.5 py-1", v === true ? "bg-positive-500 text-white" : "hover:bg-surface-2")} aria-label="Grant">
                              <Check className="size-3" />
                            </button>
                          </Tooltip>
                          <Tooltip content="Revoke">
                            <button type="button" onClick={() => setState({ ...state, [p.key]: false })} className={cn("px-1.5 py-1", v === false ? "bg-negative-500 text-white" : "hover:bg-surface-2")} aria-label="Revoke">
                              <Ban className="size-3" />
                            </button>
                          </Tooltip>
                        </div>
                      </li>
                    );
                  })}
                </ul>
              </div>
            );
          })}
        </div>
      </CardContent>
    </Card>
  );
}

export function SessionsList({ sessions, canRevoke }: { sessions: { id: string; device: string | null; browser: string | null; ipAddress: string | null; createdAt: string; lastSeenAt: string; revokedAt: string | null; current: boolean }[]; canRevoke: boolean }) {
  const router = useRouter();
  const confirm = useConfirm();
  async function revoke(id: string) {
    const { ok } = await confirm({ title: "Sign out this session?", description: "The device will need to sign in again.", confirmLabel: "Sign out" });
    if (!ok) return;
    const res = await revokeSession(id);
    if (!res.ok) return toast.error(res.error);
    toast.success("Session revoked");
    router.refresh();
  }
  const live = sessions.filter((s) => !s.revokedAt);
  if (live.length === 0) return <EmptyState compact title="No active sessions" />;
  return (
    <ul className="divide-y divide-border">
      {live.map((s) => {
        const Icon = s.device?.startsWith("Mobile") ? Smartphone : s.device?.startsWith("Tablet") ? Tablet : Monitor;
        const online = Date.now() - new Date(s.lastSeenAt).getTime() < 3 * 60_000;
        return (
          <li key={s.id} className="flex items-center gap-3 py-2.5 text-sm">
            <span className="flex size-9 items-center justify-center rounded-md bg-surface-2 text-fg-muted">
              <Icon className="size-4" />
            </span>
            <span className="min-w-0 flex-1">
              <span className="flex items-center gap-2">
                <span className="font-medium">{s.device ?? "Unknown device"}</span>
                <span className="text-fg-muted">· {s.browser}</span>
                {s.current ? <span className="rounded-full bg-primary/10 px-1.5 text-2xs text-primary">this device</span> : null}
                {online ? <span className="size-2 rounded-full bg-positive-500" title="Active" /> : null}
              </span>
              <span className="block text-xs text-fg-subtle">
                Started {fmtDateTime(s.createdAt)} · active {relativeTime(s.lastSeenAt)} · {s.ipAddress}
              </span>
            </span>
            {canRevoke && !s.current ? (
              <Button variant="ghost" size="iconXs" onClick={() => revoke(s.id)} title="Sign out">
                <LogOut />
              </Button>
            ) : null}
          </li>
        );
      })}
    </ul>
  );
}
