"use client";

import { useState } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { Pencil, Shield, ShieldOff, UserPlus } from "lucide-react";
import { PageHeader, Breadcrumbs } from "@/components/shared/page-header";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { FormField } from "@/components/ui/form-field";
import { Badge } from "@/components/ui/badge";
import { Switch } from "@/components/ui/switch";
import { CheckboxField } from "@/components/ui/checkbox";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { ErrorState, TableSkeleton } from "@/components/shared/states";
import { ConfirmDialog } from "@/components/shared/confirm-dialog";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { getAdmins, storeAdmin, updateAdmin, toggleAdminActivation } from "@/services/profile";
import { getRoles } from "@/services/roles";
import { queryKeys } from "@/lib/query-keys";
import { useI18n, useT } from "@/i18n";
import { useCan } from "@/features/auth/use-can";
import { applyFieldErrors, friendlyErrorMessage } from "@/lib/errors";
import { formatDateTime } from "@/lib/format";
import type { Admin } from "@/types/admin";

const formSchema = z
  .object({
    name: z.string().min(1, "errors.required"),
    email: z.string().email("errors.email"),

    // The API requires this and holds it to E.164 — a number without the leading `+` is
    // refused. Checking it here means the person is told while they are looking at the
    // field, rather than by a 422 after they submit.
    phone: z.string().regex(/^\+[0-9]{8,15}$/, "errors.phoneFormat"),

    password: z.string().optional(),
    password_confirmation: z.string().optional(),

    // Optional, and the API refuses a date that is not in the past.
    date_of_birth: z.string().optional(),

    roles: z.array(z.string()).min(1, "errors.required"),
    is_active: z.boolean(),

    /**
     * Which form this is. Not rendered — it is what lets one schema hold both cases, because a
     * password is required to create an account and must be left alone when editing one.
     */
    mode: z.enum(["create", "edit"]),
  })
  .superRefine((values, context) => {
    // The server applies `confirmed`; without this the two never meet until the request fails,
    // which is how creating an administrator was silently impossible.
    if (values.password !== values.password_confirmation) {
      context.addIssue({
        code: "custom",
        path: ["password_confirmation"],
        message: "errors.passwordMismatch",
      });
    }

    if (values.mode !== "create") return;

    // Marked required on screen but optional in the schema was the whole bug: an empty password
    // passed this side and came back as a 422 whose only visible text was "check the data".
    if (!values.password) {
      context.addIssue({ code: "custom", path: ["password"], message: "errors.required" });
      return;
    }

    // `Password::defaults()` on the server is eight characters. Saying it here names the rule
    // while the field is still in front of them.
    if (values.password.length < PASSWORD_MIN) {
      context.addIssue({ code: "custom", path: ["password"], message: "errors.passwordTooShort" });
    }
  });

/** The server's own minimum, from `Password::defaults()`. */
const PASSWORD_MIN = 8;

/**
 * The inputs this form renders.
 *
 * A 422 can also carry a refusal about the caller rather than the data, and a form that counted
 * one of those as displayed would swallow the only message there was.
 */
const ADMIN_FIELDS = [
  "name",
  "email",
  "phone",
  "password",
  "password_confirmation",
  "date_of_birth",
  "roles",
];

type FormValues = z.infer<typeof formSchema>;

