"use client";

import { toastApiError } from "@/lib/toast-api-error";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { LogIn, Pencil, Plus, Trash2 } from "lucide-react";
import { toast } from "sonner";

import type { AccessUserRow } from "@/app/customer/_lib/admin/access-types";
import { customerCsrfHeader } from "@/lib/customer-csrf.client";
import { ErrorBanner } from "@/components/shared/error-banner";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";

type UsersPageClientProps = {
  tenant: string;
  initialUsers: AccessUserRow[];
  groups: Array<{ group_id: number; name: string }>;
  initialErrorMessage: string | null;
  canManageUsers?: boolean;
};

type UserFormState = {
  email: string;
  first_name: string;
  last_name: string;
  password: string;
  group_id: string;
  status: string;
};

export function UsersPageClient({
  tenant,
  initialUsers,
  groups,
  initialErrorMessage,
  canManageUsers = false,
}: UsersPageClientProps) {
  const router = useRouter();
  const [users, setUsers] = useState(initialUsers);
  const [dialogOpen, setDialogOpen] = useState(false);
  const [editingUser, setEditingUser] = useState<AccessUserRow | null>(null);
  const [form, setForm] = useState<UserFormState>({
    email: "",
    first_name: "",
    last_name: "",
    password: "",
    group_id: "",
    status: "active",
  });
  const [saving, setSaving] = useState(false);
  const createHref = `/customer/${tenant}/admin/users/create`;

  function openEdit(user: AccessUserRow) {
    setEditingUser(user);
    setForm({
      email: user.email,
      first_name: user.first_name ?? "",
      last_name: user.last_name ?? "",
      password: "",
      group_id: user.group_id ? String(user.group_id) : "",
      status: user.status,
    });
    setDialogOpen(true);
  }

  async function handleSave() {
    if (!editingUser) {
      return;
    }

    if (!form.email.trim()) {
      toast.error("Email is required.");
      return;
    }

    setSaving(true);
    try {
      const response = await fetch(`/customer/${tenant}/admin/users/${editingUser.id}`, {
        method: "POST",
        credentials: "same-origin",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
          ...customerCsrfHeader(tenant),
        },
        body: JSON.stringify({
          email: form.email.trim(),
          first_name: form.first_name.trim(),
          last_name: form.last_name.trim(),
          password: form.password.trim() || undefined,
          group_id: form.group_id && form.group_id !== "__none__" ? Number(form.group_id) : null,
          status: form.status,
          phone: editingUser.phone ?? "",
        }),
      });

      const data = (await response.json()) as { status?: string; message?: string };
      if (!response.ok || data.status !== "success") {
        throw new Error(data.message ?? "Could not save user.");
      }

      toast.success(data.message ?? "User saved.");
      setDialogOpen(false);
      router.refresh();
    } catch (error) {
      toastApiError(error, "Could not save user.");
    } finally {
      setSaving(false);
    }
  }

  async function handleDelete(user: AccessUserRow) {
    if (!window.confirm(`Delete user "${user.name}"?`)) {
      return;
    }

    try {
      const response = await fetch(`/customer/${tenant}/admin/users/${user.id}`, {
        method: "DELETE",
        credentials: "same-origin",
      });
      const data = (await response.json()) as { status?: string; message?: string };
      if (!response.ok || data.status !== "success") {
        throw new Error(data.message ?? "Could not delete user.");
      }

      setUsers((current) => current.filter((item) => item.id !== user.id));
      toast.success(data.message ?? "User deleted.");
      router.refresh();
    } catch (error) {
      toastApiError(error, "Could not delete user.");
    }
  }

  async function handleImpersonate(user: AccessUserRow) {
    if (!user.customer_uid) {
      toast.error("User is missing a portal identifier.");
      return;
    }

    try {
      const response = await fetch(`/customer/${tenant}/admin/users/impersonate`, {
        method: "POST",
        credentials: "same-origin",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
          ...customerCsrfHeader(tenant),
        },
        body: JSON.stringify({ customer_uid: user.customer_uid }),
      });
      const payload = (await response.json().catch(() => null)) as
        | {
            status?: string;
            message?: string;
            data?: {
              launch_url?: string;
              open_in_new_tab?: boolean;
            };
          }
        | null;

      if (!response.ok || payload?.status !== "success") {
        throw new Error(payload?.message ?? "Could not start impersonation.");
      }

      const launchUrl = payload.data?.launch_url;
      if (!launchUrl) {
        throw new Error("Impersonation launch URL was not returned.");
      }

      const opened = window.open(launchUrl, "_blank", "noopener,noreferrer");
      if (!opened) {
        throw new Error("Pop-up blocked. Allow pop-ups for this site and try again.");
      }
    } catch (error) {
      toastApiError(error, "Could not impersonate user.");
    }
  }

  if (initialErrorMessage) {
    return <ErrorBanner message={initialErrorMessage} />;
  }

  return (
    <div className="flex flex-col gap-4">
      <div className="flex items-center justify-between gap-3">
        <div>
          <h1 className="text-2xl font-semibold tracking-tight">Users</h1>
          <p className="text-sm text-muted-foreground">
            {canManageUsers
              ? "Manage sub-users and assign each user a permission role."
              : "Portal users are managed by the corporate account."}
          </p>
        </div>
        {canManageUsers ? (
          <Button asChild>
            <Link href={createHref}>
              <Plus />
              New user
            </Link>
          </Button>
        ) : null}
      </div>

      <div className="rounded-xl border">
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>Name</TableHead>
              <TableHead>Email</TableHead>
              <TableHead>Role</TableHead>
              <TableHead>Status</TableHead>
              <TableHead className="text-right">Actions</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {users.length === 0 ? (
              <TableRow>
                <TableCell colSpan={5} className="py-8 text-center text-muted-foreground">
                  No sub-users yet.
                </TableCell>
              </TableRow>
            ) : (
              users.map((user) => (
                <TableRow key={user.id}>
                  <TableCell className="font-medium">{user.name}</TableCell>
                  <TableCell>{user.email}</TableCell>
                  <TableCell>{user.group_name ?? <span className="text-muted-foreground">Unassigned</span>}</TableCell>
                  <TableCell>
                    <Badge variant={user.status === "active" ? "secondary" : "outline"}>{user.status}</Badge>
                  </TableCell>
                  <TableCell className="text-right">
                    <div className="flex justify-end gap-2">
                      {user.can_impersonate && user.customer_uid ? (
                        <Button
                          size="sm"
                          variant="outline"
                          type="button"
                          onClick={() => void handleImpersonate(user)}
                        >
                          <LogIn />
                          Impersonate
                        </Button>
                      ) : null}
                      {canManageUsers ? (
                        <>
                          <Button size="sm" variant="outline" onClick={() => openEdit(user)}>
                            <Pencil />
                            Edit
                          </Button>
                          <Button size="sm" variant="outline" onClick={() => void handleDelete(user)}>
                            <Trash2 />
                            Delete
                          </Button>
                        </>
                      ) : null}
                    </div>
                  </TableCell>
                </TableRow>
              ))
            )}
          </TableBody>
        </Table>
      </div>

      <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Edit user</DialogTitle>
            <DialogDescription>Update the user&apos;s profile, role, and optional password.</DialogDescription>
          </DialogHeader>

          <div className="grid gap-4">
            <div className="grid gap-2">
              <Label htmlFor="user-email">Email</Label>
              <Input
                id="user-email"
                type="email"
                value={form.email}
                onChange={(event) => setForm((current) => ({ ...current, email: event.target.value }))}
              />
            </div>
            <div className="grid gap-4 sm:grid-cols-2">
              <div className="grid gap-2">
                <Label htmlFor="user-first-name">First name</Label>
                <Input
                  id="user-first-name"
                  value={form.first_name}
                  onChange={(event) => setForm((current) => ({ ...current, first_name: event.target.value }))}
                />
              </div>
              <div className="grid gap-2">
                <Label htmlFor="user-last-name">Last name</Label>
                <Input
                  id="user-last-name"
                  value={form.last_name}
                  onChange={(event) => setForm((current) => ({ ...current, last_name: event.target.value }))}
                />
              </div>
            </div>
            <div className="grid gap-2">
              <Label htmlFor="user-password">New password (optional)</Label>
              <Input
                id="user-password"
                type="password"
                value={form.password}
                onChange={(event) => setForm((current) => ({ ...current, password: event.target.value }))}
              />
            </div>
            <div className="grid gap-2">
              <Label>Role</Label>
              <Select
                value={form.group_id || "__none__"}
                onValueChange={(value) => setForm((current) => ({ ...current, group_id: value === "__none__" ? "" : value }))}
              >
                <SelectTrigger>
                  <SelectValue placeholder="Select a role" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="__none__">Unassigned</SelectItem>
                  {groups.map((group) => (
                    <SelectItem key={group.group_id} value={String(group.group_id)}>
                      {group.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={() => setDialogOpen(false)}>
              Cancel
            </Button>
            <Button onClick={() => void handleSave()} disabled={saving}>
              {saving ? "Saving..." : "Save user"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
