'use client';
import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { api } from '@/lib/api';
import { useAuth } from '@/lib/auth-context';
import { Importer } from '@/components/importer';
import { DataTable, Pagination } from '@/components/data-table';
import { FloatInput, FloatSelect } from '@/components/float';
import { DepartmentPicker } from '@/components/pickers';
import { IconBan, IconClose, IconEdit, IconTrash } from '@/components/ui';
import { formatDateTime, formatRole, capitalizeFirst as cap } from '@/lib/format';
import { validate, v, Errors } from '@/lib/validation';
import { useDialog } from '@/components/dialog';

const PAGE_SIZE = 10;

export default function UsersPage() {
  const { user } = useAuth();
  const { confirmDialog, notify, promptDialog } = useDialog();
  const canManage = user?.role === 'admin' || user?.role === 'super_admin' || user?.role === 'stakeholder';
  const isSuper = user?.role === 'super_admin';
  const isStakeholder = user?.role === 'stakeholder';
  // Row-level delete visibility mirrors the backend hierarchy guard:
  // super_admin → anyone but self; admin → stakeholder/employee; stakeholder → employee.
  const canDelete = (u: any) => user && user.id !== u.id && (
    isSuper || (user.role === 'admin' && (u.role === 'stakeholder' || u.role === 'employee')) ||
    (isStakeholder && u.role === 'employee')
  );
  // Deactivate + password reset stay with admin/super_admin; stakeholders manage employees via create/delete.
  const canStaff = !isStakeholder;
  const [page, setPage] = useState(1);
  const [search, setSearch] = useState('');
  const [orgFilter, setOrgFilter] = useState('');
  const [showImport, setShowImport] = useState(false);
  const q = useQuery({
    queryKey: ['users', page, search, orgFilter],
    queryFn: () => api.get(`/api/v1/users?search=${encodeURIComponent(search)}&page=${page}&limit=${PAGE_SIZE}${orgFilter ? `&organisation_id=${orgFilter}` : ''}`),
    enabled: canManage,
  });
  const orgsQ = useQuery({
    queryKey: ['users-orgs'], queryFn: () => api.get('/api/v1/super/organisations?limit=100'),
    enabled: canManage && isSuper,
  });
  const orgs: any[] = orgsQ.data?.data ?? [];
  if (!canManage) return <p>Access denied — the Users module is not available for your role.</p>;
  const rows: any[] = q.data?.data ?? [];
  return (
    <div className="space-y-3">
      <div className="flex gap-2 items-center">
        <h1 className="page-title mr-auto">User Management</h1>
        {!isStakeholder && (showImport
          ? <button className="btn-ghost btn-icon" aria-label="Close import" title="Close" onClick={() => setShowImport(false)}><IconClose /></button>
          : <button className="btn-ghost text-sm" onClick={() => setShowImport(true)}>Bulk import</button>)}
      </div>
      <CreateUser refresh={() => q.refetch()} orgs={orgs} />
      {!isStakeholder && showImport && <Importer kind="users" label="users" onDone={() => q.refetch()} />}
      <div className="flex flex-wrap gap-2 items-end">
        {isSuper && (
          <div className="w-72 max-w-full">
            <FloatSelect label="Filter by organisation" id="u-org-filter" value={orgFilter} onChange={(e) => { setOrgFilter(e.target.value); setPage(1); }}>
              <option value="">All organisations</option>
              {orgs.map((o: any) => <option key={o.id} value={o.id}>{cap(o.name)}</option>)}
            </FloatSelect>
          </div>
        )}
        <input
          className="input h-14 text-sm flex-1 min-w-52"
          type="search"
          placeholder="Search name / email / code / phone"
          aria-label="Search name / email / code / phone"
          value={search}
          onChange={(e) => { setSearch(e.target.value); setPage(1); }}
        />
      </div>
      <DataTable
        caption="Users"
        rows={rows}
        keyOf={(u) => u.id}
        searchValue={search}
        onSearchChange={(v) => { setSearch(v); setPage(1); }}
        searchPlaceholder="Search name / email / code / phone"
        hideSearch
        empty={q.isLoading ? 'Loading…' : 'No users found.'}
        columns={[
          { header: 'Name', render: (u: any) => <b>{u.name}</b> },
          { header: 'Email', render: (u: any) => <span className="whitespace-nowrap">{u.email}</span> },
          { header: 'Phone', render: (u: any) => <span className="whitespace-nowrap">{u.phone ?? '—'}</span> },
          { header: 'Employee ID', render: (u: any) => <span className="whitespace-nowrap">{u.employee_code ?? '—'}</span> },
          { header: 'Role', render: (u: any) => <span className="badge bg-slate-100 whitespace-nowrap">{formatRole(u.role)}</span> },
          ...(isSuper ? [{ header: 'Organisation', render: (u: any) => u.org_name ?? '—' }] : []),
          { header: 'Status', render: (u: any) => u.status },
          { header: 'Department', render: (u: any) => u.dept_name ?? '—' },
          { header: 'Joined', render: (u: any) => <span className="whitespace-nowrap">{formatDateTime(u.created_at)}</span> },
          {
            header: '', render: (u: any) => (
              <span className="flex gap-1">
                {canStaff && (
                  <button type="button" className="btn-plain" aria-label={`Deactivate ${u.name}`} title="Deactivate" onClick={async () => {
                    if (!await confirmDialog(`Deactivate ${u.name}? They will no longer be able to log in.`, { title: 'Deactivate user', confirmLabel: 'Deactivate' })) return;
                    try { await api.post(`/api/v1/users/${u.id}/deactivate`); q.refetch(); }
                    catch (e: any) { notify(e.message, { tone: 'error' }); }
                  }}><IconBan /></button>
                )}
                {canStaff && (
                  <button type="button" className="btn-plain" aria-label={`Reset password for ${u.name}`} title="Reset password" onClick={async () => {
                    const pw = await promptDialog(`New password for ${u.name} (min 8 chars):`, { title: 'Reset password' });
                    if (!pw) return;
                    if (pw.length < 8) { notify('Password must be at least 8 characters.', { tone: 'error' }); return; }
                    try { await api.post(`/api/v1/users/${u.id}/reset-password`, { password: pw }); notify('Password reset done.', { tone: 'success' }); }
                    catch (e: any) { notify(e.message, { tone: 'error' }); }
                  }}><IconEdit /></button>
                )}
                {canDelete(u) && (
                  <button type="button" className="btn-plain" aria-label={`Delete ${u.name}`} title="Delete" onClick={async () => {
                    if (!await confirmDialog(`Delete ${u.name}? They will be removed from this organisation.`, { title: 'Delete user', confirmLabel: 'Delete' })) return;
                    try { await api.del(`/api/v1/users/${u.id}`); notify('User deleted.', { tone: 'success' }); q.refetch(); }
                    catch (e: any) { notify(e.message, { tone: 'error' }); }
                  }}><IconTrash /></button>
                )}
              </span>
            ),
          },
        ]}
      />
      <Pagination page={page} total={q.data?.total ?? 0} limit={PAGE_SIZE} onPage={setPage} />
    </div>
  );
}

