"use client";

import { useEffect, useState } from "react";
import { del, get, put } from "@/lib/api";
import { Badge, Field, InfoTip, Notice, Spinner } from "@/components/ui";
import { ROLE_DESCRIPTIONS, ROLE_LABELS, type Role } from "@/lib/roles";

type User = { email: string; name: string; roles: string[]; hasPassword: boolean };

export default function UsersRolesPanel() {
  const [users, setUsers] = useState<User[] | null>(null);
  const [availableRoles, setAvailableRoles] = useState<string[]>([]);
  const [pw, setPw] = useState<Record<string, string>>({});
  const [add, setAdd] = useState({ email: "", name: "", roles: ["monitoring"] as string[], password: "" });
  const [error, setError] = useState<string | null>(null);
  const [msg, setMsg] = useState<string | null>(null);
  const [busy, setBusy] = useState<string | null>(null);

  async function load() {
    try {
      const d = await get<{ users: User[]; availableRoles: string[] }>("users");
      setUsers(d.users);
      setAvailableRoles(d.availableRoles);
    } catch (e) {
      setError((e as Error).message);
    }
  }
  useEffect(() => {
    load();
  }, []);

  if (error) return <Notice kind="error">Could not load users: {error}</Notice>;
  if (!users) return <Spinner label="Loading users…" />;

  const patchUser = (email: string, change: Partial<User>) =>
    setUsers((us) => (us ? us.map((u) => (u.email === email ? { ...u, ...change } : u)) : us));
  const toggleRole = (email: string, role: string) =>
    setUsers((us) =>
      us
        ? us.map((u) =>
            u.email === email
              ? { ...u, roles: u.roles.includes(role) ? u.roles.filter((r) => r !== role) : [...u.roles, role] }
              : u,
          )
        : us,
    );

  async function saveUser(u: User) {
    setBusy(u.email);
    setMsg(null);
    try {
      const payload: Record<string, unknown> = { email: u.email, name: u.name, roles: u.roles };
      if (pw[u.email]) payload.password = pw[u.email];
      const d = await put<{ users: User[] }>("users", payload);
      setUsers(d.users);
      setPw((p) => ({ ...p, [u.email]: "" }));
      setMsg(`Saved ${u.email}.`);
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setBusy(null);
    }
  }

  async function removeUser(email: string) {
    if (!window.confirm(`Remove ${email}? They will lose access.`)) return;
    setBusy(email);
    setMsg(null);
    try {
      const d = await del<{ users: User[] }>(`users/${encodeURIComponent(email)}`);
      setUsers(d.users);
      setMsg(`Removed ${email}.`);
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setBusy(null);
    }
  }

  async function addUser(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setBusy("__add");
    setMsg(null);
    try {
      const d = await put<{ users: User[] }>("users", { email: add.email, name: add.name || add.email, roles: add.roles, password: add.password });
      setUsers(d.users);
      setAdd({ email: "", name: "", roles: ["monitoring"], password: "" });
      setMsg(`Added ${add.email}.`);
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setBusy(null);
    }
  }

  const roleChecks = (selected: string[], onToggle: (role: string) => void) =>
    availableRoles.map((role) => (
      <label key={role} className="flex items-center gap-1.5 text-sm text-slate-700">
        <input type="checkbox" checked={selected.includes(role)} onChange={() => onToggle(role)} />
        {ROLE_LABELS[role as Role] ?? role}
        <InfoTip label={ROLE_LABELS[role as Role] ?? role}>{ROLE_DESCRIPTIONS[role as Role]}</InfoTip>
      </label>
    ));

  return (
    <section className="space-y-6">
      <p className="text-sm text-slate-600">
        Who can sign in and what they can access. A user <strong>with a password</strong> signs in with username +
        password; a user <strong>without one</strong> signs in via Google (their email must be listed here). Roles control
        which sections each user sees. The developer login remains as a bootstrap escape hatch.
      </p>

      {msg && <Notice kind="success">{msg}</Notice>}

      <form onSubmit={addUser} className="card space-y-4">
        <h3 className="font-semibold text-slate-900">Add user</h3>
        <div className="grid gap-4 sm:grid-cols-2">
          <Field label="Email (username)" htmlFor="add-email">
            <input id="add-email" type="email" required value={add.email} onChange={(e) => setAdd({ ...add, email: e.target.value })} placeholder="user@digt.ch" className="input" autoComplete="off" />
          </Field>
          <Field label="Name" htmlFor="add-name">
            <input id="add-name" value={add.name} onChange={(e) => setAdd({ ...add, name: e.target.value })} className="input" autoComplete="off" />
          </Field>
        </div>
        <div className="flex flex-wrap gap-3">
          {roleChecks(add.roles, (role) => setAdd((a) => ({ ...a, roles: a.roles.includes(role) ? a.roles.filter((r) => r !== role) : [...a.roles, role] })))}
        </div>
        <Field label="Password (optional — leave blank for a Google-only user)" htmlFor="add-pw">
          <input id="add-pw" type="password" value={add.password} onChange={(e) => setAdd({ ...add, password: e.target.value })} className="input" autoComplete="new-password" />
        </Field>
        <button type="submit" className="btn-primary" disabled={busy === "__add"}>{busy === "__add" ? "Adding…" : "Add user"}</button>
      </form>

      <div className="space-y-3">
        {users.length === 0 && (
          <Notice kind="info">No users yet — add one above. Until then, sign in with the developer login (Superadmin).</Notice>
        )}
        {users.map((u) => (
          <div key={u.email} className="card">
            <div className="flex flex-wrap items-start justify-between gap-3">
              <div className="flex items-center gap-2">
                <span className="font-semibold text-slate-900">{u.email}</span>
                {u.hasPassword ? <Badge kind="ok">local + password</Badge> : <Badge kind="neutral">Google-only</Badge>}
              </div>
              <div className="flex gap-2">
                <button type="button" className="btn-primary px-3 py-1.5" onClick={() => saveUser(u)} disabled={busy === u.email}>Save</button>
                <button type="button" className="btn-danger px-3 py-1.5" onClick={() => removeUser(u.email)} disabled={busy === u.email} aria-label={`Delete ${u.email}`}>Delete</button>
              </div>
            </div>
            <div className="mt-3 grid gap-4 sm:grid-cols-2">
              <Field label="Name" htmlFor={`name-${u.email}`}>
                <input id={`name-${u.email}`} value={u.name} onChange={(e) => patchUser(u.email, { name: e.target.value })} className="input" autoComplete="off" />
              </Field>
              <Field label={u.hasPassword ? "Change password" : "Set password"} htmlFor={`pw-${u.email}`} hint={u.hasPassword ? "Leave blank to keep the current password." : "Set a password to enable username/password login."}>
                <input id={`pw-${u.email}`} type="password" value={pw[u.email] ?? ""} onChange={(e) => setPw((p) => ({ ...p, [u.email]: e.target.value }))} placeholder={u.hasPassword ? "•••••••• (set)" : "no password"} className="input" autoComplete="new-password" />
              </Field>
            </div>
            <div className="mt-3 flex flex-wrap gap-3">{roleChecks(u.roles, (role) => toggleRole(u.email, role))}</div>
          </div>
        ))}
      </div>
    </section>
  );
}