export default function SettingsAdminsPage() {
  const t = useT();
  const { locale } = useI18n();
  const { can } = useCan();
  const queryClient = useQueryClient();
  const [editing, setEditing] = useState<Admin | null>(null);
  const [creating, setCreating] = useState(false);
  const [toggling, setToggling] = useState<Admin | null>(null);

  const adminsQuery = useQuery({
    queryKey: queryKeys.admins({ page: 1, rows: 25 }),
    queryFn: () => getAdmins({ page: 1, rows: 25 }),
  });

  const rolesQuery = useQuery({
    queryKey: queryKeys.roles({ page: 1, rows: 25 }),
    queryFn: () => getRoles({ page: 1, rows: 25 }),
  });

  const roles = rolesQuery.data?.Model ?? [];

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    mode: "onTouched",
    defaultValues: { name: "", email: "", phone: "", password: "", roles: [], is_active: true, mode: "create" },
  });

  const dialogOpen = creating || editing !== null;

  function openCreate() {
    form.reset({ name: "", email: "", phone: "", password: "", roles: [], is_active: true, mode: "create" });
    setEditing(null);
    setCreating(true);
  }

  function openEdit(admin: Admin) {
    form.reset({
      name: admin.name,
      email: admin.email,
      phone: admin.phone ?? "",
      password: "",
      roles: admin.roles ?? [],
      is_active: admin.is_active,
      mode: "edit",
    });
    setCreating(false);
    setEditing(admin);
  }

  function closeDialog() {
    setCreating(false);
    setEditing(null);
  }

  function invalidate() {
    queryClient.invalidateQueries({ queryKey: ["admins"] });
  }

  async function handleSubmit(values: FormValues) {
    try {
      if (editing) {
        const response = await updateAdmin(editing.uuid, {
          name: values.name,
          email: values.email,
          phone: values.phone || null,
          date_of_birth: values.date_of_birth || null,
          roles: values.roles,
          is_active: values.is_active,
        });
        toast.success(response.Message || t("settings.adminSaved"));
      } else {
        const response = await storeAdmin({
          name: values.name,
          email: values.email,
          phone: values.phone || null,
          password: values.password || "",
          password_confirmation: values.password_confirmation || "",
          date_of_birth: values.date_of_birth || null,
          roles: values.roles,
          is_active: values.is_active,
        });
        toast.success(response.Message || t("settings.adminSaved"));
      }
      closeDialog();
      invalidate();
    } catch (error) {
      // The server refuses per field — a taken email, a phone in use, a password it judges weak.
      // Each message goes under its own input; the toast stays for everything else, including a
      // 422 that is about the caller rather than the data.
      const shown = applyFieldErrors(
        error,
        (field, message) => form.setError(field as never, { message }),
        { only: ADMIN_FIELDS, collapse: ["roles"] },
      );
      if (shown === 0) toast.error(friendlyErrorMessage(error, t));
    }
  }

  async function handleToggle(admin: Admin) {
    try {
      const response = await toggleAdminActivation(admin.uuid);
      toast.success(response.Message || (admin.is_active ? t("settings.adminDeactivated") : t("settings.adminActivated")));
      setToggling(null);
      invalidate();
    } catch (error) {
      toast.error(friendlyErrorMessage(error, t));
      setToggling(null);
    }
  }

  const canCreate = can("admins.create");
  const canUpdate = can("admins.update");

  return (
    <div className="mx-auto max-w-5xl">
      <Breadcrumbs items={[{ label: t("nav.settings"), href: "/settings" }, { label: t("settings.adminsTitle") }]} />
      <PageHeader
        title={t("settings.adminsTitle")}
        subtitle={t("settings.adminsSubtitle")}
        actions={
          canCreate ? (
            <Button onClick={openCreate}>
              <UserPlus className="h-4 w-4" aria-hidden />
              {t("common.create")}
            </Button>
          ) : null
        }
      />

      <Card>
        {adminsQuery.isLoading ? (
          <TableSkeleton rows={6} cols={5} />
        ) : adminsQuery.isError ? (
          <ErrorState message={friendlyErrorMessage(adminsQuery.error, t)} onRetry={() => adminsQuery.refetch()} />
        ) : (
          <div className="overflow-x-auto">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>{t("drivers.fieldName")}</TableHead>
                  <TableHead>{t("auth.email")}</TableHead>
                  <TableHead>{t("settings.rolesTitle")}</TableHead>
                  <TableHead>{t("common.status")}</TableHead>
                  <TableHead>{t("common.createdAt")}</TableHead>
                  <TableHead aria-label={t("common.actions")} />
                </TableRow>
              </TableHeader>
              <TableBody>
                {(adminsQuery.data?.Model ?? []).map((admin) => (
                  <TableRow key={admin.uuid}>
                    <TableCell className="font-medium text-foreground">{admin.name}</TableCell>
                    <TableCell dir="ltr" className="text-muted-foreground">{admin.email}</TableCell>
                    <TableCell>
                      <div className="flex max-w-[14rem] flex-wrap gap-1">
                        {admin.is_super_admin ? (
                          <Badge variant="primary">{t("settings.superAdminBadge")}</Badge>
                        ) : (admin.roles ?? []).length === 0 ? (
                          <span className="text-xs text-muted-foreground">—</span>
                        ) : (
                          (admin.roles ?? []).slice(0, 2).map((role) => (
                            <Badge key={role} variant="secondary">{role}</Badge>
                          ))
                        )}
                      </div>
                    </TableCell>
                    <TableCell>
                      <Badge variant={admin.is_active ? "success" : "secondary"}>
                        {admin.is_active ? t("common.active") : t("common.inactive")}
                      </Badge>
                    </TableCell>
                    <TableCell className="text-xs text-muted-foreground">
                      {formatDateTime(admin.created_at, locale)}
                    </TableCell>
                    <TableCell>
                      <div className="flex items-center gap-1">
                        {canUpdate ? (
                          <>
                            <Button variant="ghost" size="icon-sm" onClick={() => openEdit(admin)} aria-label={t("common.edit")}>
                              <Pencil className="h-4 w-4" />
                            </Button>
                            <Button
                              variant="ghost"
                              size="icon-sm"
                              onClick={() => setToggling(admin)}
                              aria-label={admin.is_active ? t("settings.deleteAdmin") : t("settings.activateAdmin")}
                            >
                              {admin.is_active ? (
                                <ShieldOff className="h-4 w-4 text-destructive" />
                              ) : (
                                <Shield className="h-4 w-4 text-success" />
                              )}
                            </Button>
                          </>
                        ) : null}
                      </div>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </div>
        )}
      </Card>

      <Dialog open={dialogOpen} onOpenChange={(open) => !open && closeDialog()}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>{creating ? t("common.create") : t("common.edit")} — {t("settings.adminsTitle")}</DialogTitle>
            <DialogDescription>{t("settings.adminsSubtitle")}</DialogDescription>
          </DialogHeader>
          <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4" noValidate>
            <FormField label={t("drivers.fieldName")} htmlFor="admin-name" required error={form.formState.errors.name?.message}>
              <Input id="admin-name" {...form.register("name")} />
            </FormField>
            <div className="grid gap-4 sm:grid-cols-2">
              <FormField label={t("auth.email")} htmlFor="admin-email" required error={form.formState.errors.email?.message}>
                <Input id="admin-email" type="email" dir="ltr" {...form.register("email")} />
              </FormField>
              <FormField
                label={t("drivers.fieldPhone")}
                htmlFor="admin-phone"
                required
                hint="+9665XXXXXXXX"
                error={form.formState.errors.phone?.message}
              >
                <Input id="admin-phone" dir="ltr" placeholder="+966500000000" {...form.register("phone")} />
              </FormField>
            </div>
            {creating ? (
              <div className="grid gap-4 sm:grid-cols-2">
                <FormField
                  label={t("auth.password")}
                  htmlFor="admin-password"
                  required
                  hint={t("settings.passwordMinHint", { min: String(PASSWORD_MIN) })}
                  error={form.formState.errors.password?.message}
                >
                  <Input id="admin-password" type="password" autoComplete="new-password" {...form.register("password")} />
                </FormField>
                <FormField
                  label={t("settings.passwordConfirmation")}
                  htmlFor="admin-password-confirmation"
                  required
                  error={form.formState.errors.password_confirmation?.message}
                >
                  <Input
                    id="admin-password-confirmation"
                    type="password"
                    autoComplete="new-password"
                    {...form.register("password_confirmation")}
                  />
                </FormField>
              </div>
            ) : null}

            <FormField
              label={t("settings.dateOfBirth")}
              htmlFor="admin-dob"
              hint={t("common.optional")}
              error={form.formState.errors.date_of_birth?.message}
            >
              <Input id="admin-dob" type="date" dir="ltr" {...form.register("date_of_birth")} />
            </FormField>
            {/* A group, but one control as far as the operator is concerned — so it carries its
                refusal the same way a text box does. */}
            <FormField
              label={t("settings.rolesTitle")}
              required
              error={form.formState.errors.roles?.message}
            >
              <div className="grid max-h-48 gap-2 overflow-y-auto rounded-lg border p-3 sm:grid-cols-2">
                {roles.length === 0 ? (
                  <p className="col-span-2 text-xs text-muted-foreground">{t("settings.rolesEmpty")}</p>
                ) : (
                  roles.map((role) => (
                    <CheckboxField
                      key={role.uuid}
                      id={`role-${role.uuid}`}
                      label={role.name}
                      checked={form.watch("roles")?.includes(role.name) ?? false}
                      onCheckedChange={(checked) => {
                        const current = form.getValues("roles");
                        form.setValue(
                          "roles",
                          checked ? Array.from(new Set([...current, role.name])) : current.filter((name) => name !== role.name),
                        );
                      }}
                    />
                  ))
                )}
              </div>
            </FormField>
            <div className="flex items-center justify-between rounded-lg border p-3">
              <div className="text-sm">
                <p className="font-medium text-foreground">{t("common.active")}</p>
                <p className="text-xs text-muted-foreground">{t("drivers.activeOnly")}</p>
              </div>
              <Switch
                checked={form.watch("is_active")}
                onCheckedChange={(checked) => form.setValue("is_active", checked)}
              />
            </div>
            <DialogFooter>
              <Button type="button" variant="outline" onClick={closeDialog}>
                {t("common.cancel")}
              </Button>
              <Button type="submit" loading={form.formState.isSubmitting}>
                {t("common.save")}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      <ConfirmDialog
        open={toggling !== null}
        onOpenChange={(open) => !open && setToggling(null)}
        title={
          toggling?.is_active
            ? t("settings.adminDeactivateConfirmTitle")
            : t("settings.adminActivateConfirmTitle")
        }
        description={toggling?.is_active ? t("settings.adminDeactivated") : t("settings.adminActivated")}
        confirmLabel={toggling?.is_active ? t("settings.deleteAdmin") : t("settings.activateAdmin")}
        destructive={toggling?.is_active}
        onConfirm={async () => {
          if (toggling) await handleToggle(toggling);
        }}
      />
    </div>
  );
}