"use client";

import { useEffect, useMemo, useState } from "react";
import { useTranslations } from "next-intl";
import { Check, Eye, Loader2, Search, Sparkles } from "lucide-react";
import Button from "@/components/ui/Button";
import Input from "@/components/ui/Input";
import Modal from "@/components/ui/Modal";
import { HelpTooltip, LabelWithHint } from "@/components/ui/Tooltip";

interface Permission {
  id: string;
  name: string;
  module: string;
  action: string;
  description: string | null;
}

interface RoleOption {
  id: string;
  name: string;
  permissions: { permission: Permission }[];
}

interface RoleFormModalProps {
  open: boolean;
  isEdit: boolean;
  initial: { name: string; description: string; permissionIds: string[] };
  allPerms: Permission[];
  roles: RoleOption[];
  saving: boolean;
  onClose: () => void;
  onSubmit: (form: { name: string; description: string; permissionIds: string[] }) => void;
}

const ACTION_ORDER = ["view", "create", "update", "delete"] as const;

function friendlyAction(action: string) {
  return action.charAt(0).toUpperCase() + action.slice(1);
}

export default function RoleFormModal({
  open,
  isEdit,
  initial,
  allPerms,
  roles,
  saving,
  onClose,
  onSubmit,
}: RoleFormModalProps) {
  const t = useTranslations("roles");
  const tc = useTranslations("common");
  const [form, setForm] = useState(initial);
  const [permSearch, setPermSearch] = useState("");
  const [copyFromId, setCopyFromId] = useState("");

  useEffect(() => {
    if (!open) return;
    setForm(initial);
    setPermSearch("");
    setCopyFromId("");
    // Reset only when the modal opens — avoid wiping edits if parent re-renders.
    // eslint-disable-next-line react-hooks/exhaustive-deps -- intentional
  }, [open]);

  const groupedPerms = useMemo(() => {
    const q = permSearch.trim().toLowerCase();
    const filtered = q
      ? allPerms.filter(
          (p) =>
            p.module.toLowerCase().includes(q) ||
            p.action.toLowerCase().includes(q) ||
            p.name.toLowerCase().includes(q) ||
            (p.description?.toLowerCase().includes(q) ?? false)
        )
      : allPerms;

    return filtered.reduce<Record<string, Permission[]>>((acc, p) => {
      acc[p.module] = acc[p.module] ?? [];
      acc[p.module].push(p);
      return acc;
    }, {});
  }, [allPerms, permSearch]);

  const viewOnlyIds = useMemo(
    () => allPerms.filter((p) => p.action === "view").map((p) => p.id),
    [allPerms]
  );

  const allIds = useMemo(() => allPerms.map((p) => p.id), [allPerms]);

  function togglePerm(permId: string) {
    setForm((f) => ({
      ...f,
      permissionIds: f.permissionIds.includes(permId)
        ? f.permissionIds.filter((id) => id !== permId)
        : [...f.permissionIds, permId],
    }));
  }

  function setModuleSelection(modulePerms: Permission[], selectAll: boolean) {
    const ids = modulePerms.map((p) => p.id);
    setForm((f) => {
      const without = f.permissionIds.filter((id) => !ids.includes(id));
      return { ...f, permissionIds: selectAll ? [...without, ...ids] : without };
    });
  }

  function applyPreset(kind: "view" | "all" | "none") {
    if (kind === "view") setForm((f) => ({ ...f, permissionIds: [...viewOnlyIds] }));
    if (kind === "all") setForm((f) => ({ ...f, permissionIds: [...allIds] }));
    if (kind === "none") setForm((f) => ({ ...f, permissionIds: [] }));
  }

  function copyFromRole(roleId: string) {
    setCopyFromId(roleId);
    const role = roles.find((r) => r.id === roleId);
    if (!role) return;
    setForm((f) => ({
      ...f,
      permissionIds: role.permissions.map((rp) => rp.permission.id),
    }));
  }

  if (!open) return null;

  const moduleEntries = Object.entries(groupedPerms).map(([module, perms]) => {
    const sorted = [...perms].sort((a, b) => {
      const ai = ACTION_ORDER.indexOf(a.action as (typeof ACTION_ORDER)[number]);
      const bi = ACTION_ORDER.indexOf(b.action as (typeof ACTION_ORDER)[number]);
      return (ai === -1 ? 99 : ai) - (bi === -1 ? 99 : bi);
    });
    return [module, sorted] as const;
  });

  return (
    <Modal
      wide
      title={isEdit ? t("editRole") : t("createRole")}
      description={t("formEasyHint")}
      onClose={onClose}
    >
      <form
        onSubmit={(e) => {
          e.preventDefault();
          onSubmit(form);
        }}
        className="flex min-h-0 flex-1 flex-col overflow-hidden"
      >
        <div className="min-h-0 flex-1 space-y-5 overflow-y-auto px-5 py-5 sm:px-6">
          <section className="grid gap-3.5 sm:grid-cols-2">
            <Input
              label={t("roleName")}
              hint={t("roleNameHint")}
              hintLabel={tc("helpLabel")}
              value={form.name}
              onChange={(e) => setForm({ ...form, name: e.target.value })}
              required
              placeholder={t("namePlaceholder")}
            />
            <Input
              label={t("description")}
              value={form.description}
              onChange={(e) => setForm({ ...form, description: e.target.value })}
              placeholder={t("descPlaceholder")}
            />
          </section>

          <section className="space-y-3 rounded-2xl border border-[var(--border)] bg-[var(--bg)]/40 p-3.5 sm:p-4">
            <div className="flex flex-wrap items-center justify-between gap-2">
              <div className="flex items-center gap-2 text-[var(--text)]">
                <Sparkles className="h-4 w-4 text-[var(--accent)]" />
                <p className="text-sm font-semibold">{t("quickSetup")}</p>
                <HelpTooltip content={t("quickSetupHint")} label={tc("helpLabel")} />
              </div>
              <span className="rounded-md border border-[var(--border)] bg-[var(--bg-elevated)] px-2 py-1 text-[11px] text-[var(--text-faint)]">
                {t("selectedCount", { count: form.permissionIds.length })}
              </span>
            </div>

            <div className="flex flex-wrap gap-2">
              <button
                type="button"
                onClick={() => applyPreset("view")}
                className="inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-[var(--border)] bg-[var(--bg-elevated)] px-3 py-1.5 text-xs font-medium text-[var(--text-muted)] transition-colors hover:border-[var(--accent)]/40 hover:text-[var(--text)]"
              >
                <Eye className="h-3.5 w-3.5" />
                {t("presetViewOnly")}
              </button>
              <button
                type="button"
                onClick={() => applyPreset("all")}
                className="inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-[var(--border)] bg-[var(--bg-elevated)] px-3 py-1.5 text-xs font-medium text-[var(--text-muted)] transition-colors hover:border-[var(--accent)]/40 hover:text-[var(--text)]"
              >
                <Check className="h-3.5 w-3.5" />
                {t("presetFullAccess")}
              </button>
              <button
                type="button"
                onClick={() => applyPreset("none")}
                className="inline-flex cursor-pointer items-center gap-1.5 rounded-lg border border-[var(--border)] bg-[var(--bg-elevated)] px-3 py-1.5 text-xs font-medium text-[var(--text-muted)] transition-colors hover:border-[var(--accent)]/40 hover:text-[var(--text)]"
              >
                {t("presetClear")}
              </button>
            </div>

            {roles.length > 0 && (
              <div className="space-y-1.5">
                <LabelWithHint
                  label={t("copyFromRole")}
                  hint={t("copyFromRoleHint")}
                  hintLabel={tc("helpLabel")}
                  htmlFor="copy-from-role"
                />
                <select
                  id="copy-from-role"
                  value={copyFromId}
                  onChange={(e) => copyFromRole(e.target.value)}
                  className="w-full cursor-pointer rounded-lg border border-[var(--border)] bg-[var(--bg-elevated)] px-3 py-2.5 text-sm text-[var(--text)] focus:border-[var(--accent)]/60 focus:outline-none focus:ring-2 focus:ring-[var(--accent)]/40"
                >
                  <option value="">{t("copyFromPlaceholder")}</option>
                  {roles.map((role) => (
                    <option key={role.id} value={role.id}>
                      {role.name} ({role.permissions.length})
                    </option>
                  ))}
                </select>
              </div>
            )}
          </section>

          <section className="space-y-3">
            <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
              <div className="flex items-start gap-1.5">
                <div>
                  <p className="text-sm font-semibold text-[var(--text)]">{t("accessSection")}</p>
                  <p className="mt-0.5 text-xs text-[var(--text-faint)]">{t("tapToToggle")}</p>
                </div>
                <HelpTooltip content={t("permissionsHint")} label={tc("helpLabel")} className="mt-0.5" />
              </div>
              <div className="relative w-full sm:max-w-[220px]">
                <Search className="pointer-events-none absolute start-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-[var(--text-faint)]" />
                <input
                  type="search"
                  value={permSearch}
                  onChange={(e) => setPermSearch(e.target.value)}
                  placeholder={t("searchPermissions")}
                  className="w-full rounded-lg border border-[var(--border)] bg-[var(--bg)] py-2 pe-3 ps-9 text-sm text-[var(--text)] placeholder:text-[var(--text-faint)] focus:border-[var(--accent)]/60 focus:outline-none focus:ring-2 focus:ring-[var(--accent)]/40"
                />
              </div>
            </div>

            {moduleEntries.length === 0 ? (
              <p className="rounded-xl border border-dashed border-[var(--border)] px-4 py-8 text-center text-sm text-[var(--text-faint)]">
                {t("noPermissionsMatch")}
              </p>
            ) : (
              <div className="space-y-3">
                {moduleEntries.map(([module, perms]) => {
                  const selectedInModule = perms.filter((p) =>
                    form.permissionIds.includes(p.id)
                  ).length;
                  const allSelected = selectedInModule === perms.length && perms.length > 0;
                  const someSelected = selectedInModule > 0 && !allSelected;

                  return (
                    <div
                      key={module}
                      className="overflow-hidden rounded-xl border border-[var(--border)] bg-[var(--bg)]/50"
                    >
                      <div className="flex items-center justify-between gap-3 border-b border-[var(--border)] px-3 py-2.5">
                        <label className="flex min-w-0 cursor-pointer items-center gap-2.5">
                          <input
                            type="checkbox"
                            checked={allSelected}
                            ref={(el) => {
                              if (el) el.indeterminate = someSelected;
                            }}
                            onChange={() => setModuleSelection(perms, !allSelected)}
                            className="h-4 w-4 cursor-pointer rounded accent-[var(--accent)]"
                          />
                          <span className="min-w-0">
                            <span className="block text-sm font-semibold capitalize text-[var(--text)]">
                              {module}
                            </span>
                            <span className="text-[11px] text-[var(--text-faint)]">
                              {t("moduleSelected", {
                                selected: selectedInModule,
                                total: perms.length,
                              })}
                            </span>
                          </span>
                        </label>
                      </div>

                      <div className="flex flex-wrap gap-2 p-3">
                        {perms.map((perm) => {
                          const checked = form.permissionIds.includes(perm.id);
                          return (
                            <button
                              key={perm.id}
                              type="button"
                              onClick={() => togglePerm(perm.id)}
                              title={perm.description ?? perm.name}
                              className={`inline-flex cursor-pointer items-center gap-1.5 rounded-full border px-3 py-1.5 text-xs font-medium transition-colors ${
                                checked
                                  ? "border-[var(--accent)]/40 bg-[var(--accent-muted)] text-[var(--accent)]"
                                  : "border-[var(--border)] bg-[var(--bg-elevated)] text-[var(--text-muted)] hover:border-[var(--accent)]/30 hover:text-[var(--text)]"
                              }`}
                            >
                              {checked && <Check className="h-3 w-3" />}
                              {friendlyAction(perm.action)}
                            </button>
                          );
                        })}
                      </div>
                    </div>
                  );
                })}
              </div>
            )}
          </section>
        </div>

        <div className="flex shrink-0 items-center justify-end gap-2.5 border-t border-[var(--border)] bg-[var(--bg)]/40 px-5 py-4 sm:px-6">
          <Button
            type="button"
            variant="secondary"
            onClick={onClose}
            disabled={saving}
            className="min-w-[96px]"
          >
            {tc("cancel")}
          </Button>
          <Button type="submit" disabled={saving || !form.name.trim()} className="min-w-[110px]">
            {saving ? (
              <>
                <Loader2 className="h-4 w-4 animate-spin" />
                {tc("saving")}
              </>
            ) : isEdit ? (
              tc("update")
            ) : (
              tc("create")
            )}
          </Button>
        </div>
      </form>
    </Modal>
  );
}
