import { useEffect, useMemo, useRef, useState } from "react";
import { Pencil, Plus, Search, Trash2 } from "lucide-react";
import type { ApiSettings, AuthInfo } from "@govoplan/core-webui";
import { createGroup, fetchGroupsDelta, fetchRolesDelta, fetchUsersDelta, updateGroup, type GroupSummary, type RoleSummary, type UserAdminItem } from "../../api/admin";
import { Button } from "@govoplan/core-webui";
import { DataGrid, type DataGridColumn } from "@govoplan/core-webui";
import { Dialog } from "@govoplan/core-webui";
import { FormField } from "@govoplan/core-webui";
import { StatusBadge } from "@govoplan/core-webui";
import { ConfirmDialog } from "@govoplan/core-webui";
import { AdminIconButton, AdminPageLayout, AdminSelectionList, TableActionGroup, adminErrorMessage, formatAdminDateTime as formatDateTime, joinLabels, i18nMessage, useDeltaWatermarks, useUnsavedDraftGuard } from "@govoplan/core-webui";
import { loadDeltaRows } from "./utils/deltaRows";

const emptyDraft = { slug: "", name: "", description: "", isActive: true, memberIds: [] as string[], roleIds: [] as string[] };

export default function GroupsPanel({ settings, auth, canDefine, canManageMembers, canAssignRoles, onAuthRefresh






}: {settings: ApiSettings;auth: AuthInfo;canDefine: boolean;canManageMembers: boolean;canAssignRoles: boolean;onAuthRefresh: () => Promise<void>;}) {
  const [groups, setGroups] = useState<GroupSummary[]>([]);
  const [users, setUsers] = useState<UserAdminItem[]>([]);
  const [roles, setRoles] = useState<RoleSummary[]>([]);
  const groupsRef = useRef<GroupSummary[]>([]);
  const usersRef = useRef<UserAdminItem[]>([]);
  const rolesRef = useRef<RoleSummary[]>([]);
  const { getDeltaWatermark, setDeltaWatermark, resetDeltaWatermark } = useDeltaWatermarks();
  const [editing, setEditing] = useState<GroupSummary | "new" | null>(null);
  const [viewing, setViewing] = useState<GroupSummary | null>(null);
  const [deactivating, setDeactivating] = useState<GroupSummary | null>(null);
  const [draft, setDraft] = useState(emptyDraft);
  const [savedDraftKey, setSavedDraftKey] = useState(draftKey(emptyDraft));
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const [success, setSuccess] = useState("");
  const dirty = editing !== null && draftKey(draft) !== savedDraftKey;

  useUnsavedDraftGuard({
    dirty,
    onSave: save,
    onDiscard: closeEditor
  });

  async function load() {
    setLoading(true);
    setError("");
    try {
      const [nextGroups, nextUsers, nextRoles] = await Promise.all([
      loadDeltaRows(groupsRef.current, "access:groups", getDeltaWatermark, setDeltaWatermark, (since) => fetchGroupsDelta(settings, { since }), (response) => response.groups, (group) => group.id, "access_group", sortGroups),
      loadDeltaRows(usersRef.current, "access:users", getDeltaWatermark, setDeltaWatermark, (since) => fetchUsersDelta(settings, { since }), (response) => response.users, (user) => user.id, "access_user", sortUsers),
      loadDeltaRows(rolesRef.current, "access:roles", getDeltaWatermark, setDeltaWatermark, (since) => fetchRolesDelta(settings, { since }), (response) => response.roles, (role) => role.id, "access_role", sortTenantRoles)]
      );
      groupsRef.current = nextGroups;
      usersRef.current = nextUsers;
      rolesRef.current = nextRoles;
      setGroups(nextGroups);
      setUsers(nextUsers);
      setRoles(nextRoles.filter((role) => role.is_assignable));
    } catch (err) {setError(adminErrorMessage(err));} finally
    {setLoading(false);}
  }

  useEffect(() => {
    groupsRef.current = [];
    usersRef.current = [];
    rolesRef.current = [];
    resetDeltaWatermark();
    void load();
  }, [settings.accessToken, settings.apiBaseUrl, (auth.active_tenant ?? auth.tenant).id, resetDeltaWatermark]);

  function openCreate() {setDraft(emptyDraft);setSavedDraftKey(draftKey(emptyDraft));setEditing("new");setError("");}
  function openEdit(group: GroupSummary) {
    const nextDraft = { slug: group.slug, name: group.name, description: group.description || "", isActive: group.is_active, memberIds: group.member_ids, roleIds: group.roles.map((role) => role.id) };
    setDraft(nextDraft);
    setSavedDraftKey(draftKey(nextDraft));
    setEditing(group);
    setError("");
  }

  function closeEditor() {
    setEditing(null);
    setDraft(emptyDraft);
    setSavedDraftKey(draftKey(emptyDraft));
  }

  async function save(): Promise<boolean> {
    setBusy(true);
    setError("");
    try {
      if (editing === "new") {
        await createGroup(settings, { slug: draft.slug, name: draft.name, description: draft.description || null, is_active: draft.isActive, member_ids: canManageMembers ? draft.memberIds : [], role_ids: canAssignRoles ? draft.roleIds : [] });
        setSuccess(i18nMessage("i18n:govoplan-access.group_value_created.5a39a341", { value0: draft.name }));
      } else if (editing) {
        const managed = Boolean(editing.system_template_id);
        await updateGroup(settings, editing.id, {
          ...(canDefine && !managed ? { name: draft.name, description: draft.description || null } : {}),
          ...(canDefine && !editing.system_required ? { is_active: draft.isActive } : {}),
          ...(canManageMembers ? { member_ids: draft.memberIds } : {}),
          ...(canAssignRoles ? { role_ids: draft.roleIds } : {})
        });
        setSuccess(i18nMessage("i18n:govoplan-access.group_value_updated.3d97d5b2", { value0: draft.name }));
      }
      setEditing(null);
      await onAuthRefresh();
      await load();
      return true;
    } catch (err) {setError(adminErrorMessage(err));return false;} finally
    {setBusy(false);}
  }

  async function deactivate() {
    if (!deactivating) return;
    setBusy(true);
    setError("");
    try {
      await updateGroup(settings, deactivating.id, { is_active: false });
      setSuccess(i18nMessage("i18n:govoplan-access.group_value_deactivated.8512bf9c", { value0: deactivating.name }));
      setDeactivating(null);
      if (deactivating.member_ids.includes(auth.user.id)) await onAuthRefresh();
      await load();
    } catch (err) {setError(adminErrorMessage(err));} finally
    {setBusy(false);}
  }

  const columns = useMemo<DataGridColumn<GroupSummary>[]>(() => [
  { id: "group", header: "i18n:govoplan-access.group.171a0606", width: "minmax(220px, 1fr)", minWidth: 190, resizable: true, sticky: "start", sortable: true, filterable: true, value: (row) => `${row.name} ${row.slug}`, render: (row) => <div><strong>{row.name}</strong><div className="muted small-note">{row.slug} {row.system_template_id && <StatusBadge status={row.system_required ? "warning" : "inactive"} label={`i18n:govoplan-access.system.bc0792d8${row.system_required ? " · i18n:govoplan-access.required.7c65879a" : ""}`} />}</div></div> },
  { id: "members", header: "i18n:govoplan-access.members.1cb449c1", width: 110, resizable: false, sortable: true, filterable: true, filterType: "integer", value: (row) => row.member_count },
  { id: "roles", header: "i18n:govoplan-access.inherited_roles.8def9f05", width: 260, minWidth: 180, maxWidth: 520, resizable: true, fill: true, sortable: true, filterable: true, value: (row) => joinLabels(row.roles) },
  { id: "status", header: "i18n:govoplan-access.status.bae7d5be", width: 120, resizable: false, sortable: true, filterable: true, value: (row) => row.is_active ? "active" : "inactive", render: (row) => <StatusBadge status={row.is_active ? "active" : "inactive"} /> },
  { id: "actions", header: "i18n:govoplan-access.actions.c3cd636a", width: 150, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[
      { id: "inspect", label: i18nMessage("i18n:govoplan-access.inspect_value.9d5d1071", { value0: row.name }), icon: <Search />, onClick: () => setViewing(row) },
      { id: "edit", label: i18nMessage("i18n:govoplan-access.edit_value.fad75899", { value0: row.name }), icon: <Pencil />, disabled: !(canDefine || canManageMembers || canAssignRoles), onClick: () => openEdit(row) },
      { id: "deactivate", label: i18nMessage("i18n:govoplan-access.deactivate_value.a276a667", { value0: row.name }), icon: <Trash2 />, variant: "danger", applicable: row.is_active, disabled: !canDefine || Boolean(row.system_required), onClick: () => setDeactivating(row) }
    ]} /> }],
  [canAssignRoles, canDefine, canManageMembers]);

  return (
    <>
      <AdminPageLayout title="i18n:govoplan-access.tenant_groups.47e6cc05" description="i18n:govoplan-access.groups_provide_shared_file_spaces_and_inherited_.27f05309" loading={loading} error={error} success={success} actions={<><Button onClick={() => void load()} disabled={loading}>i18n:govoplan-access.reload.cce71553</Button><AdminIconButton label="i18n:govoplan-access.add_group.2fca464f" icon={<Plus />} variant="primary" onClick={openCreate} disabled={!canDefine} /></>}>
        <div className="admin-table-surface"><DataGrid id="admin-groups-v3" rows={groups} columns={columns} initialFit="container" getRowKey={(row) => row.id} emptyText="i18n:govoplan-access.no_groups_found.627ca913" /></div>
      </AdminPageLayout>

      <Dialog open={editing !== null} title={editing === "new" ? "i18n:govoplan-access.create_group.5a0b1c17" : "i18n:govoplan-access.edit_group.edb57d8e"} onClose={() => !busy && setEditing(null)} className="admin-dialog admin-dialog-wide" footer={<><Button onClick={() => setEditing(null)} disabled={busy}>i18n:govoplan-access.cancel.77dfd213</Button><Button variant="primary" onClick={() => void save()} disabled={busy || !draft.name.trim() || !draft.slug.trim() || (editing === "new" ? !canDefine : !(canDefine || canManageMembers || canAssignRoles))}>{busy ? "i18n:govoplan-access.saving.56a2285c" : "i18n:govoplan-access.save_group.36ca6865"}</Button></>}>
        {editing !== "new" && editing?.system_template_id && <p className="admin-managed-notice">i18n:govoplan-access.this_group_definition_is_managed_by_the_system_n.640b235e</p>}
        <div className="admin-form-grid two-columns">
          <FormField label="i18n:govoplan-access.name.709a2322"><input value={draft.name} disabled={!canDefine || editing !== "new" && Boolean(editing?.system_template_id)} onChange={(event) => setDraft({ ...draft, name: event.target.value })} /></FormField>
          <FormField label="i18n:govoplan-access.slug.094da9b9"><input value={draft.slug} disabled={editing !== "new" || !canDefine} onChange={(event) => setDraft({ ...draft, slug: event.target.value })} /></FormField>
          <FormField label="i18n:govoplan-access.status.bae7d5be"><select value={draft.isActive ? "active" : "inactive"} disabled={!canDefine || editing !== "new" && Boolean(editing?.system_required)} onChange={(event) => setDraft({ ...draft, isActive: event.target.value === "active" })}><option value="active">i18n:govoplan-access.active.a733b809</option><option value="inactive">i18n:govoplan-access.inactive.09af574c</option></select></FormField>
          <FormField label="i18n:govoplan-access.description.55f8ebc8"><textarea rows={3} value={draft.description} disabled={!canDefine || editing !== "new" && Boolean(editing?.system_template_id)} onChange={(event) => setDraft({ ...draft, description: event.target.value })} /></FormField>
        </div>
        <div className="admin-assignment-grid">
          <div><span className="form-label">i18n:govoplan-access.members.1cb449c1</span><AdminSelectionList options={users.map((user) => ({ id: user.id, label: user.display_name || user.email, description: user.email, disabled: !canManageMembers || !user.is_active || !user.account_is_active }))} selected={draft.memberIds} onChange={(memberIds) => setDraft({ ...draft, memberIds })} emptyText="i18n:govoplan-access.no_tenant_users_exist.96b4a88a" /></div>
          <div><span className="form-label">i18n:govoplan-access.inherited_roles.8def9f05</span><AdminSelectionList options={roles.map((role) => ({ id: role.id, label: role.name, description: role.description, disabled: !canAssignRoles }))} selected={draft.roleIds} onChange={(roleIds) => setDraft({ ...draft, roleIds })} emptyText="i18n:govoplan-access.no_assignable_roles_exist.a4c268c2" /></div>
        </div>
        <p className="muted small-note">i18n:govoplan-access.the_backend_evaluates_the_resulting_access_graph.f318a7dc</p>
      </Dialog>

      <Dialog open={Boolean(viewing)} title="i18n:govoplan-access.group_details.df844ae3" onClose={() => setViewing(null)} className="admin-dialog admin-dialog-wide" footer={<Button onClick={() => setViewing(null)}>i18n:govoplan-access.close.bbfa773e</Button>}>
        {viewing && <dl className="admin-details-grid">
          <div><dt>i18n:govoplan-access.group.171a0606</dt><dd>{viewing.name}</dd></div><div><dt>i18n:govoplan-access.slug.094da9b9</dt><dd>{viewing.slug}</dd></div>
          <div><dt>i18n:govoplan-access.status.bae7d5be</dt><dd>{viewing.is_active ? "i18n:govoplan-access.active.a733b809" : "i18n:govoplan-access.inactive.09af574c"}</dd></div><div><dt>i18n:govoplan-access.management.63cecca6</dt><dd>{viewing.system_template_id ? i18nMessage("i18n:govoplan-access.system_managed_value.eb564eb1", { value0: viewing.system_required ? "i18n:govoplan-access.required.2e5396fd" : "i18n:govoplan-access.available.ce372771" }) : "i18n:govoplan-access.tenant_managed.843eed93"}</dd></div>
          <div><dt>i18n:govoplan-access.members.1cb449c1</dt><dd>{viewing.member_count}</dd></div><div><dt>i18n:govoplan-access.roles.47dcc27d</dt><dd>{joinLabels(viewing.roles)}</dd></div>
          <div><dt>i18n:govoplan-access.created.accf40c8</dt><dd>{formatDateTime(viewing.created_at)}</dd></div><div><dt>i18n:govoplan-access.updated.f2f8570d</dt><dd>{formatDateTime(viewing.updated_at)}</dd></div>
        </dl>}
      </Dialog>

      <ConfirmDialog open={Boolean(deactivating)} title="i18n:govoplan-access.deactivate_group.f1b8ceea" message={i18nMessage("i18n:govoplan-access.deactivate_value_memberships_remain_stored_but_r.4693e4fd", { value0: deactivating?.name })} confirmLabel="i18n:govoplan-access.deactivate_group.f1b8ceea" tone="danger" busy={busy} onCancel={() => setDeactivating(null)} onConfirm={() => void deactivate()} />
    </>);

}

function draftKey(draft: typeof emptyDraft): string {
  return JSON.stringify(draft);
}

function sortGroups(left: GroupSummary, right: GroupSummary): number {
  return left.name.localeCompare(right.name);
}

function sortUsers(left: UserAdminItem, right: UserAdminItem): number {
  return (left.display_name || left.email).localeCompare(right.display_name || right.email) || left.email.localeCompare(right.email);
}

function sortTenantRoles(left: RoleSummary, right: RoleSummary): number {
  const builtinDelta = Number(right.is_builtin) - Number(left.is_builtin);
  if (builtinDelta !== 0) return builtinDelta;
  return left.name.localeCompare(right.name);
}
