"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Copy, RotateCcw, Search, Trash2, UserPlus2, X } from "lucide-react";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { useAuth } from "@/components/auth";
import { apiDelete, apiFetch, apiGet, Paginated, User } from "@/lib/api";
import { buildUsersQueryParams } from "@/lib/users-query";

const schema = z.object({
  first_name: z.string().min(1, "Vorname erforderlich"),
  last_name: z.string().min(1, "Nachname erforderlich"),
  email: z.string().email("Gueltige E-Mail erforderlich"),
  role: z.enum(["admin", "pruefer", "mitarbeiter", "leser"]),
  is_active: z.boolean().default(true),
  must_change_password: z.boolean().default(true),
  temporary_password: z.string().min(12, "Mindestens 12 Zeichen")
});

type UserForm = z.infer<typeof schema>;

const roleLabels: Record<User["role"], string> = {
  admin: "ADMIN",
  pruefer: "PRUEFER",
  mitarbeiter: "MITARBEITER",
  leser: "LESER"
};

export default function UsersPage() {
  const { token, user } = useAuth();
  const client = useQueryClient();
  const [search, setSearch] = useState("");
  const [role, setRole] = useState("");
  const [active, setActive] = useState<"all" | "active" | "inactive">("all");
  const [page, setPage] = useState(1);
  const [sortBy, setSortBy] = useState("created_at");
  const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc");
  const [editing, setEditing] = useState<User | null>(null);
  const [temporaryPassword, setTemporaryPassword] = useState("");
  const [temporaryPasswordOpen, setTemporaryPasswordOpen] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<User | null>(null);
  const [message, setMessage] = useState("");
  const [error, setError] = useState("");

  const form = useForm<UserForm>({
    resolver: zodResolver(schema),
    defaultValues: {
      first_name: "",
      last_name: "",
      email: "",
      role: "mitarbeiter",
      is_active: true,
      must_change_password: true,
      temporary_password: ""
    }
  });

  const users = useQuery({
    queryKey: ["users", page, 20, search, role, active, sortBy, sortOrder],
    queryFn: () =>
      apiGet<Paginated<User>>(
        `/users?${buildUsersQueryParams({
          page,
          pageSize: 20,
          search,
          role,
          active: active === "all" ? undefined : active === "active",
          sortBy,
          sortOrder
        }).toString()}`,
        token ?? ""
      ),
    enabled: Boolean(token)
  });
  const pages = users.data?.pages ?? Math.max(1, Math.ceil((users.data?.total ?? 0) / (users.data?.page_size ?? 20)));

  const saveMutation = useMutation({
    mutationFn: async (values: UserForm) => {
      const payload = {
        ...values,
        email: values.email.trim().toLowerCase()
      };
      if (editing) {
        return apiFetch<User>(`/users/${editing.id}`, token ?? "", { method: "PUT", body: JSON.stringify(payload) });
      }
      return apiFetch<{ temporary_password: string; user: User }>(`/users`, token ?? "", {
        method: "POST",
        body: JSON.stringify(payload)
      });
    },
    onSuccess: async (created) => {
      const isCreate = !editing;
      if (!editing) {
        setTemporaryPassword((created as { temporary_password?: string }).temporary_password ?? "");
      } else {
        setTemporaryPassword("");
      }
      setMessage(editing ? "Benutzer gespeichert" : "Benutzer angelegt");
      setError("");
      setEditing(null);
      setTemporaryPasswordOpen(isCreate && Boolean((created as { temporary_password?: string }).temporary_password));
      form.reset();
      await client.invalidateQueries({ queryKey: ["users"] });
    },
    onError: (err: Error) => setError(err.message)
  });

  const deleteMutation = useMutation({
    mutationFn: (item: User) => apiDelete(`/users/${item.id}`, token ?? ""),
    onSuccess: async () => {
      setMessage("Benutzer geloescht");
      setError("");
      setDeleteTarget(null);
      await client.invalidateQueries({ queryKey: ["users"] });
    },
    onError: (err: Error) => setError(err.message)
  });
  const resetMutation = useMutation({
    mutationFn: (item: User) => apiFetch<{ temporary_password: string }>(`/users/${item.id}/reset-password`, token ?? "", { method: "POST" }),
    onSuccess: (result) => {
      setTemporaryPassword(result.temporary_password);
      setMessage("Temporäres Passwort erzeugt");
      setTemporaryPasswordOpen(true);
    }
  });

  if (user?.role !== "admin") {
    return <div className="rounded-lg border border-border bg-surface p-6 text-text-light">Nur fuer Administratoren verfuegbar.</div>;
  }

  function startCreate() {
    setEditing(null);
    form.reset({ first_name: "", last_name: "", email: "", role: "mitarbeiter", is_active: true, must_change_password: true, temporary_password: "" });
  }

  function startEdit(item: User) {
    setEditing(item);
    form.reset({
      first_name: item.first_name,
      last_name: item.last_name,
      email: item.email,
      role: item.role,
      is_active: item.is_active,
      must_change_password: item.must_change_password,
      temporary_password: ""
    });
  }

  function submit(values: UserForm) {
    if (saveMutation.isPending) return;
    saveMutation.mutate(values);
  }

  return (
    <div className="space-y-6">
      <header className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
        <div>
          <h1 className="text-3xl font-semibold text-text">Benutzer</h1>
          <p className="mt-2 text-text-light">Verwaltung von Rollen, Aktivstatus und Passworten.</p>
        </div>
        <button type="button" className="btn btn-primary h-12" onClick={startCreate}><UserPlus2 className="h-4 w-4" /> Benutzer anlegen</button>
      </header>
      <section className="rounded-lg border border-border bg-surface p-4 shadow-soft">
        <div className="grid gap-3 md:grid-cols-4">
          <label className="flex h-12 items-center gap-2 rounded-lg border border-border px-3 md:col-span-2">
            <Search className="h-4 w-4 text-primary" />
            <input value={search} onChange={(e) => setSearch(e.target.value)} className="flex-1 outline-none" placeholder="Suchen" />
          </label>
          <select value={role} onChange={(e) => setRole(e.target.value)} className="h-12 rounded-lg border border-border px-3">
            <option value="">Alle Rollen</option>
            {Object.entries(roleLabels).map(([value, label]) => <option key={value} value={value}>{label}</option>)}
          </select>
          <select value={active} onChange={(e) => setActive(e.target.value as "all" | "active" | "inactive")} className="h-12 rounded-lg border border-border px-3">
            <option value="all">Alle Status</option>
            <option value="active">Aktiv</option>
            <option value="inactive">Inaktiv</option>
          </select>
          <select value={sortBy} onChange={(e) => setSortBy(e.target.value)} className="h-12 rounded-lg border border-border px-3">
            <option value="created_at">Erstellt am</option>
            <option value="name">Name</option>
            <option value="email">E-Mail</option>
            <option value="role">Rolle</option>
            <option value="last_login_at">Letzter Login</option>
            <option value="password_changed_at">Passwort geaendert</option>
          </select>
          <button type="button" className="btn btn-secondary h-12" onClick={() => setSortOrder((value) => (value === "asc" ? "desc" : "asc"))}>
            Sortierung: {sortOrder.toUpperCase()}
          </button>
        </div>
      </section>
      <section className="overflow-hidden rounded-lg border border-border bg-surface shadow-soft">
        {users.isLoading ? (
          <div className="flex items-center gap-3 px-5 py-6 text-sm text-text-light">
            <span className="spinner" />
            Benutzer werden geladen...
          </div>
        ) : users.isError ? (
          <div className="px-5 py-6 text-sm text-danger">Benutzer konnten nicht geladen werden.</div>
        ) : null}
        <div className="overflow-x-auto">
          <table className="min-w-full text-left text-sm">
            <thead className="bg-background text-xs uppercase text-text-light">
              <tr>
                <th className="px-5 py-4">Name</th>
                <th className="px-5 py-4">E-Mail</th>
                <th className="px-5 py-4">Rolle</th>
                <th className="px-5 py-4">Status</th>
                <th className="px-5 py-4">Letzter Login</th>
                <th className="px-5 py-4">Passwort zuletzt geaendert</th>
                <th className="px-5 py-4 text-right">Aktionen</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-border">
              {!users.isLoading && !users.isError && (users.data?.items.length ?? 0) === 0 ? (
                <tr>
                  <td className="px-5 py-6 text-sm text-text-light" colSpan={7}>
                    Keine Benutzer vorhanden.
                  </td>
                </tr>
              ) : (
                (users.data?.items ?? []).map((item) => (
                  <tr key={item.id}>
                    <td className="px-5 py-4">{item.first_name} {item.last_name}</td>
                    <td className="px-5 py-4">{item.email}</td>
                    <td className="px-5 py-4">{roleLabels[item.role]}</td>
                    <td className="px-5 py-4">{item.is_active ? "Aktiv" : "Inaktiv"}</td>
                    <td className="px-5 py-4">{item.last_login_at ?? "nicht erfasst"}</td>
                    <td className="px-5 py-4">{item.password_changed_at ?? "nicht erfasst"}</td>
                    <td className="px-5 py-4">
                      <div className="flex justify-end gap-2">
                        <button type="button" className="btn btn-secondary h-10 px-3" onClick={() => startEdit(item)}>Bearbeiten</button>
                        <button type="button" className="btn btn-secondary h-10 px-3" onClick={() => resetMutation.mutate(item)}>{resetMutation.isPending ? <span className="spinner" /> : <RotateCcw className="h-4 w-4" />} Passwort zurücksetzen</button>
                        <button type="button" className="btn btn-danger h-10 px-3" onClick={() => setDeleteTarget(item)}><Trash2 className="h-4 w-4" /> Löschen</button>
                      </div>
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>
      </section>
      <footer className="flex items-center justify-between text-sm text-text-light">
        <span>{users.data?.total ?? 0} Datensätze</span>
        <div className="flex items-center gap-3">
          <button type="button" className="btn btn-secondary" disabled={page <= 1} onClick={() => setPage((v) => v - 1)}>Zurück</button>
          <span>Seite {page} von {pages}</span>
          <button type="button" className="btn btn-secondary" disabled={(users.data?.items.length ?? 0) < 20 || page >= pages} onClick={() => setPage((v) => v + 1)}>Weiter</button>
        </div>
      </footer>
      {temporaryPasswordOpen && temporaryPassword && (
        <div className="fixed inset-0 z-50 flex items-end bg-black/20 p-3 sm:items-center sm:justify-center">
          <div className="w-full max-w-md rounded-lg border border-border bg-surface p-5 shadow-soft">
            <div className="flex items-center justify-between gap-3">
              <h2 className="text-lg font-semibold">Passwort zurückgesetzt</h2>
              <button type="button" aria-label="Schliessen" onClick={() => setTemporaryPasswordOpen(false)} className="icon-btn"><X className="h-4 w-4" /></button>
            </div>
            <p className="mt-3 text-sm text-text-light">Dieses Passwort wird nur einmal angezeigt.</p>
            <div className="mt-4 rounded-lg border border-border bg-background px-4 py-3 font-mono text-lg tracking-wide">{temporaryPassword}</div>
            <div className="mt-4 flex flex-wrap gap-3">
              <button type="button" className="btn btn-secondary h-11" onClick={async () => navigator.clipboard.writeText(temporaryPassword)}><Copy className="h-4 w-4" /> Kopieren</button>
              <button type="button" className="btn btn-primary h-11" onClick={() => setTemporaryPasswordOpen(false)}>Schliessen</button>
            </div>
          </div>
        </div>
      )}
      {message && <div className="fixed right-4 top-4 z-50 rounded-lg border border-success/30 bg-white p-4 text-sm text-success shadow-soft">{message}</div>}
      {error && <div className="fixed right-4 top-4 z-50 rounded-lg border border-danger/30 bg-white p-4 text-sm text-danger shadow-soft">{error}</div>}
      <form onSubmit={form.handleSubmit(submit)} className="rounded-lg border border-border bg-surface p-5 shadow-soft">
        <h2 className="text-xl font-semibold">{editing ? "Benutzer bearbeiten" : "Benutzer anlegen"}</h2>
        <div className="mt-4 grid gap-4 md:grid-cols-2">
          {(["first_name", "last_name", "email", "temporary_password"] as const).map((field) => (
            <label key={field} className="block">
              <span className="text-sm font-medium">{field === "first_name" ? "Vorname" : field === "last_name" ? "Nachname" : field === "email" ? "E-Mail" : "Temporäres Passwort"}</span>
              <input type={field === "email" ? "email" : "text"} {...form.register(field)} className="mt-2 h-12 w-full rounded-lg border border-border px-4" />
            </label>
          ))}
          <label className="block">
            <span className="text-sm font-medium">Rolle</span>
            <select {...form.register("role")} className="mt-2 h-12 w-full rounded-lg border border-border px-4">
              {Object.entries(roleLabels).map(([value, label]) => <option key={value} value={value}>{label}</option>)}
            </select>
          </label>
          <label className="flex items-center gap-3 pt-7"><input type="checkbox" {...form.register("is_active")} /> Aktiv</label>
          <label className="flex items-center gap-3 pt-7"><input type="checkbox" {...form.register("must_change_password")} /> Passwortwechsel erzwingen</label>
        </div>
        <div className="mt-5 flex justify-end gap-3">
          <button type="button" className="btn btn-secondary" onClick={() => form.reset()}>Zurücksetzen</button>
          <button type="submit" disabled={saveMutation.isPending} className="btn btn-primary">{saveMutation.isPending ? <span className="spinner" /> : null}{saveMutation.isPending ? "Speichern..." : "Speichern"}</button>
        </div>
      </form>
      {deleteTarget && (
        <div className="fixed inset-0 z-50 flex items-end bg-black/20 p-3 sm:items-center sm:justify-center">
          <div className="w-full max-w-lg rounded-lg border border-border bg-surface p-5 shadow-soft">
            <h2 className="text-xl font-semibold">Benutzer wirklich löschen?</h2>
            <p className="mt-2 text-sm text-text-light">
              {deleteTarget.first_name} {deleteTarget.last_name}
              <br />
              {deleteTarget.email}
            </p>
            <div className="mt-5 flex justify-end gap-3">
              <button type="button" className="btn btn-secondary" onClick={() => setDeleteTarget(null)}>Abbrechen</button>
              <button type="button" className="btn btn-danger" disabled={deleteMutation.isPending} onClick={() => deleteMutation.mutate(deleteTarget)}>
                {deleteMutation.isPending ? <span className="spinner" /> : null}
                {deleteMutation.isPending ? "Löschen..." : "Löschen"}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
