"use client";

import { useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { Icon } from "@/components/ui/Icon";
import { confirmDialog, alertDialog } from "@/components/ui/Dialog";
import {
  deleteApplicationAction,
  setApplicationReadAction,
  setApplicationStatusAction,
} from "@/lib/forms/actions";
import { APPLICATION_CATEGORIES, APPLICATION_STATUS, STATUS_COLOR } from "@/lib/forms/contract";
import type { ApplicationDTO } from "@/lib/forms/queries";

function fmt(dt: string): string {
  const d = new Date(dt.replace(" ", "T"));
  if (Number.isNaN(d.getTime())) return dt;
  return d.toLocaleString("de-DE", {
    day: "2-digit",
    month: "2-digit",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

export function ApplicationsPanel({
  applications,
  canManage,
}: {
  applications: ApplicationDTO[];
  canManage: boolean;
}) {
  const router = useRouter();
  const [status, setStatus] = useState<string | null>(null);
  const [query, setQuery] = useState("");
  const [open, setOpen] = useState<number | null>(null);
  const [busy, setBusy] = useState<number | null>(null);

  const shown = useMemo(() => {
    const q = query.trim().toLowerCase();
    return applications.filter((a) => {
      if (status && a.status !== status) return false;
      if (!q) return true;
      return (
        a.applicantName.toLowerCase().includes(q) ||
        a.applicantEmail.toLowerCase().includes(q) ||
        a.positionTitle.toLowerCase().includes(q) ||
        a.answers.some((an) => an.value.toLowerCase().includes(q))
      );
    });
  }, [applications, status, query]);

  const run = async (id: number, fn: () => Promise<{ error?: string }>) => {
    setBusy(id);
    const res = await fn();
    setBusy(null);
    if (res.error) await alertDialog({ title: "Fehler", message: res.error, danger: true });
    else router.refresh();
  };

  const remove = async (a: ApplicationDTO) => {
    const ok = await confirmDialog({
      title: `Bewerbung von „${a.applicantName}“ löschen?`,
      message: "Die Bewerbung wird endgültig aus der gemeinsamen Datenbank entfernt.",
      confirmLabel: "Löschen",
      danger: true,
    });
    if (!ok) return;
    await run(a.id, () => deleteApplicationAction(a.id));
  };

  return (
    <>
      <div className="mb-4 flex flex-wrap items-center gap-2">
        <div className="relative min-w-[200px] flex-1">
          <input
            className="input"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Name, E-Mail, Stelle oder Antwort …"
            style={{ paddingLeft: 38 }}
          />
          <span className="text-muted pointer-events-none absolute left-3 top-1/2 -translate-y-1/2">
            <Icon name="search" size={16} />
          </span>
        </div>
        <div className="flex flex-wrap gap-1.5">
          <button className="pill" data-active={status === null} onClick={() => setStatus(null)}>
            Alle
          </button>
          {Object.entries(APPLICATION_STATUS).map(([key, label]) => (
            <button
              key={key}
              className="pill"
              data-active={status === key}
              onClick={() => setStatus(key === status ? null : key)}
            >
              <span
                className="proto-dot"
                style={{ background: STATUS_COLOR[key], width: 7, height: 7 }}
              />
              {label}
            </button>
          ))}
        </div>
      </div>

      {shown.length === 0 ? (
        <div className="ui-empty">
          <span className="ui-empty-mark">
            <Icon name={query || status ? "search" : "mail"} size={26} />
          </span>
          <p className="ui-empty-title">
            {applications.length === 0 ? "Noch keine Bewerbungen" : "Keine Treffer"}
          </p>
          <p className="ui-empty-text">
            {applications.length === 0
              ? "Sobald sich jemand über die Website bewirbt, erscheint die Bewerbung hier."
              : "Passe Suche oder Statusfilter an."}
          </p>
        </div>
      ) : (
        <div className="rc-list">
          {shown.map((a) => {
            const expanded = open === a.id;
            const color = STATUS_COLOR[a.status] ?? "#8aa0c8";
            return (
              <article key={a.id} className="rc-item" data-unread={!a.isRead}>
                <button
                  className="rc-head"
                  onClick={() => setOpen(expanded ? null : a.id)}
                  aria-expanded={expanded}
                >
                  {!a.isRead ? <span className="rc-dot" /> : <span style={{ width: 8 }} />}
                  <span className="min-w-0 flex-1">
                    <span className="rc-title block truncate">
                      {a.applicantName}
                      <span className="text-muted"> · {a.positionTitle}</span>
                    </span>
                    <span className="rc-sub block truncate">
                      {a.applicantEmail}
                      {a.category ? ` · ${APPLICATION_CATEGORIES[a.category] ?? a.category}` : ""}
                      {` · ${fmt(a.createdAt)}`}
                      {a.positionId === null ? " · Stelle entfernt" : ""}
                    </span>
                  </span>
                  <span className="rc-status" style={{ color }}>
                    {APPLICATION_STATUS[a.status] ?? a.status}
                  </span>
                  <Icon
                    name="chevron"
                    size={15}
                    className="text-muted shrink-0"
                    style={{ transform: expanded ? "rotate(90deg)" : "none" }}
                  />
                </button>

                {expanded ? (
                  <div className="rc-body">
                    {a.answers.length === 0 ? (
                      <p className="text-muted text-sm">Keine Antworten gespeichert.</p>
                    ) : (
                      a.answers.map((an) => (
                        <div key={an.key} className="rc-answer">
                          {/* Beschriftung kommt aus der Bewerbung selbst — nicht aus
                              der heutigen Felddefinition der Stelle. */}
                          <span className="rc-answer-label">{an.label}</span>
                          <span className="rc-answer-value">{an.value || "—"}</span>
                        </div>
                      ))
                    )}

                    {canManage ? (
                      <div className="rc-actions">
                        {Object.entries(APPLICATION_STATUS).map(([key, label]) => (
                          <button
                            key={key}
                            className="pill"
                            data-active={a.status === key}
                            disabled={busy === a.id}
                            onClick={() =>
                              void run(a.id, () => setApplicationStatusAction(a.id, key))
                            }
                          >
                            <span
                              className="proto-dot"
                              style={{ background: STATUS_COLOR[key], width: 7, height: 7 }}
                            />
                            {label}
                          </button>
                        ))}
                        <span className="flex-1" />
                        <a className="btn btn-ghost btn-sm" href={`mailto:${a.applicantEmail}`}>
                          <Icon name="mail" size={14} /> Antworten
                        </a>
                        <button
                          className="btn btn-ghost btn-sm"
                          disabled={busy === a.id}
                          onClick={() =>
                            void run(a.id, () => setApplicationReadAction(a.id, !a.isRead))
                          }
                        >
                          <Icon name={a.isRead ? "bell" : "check"} size={14} />
                          {a.isRead ? "Ungelesen" : "Gelesen"}
                        </button>
                        <button
                          className="btn btn-ghost btn-sm"
                          disabled={busy === a.id}
                          onClick={() => void remove(a)}
                          title="Löschen"
                        >
                          <Icon name="trash" size={14} />
                        </button>
                      </div>
                    ) : null}
                  </div>
                ) : null}
              </article>
            );
          })}
        </div>
      )}
    </>
  );
}
