"use client";

import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useAuth } from "@/hooks/useAuth";
import { useRouter } from "next/navigation";
import { apiFetch } from "@/lib/api";
import { useDismissingState } from "@/hooks/useDismissingState";
import { Users as UsersIcon } from "lucide-react";
import { RoleBadge, type Role as RoleBadgeRole } from "@/components/shared/RoleBadge";

interface UserItem {
  id: string;
  name: string;
  email: string;
  role: string;
  phoneNumber?: string | null;
  notificationPreference?: string;
  isActive: boolean;
  createdAt: string;
  updatedAt: string;
}

const roleOptions = ["user", "staff", "supervisor", "admin"] as const;
type Role = typeof roleOptions[number];

const notificationPreferenceOptions = ["email", "whatsapp", "both"] as const;

// Simple fuzzy: tolerate one missing/swapped char by checking if query chars appear in order
function fuzzyMatch(query: string, target: string): boolean {
  const q = query.toLowerCase();
  const t = target.toLowerCase();
  if (t.includes(q)) return true;
  // token-based: all tokens must appear somewhere
  const tokens = q.split(/\s+/).filter(Boolean);
  return tokens.every(tok => t.includes(tok));
}

export default function AdminUsersPage() {
  const { user, loading, token } = useAuth();
  const router = useRouter();

  const isAdmin = useMemo(() => user?.role === "admin", [user]);

  useEffect(() => {
    if (loading) return;
    if (!user) router.replace("/login");
  }, [user, loading, router]);

  // Data state
  const [users, setUsers] = useState<UserItem[]>([]);
  const [fetching, setFetching] = useState(false);
  const [error, setError] = useDismissingState<string | null>(null);
  const [page, setPage] = useState(1);
  const [totalPages, setTotalPages] = useState(1);
  const [total, setTotal] = useState(0);
  const [pageSize, setPageSize] = useState(50);

  // Search and filter state (server-side)
  const [query, setQuery] = useState("");
  const [debouncedQuery, setDebouncedQuery] = useState("");
  const [roleFilter, setRoleFilter] = useState<Role | "">("");
  const [activeFilter, setActiveFilter] = useState<"" | "true" | "false">("");

  // Debounce search
  useEffect(() => {
    const t = setTimeout(() => setDebouncedQuery(query), 350);
    return () => clearTimeout(t);
  }, [query]);

  // Create form state
  const [createOpen, setCreateOpen] = useState(false);
  const [cName, setCName] = useState("");
  const [cEmail, setCEmail] = useState("");
  const [cPassword, setCPassword] = useState("");
  const [cPhone, setCPhone] = useState("");
  const [cRole, setCRole] = useState<Role>("user");
  const [creating, setCreating] = useState(false);

  // Edit modal state
  const [editingId, setEditingId] = useState<string | null>(null);
  const [editData, setEditData] = useState<Partial<UserItem> & { password?: string }>({});
  const [saving, setSaving] = useState(false);
  const editingUser = useMemo(() => users.find(u => u.id === editingId) || null, [users, editingId]);

  const buildQuery = useCallback((p: number, ps = pageSize) => {
    const qs = new URLSearchParams({ page: String(p), limit: String(ps) });
    if (debouncedQuery.trim()) qs.set("search", debouncedQuery.trim());
    if (roleFilter) qs.set("role", roleFilter);
    if (activeFilter !== "") qs.set("isActive", activeFilter);
    return `/api/users?${qs.toString()}`;
  }, [debouncedQuery, roleFilter, activeFilter, pageSize]);

  const loadUsers = useCallback(async (p = 1, ps = pageSize) => {
    if (!token) return;
    setError(null);
    setFetching(true);
    try {
      const url = buildQuery(p, ps);
      const res = await apiFetch<any>(url, { authToken: token });
      setUsers(Array.isArray(res?.data) ? res.data : []);
      setTotal(res?.total ?? 0);
      setTotalPages(res?.pages ?? 1);
      setPage(p);
    } catch (e: any) {
      setError(e?.message || "Failed to load users");
    } finally {
      setFetching(false);
    }
  }, [token, buildQuery]);

  // Initial load + reload on filter change
  useEffect(() => { if (token) loadUsers(1); }, [token, debouncedQuery, roleFilter, activeFilter]);

  const goToPage = (p: number) => loadUsers(p);

  const handlePageSizeChange = (newSize: number) => {
    setPageSize(newSize);
    loadUsers(1, newSize);
  };

  const resetCreateForm = () => {
    setCName(""); setCEmail(""); setCPassword(""); setCPhone(""); setCRole("user");
  };

  const handleCreate = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!cEmail || !cPassword) { setError("Email and password are required"); return; }
    try {
      setCreating(true);
      const created = await apiFetch<any>("/api/users", {
        method: "POST",
        body: { name: cName || cEmail.split("@")[0], email: cEmail, password: cPassword, phoneNumber: cPhone || undefined },
      });
      if (cRole && cRole !== "user" && created?.id) {
        await apiFetch(`/api/users/${encodeURIComponent(created.id)}`, {
          method: "PUT", authToken: token!, body: { role: cRole },
        });
      }
      resetCreateForm();
      setCreateOpen(false);
      await loadUsers(page);
    } catch (e: any) {
      setError(e?.message || "Failed to create user");
    } finally {
      setCreating(false);
    }
  };

  const startEdit = (u: UserItem) => { setEditingId(u.id); setEditData({ ...u, password: "" }); };
  const cancelEdit = () => { setEditingId(null); setEditData({}); };

  const saveEdit = async () => {
    if (!editingId) return;
    try {
      setSaving(true);
      const payload: any = {
        name: editData.name,
        email: editData.email,
        role: editData.role,
        phoneNumber: editData.phoneNumber || null,
        notificationPreference: editData.notificationPreference,
        isActive: editData.isActive,
      };
      if (editData.password && editData.password.trim().length > 0) {
        payload.password = editData.password.trim();
      }
      await apiFetch(`/api/users/${encodeURIComponent(editingId)}`, {
        method: "PUT", authToken: token!, body: payload,
      });
      setEditingId(null);
      setEditData({});
      await loadUsers(page);
    } catch (e: any) {
      setError(e?.message || "Failed to save user");
    } finally {
      setSaving(false);
    }
  };

  const revokeUserSessions = async (id: string, name: string) => {
    if (!confirm(`Revoke all active sessions for ${name}? They will be signed out on all devices.`)) return;
    try {
      await apiFetch(`/api/users/${encodeURIComponent(id)}/revoke-sessions`, { method: "POST", authToken: token! });
    } catch (e: any) {
      setError(e?.message || "Failed to revoke sessions");
    }
  };

  const deactivate = async (id: string) => {
    if (!confirm("Deactivate this user? Their account will be disabled.")) return;
    try {
      await apiFetch(`/api/users/${encodeURIComponent(id)}`, { method: "DELETE", authToken: token! });
      await loadUsers(page);
    } catch (e: any) {
      setError(e?.message || "Failed to deactivate user");
    }
  };

  const deleteUserData = async (id: string, name: string) => {
    if (!confirm(`Delete personal data for "${name}"?\n\nThis will set their name to "Deleted User", clear their email and phone number, and deactivate the account. This action cannot be undone.`)) return;
    try {
      await apiFetch(`/api/users/${encodeURIComponent(id)}/anonymize`, { method: "POST", authToken: token! });
      await loadUsers(page);
    } catch (e: any) {
      setError(e?.message || "Failed to delete user data");
    }
  };

  return (
    <div className="max-w-6xl mx-auto w-full p-6">
      <div className="flex items-center justify-between mb-4 flex-wrap gap-3">
        <div className="flex items-center gap-3">
          <div className="w-10 h-10 rounded-xl bg-brand-50 flex items-center justify-center shrink-0">
            <UsersIcon className="w-5 h-5 text-brand-600" />
          </div>
          <div>
            <h1 className="text-2xl font-semibold text-gray-900">User Management</h1>
            <p className="text-sm text-gray-500">{total} user{total !== 1 ? "s" : ""} total</p>
          </div>
        </div>
        <div className="flex gap-2">
          <button className="px-3 py-1.5 text-sm rounded-lg bg-gray-100 hover:bg-gray-200" onClick={() => router.push("/dashboard")}>Back</button>
          <button className="px-3 py-1.5 text-sm rounded-lg bg-brand-600 text-white hover:bg-brand-700" onClick={() => setCreateOpen(v => !v)}>
            {createOpen ? "Close" : "Create user"}
          </button>
        </div>
      </div>

      {!isAdmin && (
        <div className="p-3 border rounded bg-yellow-50 text-yellow-800 text-sm mb-4">
          You need admin access to manage users.
        </div>
      )}

      {error && <div className="mb-3 p-3 border rounded bg-red-50 text-red-800 text-sm">{error}</div>}

      {createOpen && (
        <form onSubmit={handleCreate} className="border rounded-xl p-4 bg-white shadow-sm mb-6 grid sm:grid-cols-2 gap-3">
          <div>
            <label className="block text-sm text-gray-700 mb-1">Name</label>
            <input className="w-full border rounded px-3 py-2" value={cName} onChange={e => setCName(e.target.value)} />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-1">Email</label>
            <input type="email" className="w-full border rounded px-3 py-2" value={cEmail} onChange={e => setCEmail(e.target.value)} required />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-1">Password</label>
            <input type="password" className="w-full border rounded px-3 py-2" value={cPassword} onChange={e => setCPassword(e.target.value)} required />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-1">Phone</label>
            <input className="w-full border rounded px-3 py-2" value={cPhone} onChange={e => setCPhone(e.target.value)} />
          </div>
          <div>
            <label className="block text-sm text-gray-700 mb-1">Role</label>
            <select className="w-full border rounded px-3 py-2" value={cRole} onChange={e => setCRole(e.target.value as Role)}>
              {roleOptions.map(r => <option key={r} value={r}>{r}</option>)}
            </select>
          </div>
          <div className="flex items-end">
            <button disabled={creating} className="px-3 py-2 rounded bg-brand-600 text-white disabled:opacity-50" type="submit">
              {creating ? "Creating…" : "Create"}
            </button>
          </div>
        </form>
      )}

      <div className="border rounded-xl p-4 bg-white shadow-sm">
        {/* Filters row */}
        <div className="flex flex-wrap items-end gap-3 mb-4">
          <div className="flex-1 min-w-48">
            <label className="block text-xs text-gray-600 mb-1">Search (name, email, phone)</label>
            <input
              className="w-full border rounded px-3 py-1.5 text-sm"
              placeholder="Type to search…"
              value={query}
              onChange={e => setQuery(e.target.value)}
            />
          </div>
          <div>
            <label className="block text-xs text-gray-600 mb-1">Role</label>
            <select className="border rounded px-2 py-1.5 text-sm" value={roleFilter} onChange={e => setRoleFilter(e.target.value as Role | "")}>
              <option value="">All roles</option>
              {roleOptions.map(r => <option key={r} value={r}>{r}</option>)}
            </select>
          </div>
          <div>
            <label className="block text-xs text-gray-600 mb-1">Status</label>
            <select className="border rounded px-2 py-1.5 text-sm" value={activeFilter} onChange={e => setActiveFilter(e.target.value as "" | "true" | "false")}>
              <option value="">Active &amp; inactive</option>
              <option value="true">Active only</option>
              <option value="false">Inactive only</option>
            </select>
          </div>
          <div>
            <label className="block text-xs text-gray-600 mb-1">Per page</label>
            <select className="border rounded px-2 py-1.5 text-sm" value={pageSize} onChange={e => handlePageSizeChange(Number(e.target.value))}>
              <option value={10}>10</option>
              <option value={25}>25</option>
              <option value={50}>50</option>
              <option value={100}>100</option>
            </select>
          </div>
          <button className="text-sm px-2 py-1.5 rounded bg-gray-100 hover:bg-gray-200" onClick={() => loadUsers(page)} disabled={fetching}>
            {fetching ? "Refreshing…" : "Refresh"}
          </button>
        </div>

        <div className="text-xs text-gray-500 mb-2">
          {total > 0 && `Page ${page} of ${totalPages}`}
        </div>

        <div className="overflow-auto">
          <table className="min-w-full text-sm">
            <thead>
              <tr className="text-left text-gray-600 border-b">
                <th className="p-2">Name</th>
                <th className="p-2">Email</th>
                <th className="p-2">Role</th>
                <th className="p-2">Phone</th>
                <th className="p-2">Notify</th>
                <th className="p-2">Active</th>
                <th className="p-2">Actions</th>
              </tr>
            </thead>
            <tbody>
              {users.map(u => (
                <tr key={u.id} className="border-t hover:bg-gray-50">
                  <td className="p-2">
                    <span className={`font-medium ${!u.isActive ? "text-gray-400" : ""}`}>{u.name}</span>
                  </td>
                  <td className="p-2">
                    <span className={u.email?.endsWith("@deleted.local") ? "text-gray-400 italic" : ""}>{u.email}</span>
                  </td>
                  <td className="p-2">
                    <RoleBadge role={u.role as RoleBadgeRole} />
                  </td>
                  <td className="p-2">
                    <span>{u.phoneNumber || ""}</span>
                  </td>
                  <td className="p-2">
                    <span className="capitalize">{u.notificationPreference || "email"}</span>
                  </td>
                  <td className="p-2">
                    <span className={`inline-flex items-center gap-1.5 text-xs font-medium px-2 py-0.5 rounded-full ${u.isActive ? "bg-green-50 text-green-700" : "bg-gray-100 text-gray-500"}`}>
                      <span className={`w-1.5 h-1.5 rounded-full ${u.isActive ? "bg-green-500" : "bg-gray-400"}`} />
                      {u.isActive ? "Active" : "Inactive"}
                    </span>
                  </td>
                  <td className="p-2">
                    <div className="flex gap-1 flex-wrap">
                      <button className="px-2 py-1 text-xs rounded bg-gray-100 hover:bg-gray-200" onClick={() => startEdit(u)}>Edit</button>
                      <button className="px-2 py-1 text-xs rounded bg-amber-500 text-white hover:bg-amber-600" onClick={() => revokeUserSessions(u.id, u.name)} title="Force this user to sign in again on every device where they're currently logged in">Sign out everywhere</button>
                      <button className="px-2 py-1 text-xs rounded bg-orange-500 text-white hover:bg-orange-600" onClick={() => deactivate(u.id)} title="Deactivate account">Deactivate</button>
                      <button className="px-2 py-1 text-xs rounded bg-red-700 text-white hover:bg-red-800" onClick={() => deleteUserData(u.id, u.name)} title="Erase personal data">Delete data</button>
                    </div>
                  </td>
                </tr>
              ))}
              {users.length === 0 && !fetching && (
                <tr>
                  <td className="p-3 text-gray-500" colSpan={7}>No users found.</td>
                </tr>
              )}
              {fetching && (
                <tr>
                  <td className="p-3 text-gray-400" colSpan={7}>Loading…</td>
                </tr>
              )}
            </tbody>
          </table>
        </div>

        {totalPages > 1 && (
          <div className="flex items-center justify-between mt-4 text-sm">
            <span className="text-gray-500">Page {page} of {totalPages}</span>
            <div className="flex gap-1">
              <button
                className="px-2 py-1 rounded bg-gray-100 hover:bg-gray-200 disabled:opacity-40"
                disabled={page <= 1 || fetching}
                onClick={() => goToPage(page - 1)}
              >
                ← Prev
              </button>
              {Array.from({ length: totalPages }, (_, i) => i + 1)
                .filter(p => p === 1 || p === totalPages || Math.abs(p - page) <= 1)
                .reduce<(number | "…")[]>((acc, p, i, arr) => {
                  if (i > 0 && (p as number) - (arr[i - 1] as number) > 1) acc.push("…");
                  acc.push(p);
                  return acc;
                }, [])
                .map((p, i) =>
                  p === "…" ? (
                    <span key={`ellipsis-${i}`} className="px-2 py-1 text-gray-400">…</span>
                  ) : (
                    <button
                      key={p}
                      className={`px-2 py-1 rounded ${page === p ? "bg-brand-600 text-white" : "bg-gray-100 hover:bg-gray-200"}`}
                      disabled={fetching}
                      onClick={() => goToPage(p as number)}
                    >
                      {p}
                    </button>
                  )
                )}
              <button
                className="px-2 py-1 rounded bg-gray-100 hover:bg-gray-200 disabled:opacity-40"
                disabled={page >= totalPages || fetching}
                onClick={() => goToPage(page + 1)}
              >
                Next →
              </button>
            </div>
          </div>
        )}
      </div>

      {editingUser && (
        <div className="fixed inset-0 z-20">
          <div className="absolute inset-0 bg-black/30" onClick={() => !saving && cancelEdit()} />
          <div className="absolute inset-0 flex items-center justify-center p-4">
            <div className="w-full max-w-lg bg-white rounded-lg shadow-lg border p-4">
              <div className="flex items-center justify-between mb-3">
                <h2 className="text-base font-semibold">Edit user</h2>
                <button type="button" className="text-xs px-2 py-1 rounded bg-gray-100 hover:bg-gray-200" onClick={cancelEdit} disabled={saving}>Close</button>
              </div>
              <div className="grid gap-3">
                <div>
                  <label className="block text-xs text-gray-600 mb-1">Name</label>
                  <input className="w-full border rounded px-3 py-2 text-sm" value={editData.name || ""} onChange={e => setEditData(d => ({ ...d, name: e.target.value }))} />
                </div>
                <div>
                  <label className="block text-xs text-gray-600 mb-1">Email</label>
                  <input className="w-full border rounded px-3 py-2 text-sm" value={editData.email || ""} onChange={e => setEditData(d => ({ ...d, email: e.target.value }))} />
                </div>
                <div className="grid sm:grid-cols-2 gap-3">
                  <div>
                    <label className="block text-xs text-gray-600 mb-1">Role</label>
                    <select className="w-full border rounded px-3 py-2 text-sm" value={(editData.role as Role) || "user"} onChange={e => setEditData(d => ({ ...d, role: e.target.value }))}>
                      {roleOptions.map(r => <option key={r} value={r}>{r}</option>)}
                    </select>
                  </div>
                  <div>
                    <label className="block text-xs text-gray-600 mb-1">Phone</label>
                    <input className="w-full border rounded px-3 py-2 text-sm" value={editData.phoneNumber || ""} onChange={e => setEditData(d => ({ ...d, phoneNumber: e.target.value }))} />
                  </div>
                </div>
                <div className="grid sm:grid-cols-2 gap-3">
                  <div>
                    <label className="block text-xs text-gray-600 mb-1">Notification preference</label>
                    <select
                      className="w-full border rounded px-3 py-2 text-sm"
                      value={editData.notificationPreference || "email"}
                      onChange={e => setEditData(d => ({ ...d, notificationPreference: e.target.value }))}
                    >
                      {notificationPreferenceOptions.map(p => (
                        <option key={p} value={p} disabled={p !== "email" && !editData.phoneNumber}>{p}</option>
                      ))}
                    </select>
                  </div>
                  <div className="flex items-end pb-2">
                    <label className="flex items-center gap-2 text-sm">
                      <input type="checkbox" checked={!!editData.isActive} onChange={e => setEditData(d => ({ ...d, isActive: e.target.checked }))} />
                      Active
                    </label>
                  </div>
                </div>
                <div>
                  <label className="block text-xs text-gray-600 mb-1">New password (leave blank to keep current)</label>
                  <input type="password" placeholder="Set new password" className="w-full border rounded px-3 py-2 text-sm" value={editData.password || ""} onChange={e => setEditData(d => ({ ...d, password: e.target.value }))} />
                </div>
              </div>
              <div className="flex justify-end gap-2 mt-4">
                <button className="px-3 py-1.5 text-sm rounded bg-gray-100 hover:bg-gray-200" onClick={cancelEdit} disabled={saving}>Cancel</button>
                <button className="px-3 py-1.5 text-sm rounded bg-brand-600 text-white disabled:opacity-50" onClick={saveEdit} disabled={saving}>{saving ? "Saving…" : "Save"}</button>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}