function CreateUser({ refresh, orgs }: { refresh: () => void; orgs: any[] }) {
  const { user } = useAuth();
  const { notify } = useDialog();
  const isSuper = user?.role === 'super_admin';
  const isStakeholder = user?.role === 'stakeholder';
  const [errs, setErrs] = useState<Errors>({});
  const [dept, setDept] = useState<number | null>(null);
  return (
    <form className="card gap-2" noValidate onSubmit={async (e) => {
      e.preventDefault();
      const fd = new FormData(e.target as HTMLFormElement);
      const vals = Object.fromEntries(fd.entries()) as Record<string, string>;
      if (dept) vals.department_id = String(dept);
      const fe = validate({
        name: () => v.minLen(vals.name ?? '', 2, 'Name'),
        email: () => v.email(vals.email ?? ''),
        password: () => v.minLen(vals.password ?? '', 8, 'Password'),
        phone: () => v.optionalPhone(vals.phone ?? ''),
        organisation_id: () => isSuper && !vals.organisation_id ? 'Organisation is required' : null,
      });
      setErrs(fe);
      if (Object.keys(fe).length) return;
      try {
        await api.post('/api/v1/users', vals);
        (e.target as HTMLFormElement).reset(); setErrs({}); setDept(null); refresh();
        notify('User created.', { tone: 'success' });
      } catch (ex: any) { notify(ex.message, { tone: 'error' }); }
    }}>
      <div className="grid md:grid-cols-4 gap-2">
        <FloatInput label="Full name" id="cu-name" name="name" required error={errs.name} />
        <FloatInput label="Email" id="cu-email" name="email" type="email" required error={errs.email} />
        <FloatInput label="Password" id="cu-password" name="password" type="password" required error={errs.password} />
        <FloatSelect label="Role" id="cu-role" name="role" defaultValue="employee">
          <option value="employee">Employee</option>
          {!isStakeholder && <option value="stakeholder">Stakeholder</option>}
          {!isStakeholder && <option value="admin">Admin</option>}
          {isSuper && <option value="super_admin">Super Admin</option>}
        </FloatSelect>
        <FloatInput label="Phone (optional)" id="cu-phone" name="phone" type="tel" autoComplete="tel" error={errs.phone} />
        <FloatInput label="Employee ID (optional)" id="cu-code" name="employee_code" capitalize={false} />
        <DepartmentPicker value={dept} onChange={setDept} />
        {isSuper && (
          <FloatSelect label="Organisation" id="cu-org" name="organisation_id" required error={errs.organisation_id} defaultValue="">
            <option value="">Select organisation</option>
            {orgs.map((o: any) => <option key={o.id} value={o.id}>{cap(o.name)}</option>)}
          </FloatSelect>
        )}
        <button className="btn-primary btn-tall justify-self-start px-8">Create</button>
      </div>
    </form>
  );
}
