"use client";

import { FileSpreadsheet, FileText, Save, Trash2 } from "lucide-react";
import Link from "next/link";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useState } from "react";
import { deleteReport, saveReport } from "@/actions/reports";
import { Button, LINK_BUTTON_CLASS } from "@/components/ui/Button";
import { CONTROL_CLASS, SelectField, TextField } from "@/components/ui/Field";
import { Modal } from "@/components/ui/Modal";
import { useToast } from "@/components/ui/Toast";
import { fmtDate } from "@/lib/format";
import {
  AVERAGE_MEASURES,
  EVENT_DATE_OPEN,
  EVENT_GROUP_LABELS,
  EVENT_REPORT_PRESETS,
  EVENT_TYPE_LABELS,
  GROUP_LABELS,
  MEASURE_LABELS,
  parseStatuses,
  REPORT_PRESETS,
  sortKeysForDimension,
  STATUS_OPTIONS,
  todayIso,
  type EventGroupDimension,
  type GroupDimension,
  type Measure,
  type ReportRow,
} from "@/lib/reports";
import type { HistoryEventType } from "@/lib/supabase/types";

const SPLIT_COLORS = ["bg-brand-500", "bg-info-text", "bg-purple-text", "bg-warning-text", "bg-success-text", "bg-danger-solid"];
const EVENT_TYPES = Object.keys(EVENT_TYPE_LABELS) as HistoryEventType[];

type SavedReport = { id: string; name: string; config: Record<string, unknown> };
type OrgOption = { id: string; name: string };

type CommonProps = {
  rows: ReportRow[];
  total: number;
  recordCount: number;
  divisions: OrgOption[];
  locations: OrgOption[];
  savedReports: SavedReport[];
};

type SnapshotProps = CommonProps & {
  mode: "snapshot";
  measure: Measure;
  group: GroupDimension;
  split: GroupDimension | "";
  asOf: string;
  filters: { division: string; location: string; status: string; employment: string };
};

type EventsProps = CommonProps & {
  mode: "events";
  eventGroup: EventGroupDimension;
  eventSplit: EventGroupDimension | "";
  eventType: string;
  eventFilters: { division: string; location: string; from: string; to: string };
};

type ReportsPageClientProps = SnapshotProps | EventsProps;

function formatValue(measure: Measure, value: number): string {
  if (measure === "headcount") return String(Math.round(value));
  if (measure === "fte") return value.toFixed(1);
  if (measure === "parttime_rate" || measure === "female_share") return `${value.toFixed(1)}%`;
  if (measure === "avg_age" || measure === "avg_tenure") return `${value.toFixed(1)} Jahre`;
  return value.toFixed(1);
}

export function ReportsPageClient(props: ReportsPageClientProps) {
  const { mode, rows, total, recordCount, divisions, locations, savedReports } = props;
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const { showToast } = useToast();
  const [expandedKey, setExpandedKey] = useState<string | null>(null);
  const [saveModalOpen, setSaveModalOpen] = useState(false);
  const [newReportName, setNewReportName] = useState("");
  const [savingReport, setSavingReport] = useState(false);

  function updateParams(patch: Record<string, string | undefined>) {
    const sp = new URLSearchParams(searchParams.toString());
    for (const [k, v] of Object.entries(patch)) {
      if (v) sp.set(k, v);
      else sp.delete(k);
    }
    router.push(`${pathname}?${sp.toString()}`, { scroll: false });
  }

  function switchMode(next: "snapshot" | "events") {
    router.push(`${pathname}?mode=${next}`, { scroll: false });
  }

  function toggleStatus(status: string) {
    if (mode !== "snapshot") return;
    const current = parseStatuses(props.filters.status);
    const next = current.includes(status as (typeof current)[number]) ? current.filter((s) => s !== status) : [...current, status];
    updateParams({ status: next.length > 0 ? next.join(",") : undefined });
  }

  function applyPreset(preset: { group: string; split?: string; eventType?: string; measure?: string }) {
    const sp = new URLSearchParams({ mode });
    if (preset.measure) sp.set("measure", preset.measure);
    sp.set("group", preset.group);
    if (preset.split) sp.set("split", preset.split);
    if (preset.eventType) sp.set("eventType", preset.eventType);
    router.push(`${pathname}?${sp.toString()}`, { scroll: false });
  }

  function applySavedReport(config: Record<string, unknown>) {
    const sp = new URLSearchParams();
    for (const [k, v] of Object.entries(config)) {
      if (typeof v === "string" && v) sp.set(k, v);
    }
    if (!sp.get("mode")) sp.set("mode", "snapshot");
    router.push(`${pathname}?${sp.toString()}`, { scroll: false });
  }

  async function handleConfirmSaveReport() {
    if (!newReportName.trim()) {
      showToast("Bitte einen Namen angeben.", "error");
      return;
    }
    const config =
      mode === "snapshot"
        ? { mode, measure: props.measure, group: props.group, split: props.split, asOf: props.asOf, ...props.filters }
        : { mode, group: props.eventGroup, split: props.eventSplit, eventType: props.eventType, ...props.eventFilters };
    setSavingReport(true);
    const result = await saveReport({ name: newReportName.trim(), config });
    setSavingReport(false);
    if (result.success) {
      showToast("Bericht gespeichert.");
      setSaveModalOpen(false);
      setNewReportName("");
      router.refresh();
    } else {
      showToast(result.error ?? "Fehler beim Speichern.", "error");
    }
  }

  async function handleDeleteReport(id: string) {
    const result = await deleteReport(id);
    if (result.success) {
      showToast("Bericht gelöscht.");
      router.refresh();
    } else {
      showToast(result.error ?? "Fehler beim Löschen.", "error");
    }
  }

  function reportExportHref(format: "csv" | "xlsx"): string {
    const sp = new URLSearchParams();
    sp.set("format", format);
    sp.set("mode", mode);
    if (mode === "snapshot") {
      sp.set("measure", props.measure);
      sp.set("group", props.group);
      if (props.split) sp.set("split", props.split);
      if (props.asOf) sp.set("asOf", props.asOf);
      for (const [k, v] of Object.entries(props.filters)) if (v) sp.set(k, v);
    } else {
      sp.set("group", props.eventGroup);
      if (props.eventSplit) sp.set("split", props.eventSplit);
      if (props.eventType) sp.set("eventType", props.eventType);
      for (const [k, v] of Object.entries(props.eventFilters)) if (v) sp.set(k, v);
    }
    return `/api/export/report?${sp.toString()}`;
  }

  function fullExportHref(format: "csv" | "xlsx"): string {
    if (mode === "snapshot") {
      const sp = new URLSearchParams();
      sp.set("format", format);
      if (props.asOf) sp.set("asOf", props.asOf);
      if (props.filters.division) sp.set("division", props.filters.division);
      if (props.filters.location) sp.set("location", props.filters.location);
      if (props.filters.status) sp.set("status", props.filters.status);
      if (props.filters.employment) sp.set("employment", props.filters.employment);
      return `/api/export/employees?${sp.toString()}`;
    }
    const sp = new URLSearchParams();
    sp.set("format", format);
    if (props.eventType) sp.set("eventType", props.eventType);
    for (const [k, v] of Object.entries(props.eventFilters)) if (v) sp.set(k, v);
    return `/api/export/events?${sp.toString()}`;
  }

  const isAverage = mode === "snapshot" && AVERAGE_MEASURES.includes(props.measure);
  const maxValue = Math.max(1, ...rows.map((r) => r.value));
  const rawSplitKeys = Array.from(new Set(rows.flatMap((r) => r.split?.map((s) => s.key) ?? [])));
  const splitKeys = mode === "snapshot" && props.split ? sortKeysForDimension(rawSplitKeys, props.split) : rawSplitKeys;
  const showWeekdayMultiCountNote = mode === "snapshot" && (props.group === "weekday" || props.split === "weekday");
  const selectedStatuses = mode === "snapshot" ? parseStatuses(props.filters.status) : [];
  const statusExportLabel = selectedStatuses.length === STATUS_OPTIONS.length ? "Alle" : selectedStatuses.join(", ");
  const currentYear = new Date().getFullYear();
  const defaultEventFrom = `${currentYear}-01-01`;
  const defaultEventTo = `${currentYear}-12-31`;

  const heading =
    mode === "snapshot"
      ? `${MEASURE_LABELS[props.measure]} nach ${GROUP_LABELS[props.group]}`
      : `${props.eventType ? EVENT_TYPE_LABELS[props.eventType as HistoryEventType] : "Ereignisse"} nach ${EVENT_GROUP_LABELS[props.eventGroup]}`;
  const totalDisplay = mode === "snapshot" ? formatValue(props.measure, total) : String(Math.round(total));

  return (
    <div className="grid grid-cols-1 gap-4 lg:grid-cols-[320px_1fr]">
      <div className="flex flex-col gap-4">
        <div role="tablist" aria-label="Berichtsart" className="flex rounded border border-border bg-white p-1 text-sm font-semibold">
          {(["snapshot", "events"] as const).map((m) => (
            <button
              key={m}
              type="button"
              role="tab"
              aria-selected={mode === m}
              onClick={() => switchMode(m)}
              className={`flex-1 rounded px-3 py-1.5 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-brand-500 ${
                mode === m ? "bg-brand-500 text-white" : "text-ink-body hover:bg-surface"
              }`}
            >
              {m === "snapshot" ? "Bestand" : "Ereignisse"}
            </button>
          ))}
        </div>

        {mode === "snapshot" ? (
          <div className="rounded border border-border bg-white p-4">
            <div className="flex flex-col gap-3">
              <SelectField
                label="Kennzahl"
                dense
                value={props.measure}
                onChange={(v) => updateParams({ measure: v, split: AVERAGE_MEASURES.includes(v as Measure) ? undefined : props.split })}
                options={(Object.keys(MEASURE_LABELS) as Measure[]).map((m) => ({ value: m, label: MEASURE_LABELS[m] }))}
              />
              <SelectField
                label="Gruppieren nach"
                dense
                value={props.group}
                onChange={(v) => updateParams({ group: v })}
                options={(Object.keys(GROUP_LABELS) as GroupDimension[]).map((g) => ({ value: g, label: GROUP_LABELS[g] }))}
              />
              <SelectField
                label="Aufteilen nach"
                dense
                value={props.split}
                disabled={isAverage}
                onChange={(v) => updateParams({ split: v || undefined })}
                hint={isAverage ? "Bei Durchschnittswerten nicht verfügbar." : undefined}
                options={[
                  { value: "", label: "Keine Aufteilung" },
                  ...(Object.keys(GROUP_LABELS) as GroupDimension[])
                    .filter((g) => g !== props.group)
                    .map((g) => ({ value: g, label: GROUP_LABELS[g] })),
                ]}
              />
              <div>
                <div className="flex items-end gap-2">
                  <TextField
                    label="Stichtag"
                    dense
                    className="flex-1"
                    type="date"
                    value={props.asOf || todayIso()}
                    onChange={(v) => updateParams({ asOf: v })}
                  />
                  {props.asOf && (
                    <Button
                      variant="ghost"
                      size="sm"
                      onClick={() => updateParams({ asOf: undefined })}
                      className="!px-1 whitespace-nowrap text-brand-700 hover:!bg-transparent hover:underline"
                    >
                      Heute
                    </Button>
                  )}
                </div>
                <p className="mt-1 text-xs text-ink-muted">
                  Bestand wird rückgerechnet (Eintritt/Austritt/Langzeitabwesenheit); Bereich/Team zeigen die aktuelle
                  Zuordnung.
                </p>
              </div>
            </div>
          </div>
        ) : (
          <div className="rounded border border-border bg-white p-4">
            <div className="flex flex-col gap-3">
              <SelectField
                label="Ereignistyp"
                dense
                value={props.eventType}
                onChange={(v) => updateParams({ eventType: v || undefined })}
                options={[
                  { value: "", label: "Alle Ereignistypen" },
                  ...EVENT_TYPES.map((t) => ({ value: t, label: EVENT_TYPE_LABELS[t] })),
                ]}
              />
              <SelectField
                label="Gruppieren nach"
                dense
                value={props.eventGroup}
                onChange={(v) => updateParams({ group: v })}
                options={(Object.keys(EVENT_GROUP_LABELS) as EventGroupDimension[]).map((g) => ({ value: g, label: EVENT_GROUP_LABELS[g] }))}
              />
              <SelectField
                label="Aufteilen nach"
                dense
                value={props.eventSplit}
                onChange={(v) => updateParams({ split: v || undefined })}
                options={[
                  { value: "", label: "Keine Aufteilung" },
                  ...(Object.keys(EVENT_GROUP_LABELS) as EventGroupDimension[])
                    .filter((g) => g !== props.eventGroup)
                    .map((g) => ({ value: g, label: EVENT_GROUP_LABELS[g] })),
                ]}
              />
              <fieldset>
                <legend className="mb-1 block text-xs font-semibold uppercase tracking-wide text-ink-muted">Zeitraum</legend>
                <div className="grid grid-cols-2 gap-2">
                  <div>
                    <TextField
                      label="Von"
                      dense
                      type="date"
                      value={props.eventFilters.from === EVENT_DATE_OPEN ? "" : props.eventFilters.from || defaultEventFrom}
                      disabled={props.eventFilters.from === EVENT_DATE_OPEN}
                      onChange={(v) => updateParams({ from: v })}
                    />
                    <Button
                      variant="ghost"
                      size="sm"
                      onClick={() => updateParams({ from: props.eventFilters.from === EVENT_DATE_OPEN ? defaultEventFrom : EVENT_DATE_OPEN })}
                      className="mt-1 !px-0 text-brand-700 hover:!bg-transparent hover:underline"
                    >
                      {props.eventFilters.from === EVENT_DATE_OPEN ? "Startdatum setzen" : "Ab Anfang (offen)"}
                    </Button>
                  </div>
                  <div>
                    <TextField
                      label="Bis"
                      dense
                      type="date"
                      value={props.eventFilters.to === EVENT_DATE_OPEN ? "" : props.eventFilters.to || defaultEventTo}
                      disabled={props.eventFilters.to === EVENT_DATE_OPEN}
                      onChange={(v) => updateParams({ to: v })}
                    />
                    <Button
                      variant="ghost"
                      size="sm"
                      onClick={() => updateParams({ to: props.eventFilters.to === EVENT_DATE_OPEN ? defaultEventTo : EVENT_DATE_OPEN })}
                      className="mt-1 !px-0 text-brand-700 hover:!bg-transparent hover:underline"
                    >
                      {props.eventFilters.to === EVENT_DATE_OPEN ? "Enddatum setzen" : "Bis heute (offen)"}
                    </Button>
                  </div>
                </div>
              </fieldset>
            </div>
          </div>
        )}

        <div className="rounded border border-border bg-white p-4">
          <h3 className="mb-2 text-xs font-semibold uppercase tracking-wide text-ink-muted">Filter</h3>
          <div className="flex flex-col gap-2">
            <select
              aria-label="Nach Bereich filtern"
              value={mode === "snapshot" ? props.filters.division : props.eventFilters.division}
              onChange={(e) => updateParams({ division: e.target.value })}
              className={CONTROL_CLASS}
            >
              <option value="">Alle Bereiche</option>
              {divisions.map((d) => (
                <option key={d.id} value={d.id}>
                  {d.name}
                </option>
              ))}
            </select>
            <select
              aria-label="Nach Standort filtern"
              value={mode === "snapshot" ? props.filters.location : props.eventFilters.location}
              onChange={(e) => updateParams({ location: e.target.value })}
              className={CONTROL_CLASS}
            >
              <option value="">Alle Standorte</option>
              {locations.map((l) => (
                <option key={l.id} value={l.id}>
                  {l.name}
                </option>
              ))}
            </select>
            {mode === "snapshot" && (
              <>
                <fieldset className="rounded border border-border px-3 py-2">
                  <legend className="mb-1.5 text-xs font-semibold text-ink-muted">Status (zum Stichtag)</legend>
                  <div className="flex flex-wrap gap-x-4 gap-y-1.5">
                    {STATUS_OPTIONS.map((s) => (
                      <label key={s} className="flex items-center gap-1.5 text-sm text-ink-body">
                        <input
                          type="checkbox"
                          checked={selectedStatuses.includes(s)}
                          onChange={() => toggleStatus(s)}
                          className="h-4 w-4 rounded border-border accent-brand-500"
                        />
                        {s}
                      </label>
                    ))}
                  </div>
                </fieldset>
                <select
                  aria-label="Nach Beschäftigungsart filtern"
                  value={props.filters.employment}
                  onChange={(e) => updateParams({ employment: e.target.value })}
                  className={CONTROL_CLASS}
                >
                  <option value="">Alle Beschäftigungsarten</option>
                  <option value="Vollzeit">Vollzeit</option>
                  <option value="Teilzeit">Teilzeit</option>
                </select>
              </>
            )}
          </div>
        </div>

        <div className="rounded border border-border bg-white p-4">
          <h3 className="mb-2 text-xs font-semibold uppercase tracking-wide text-ink-muted">Vorlagen</h3>
          <div className="flex flex-wrap gap-1.5">
            {(mode === "snapshot" ? REPORT_PRESETS : EVENT_REPORT_PRESETS).map((preset) => (
              <Button key={preset.name} variant="secondary" size="sm" onClick={() => applyPreset(preset)} className="!rounded-full !px-2.5 !py-1">
                {preset.name}
              </Button>
            ))}
          </div>
        </div>

        <div className="rounded border border-border bg-white p-4">
          <h3 className="mb-1 text-xs font-semibold uppercase tracking-wide text-ink-muted">Vollständiger Datenexport</h3>
          {mode === "snapshot" ? (
            <>
              <p className="mb-1 text-xs text-ink-muted">Alle Mitarbeiterdaten (nicht nur die Kennzahl){props.asOf ? ` zum Stichtag ${fmtDate(props.asOf)}` : ""}.</p>
              <p className="mb-2 rounded bg-surface px-2 py-1.5 text-xs font-semibold text-ink-body">Status im Export: {statusExportLabel}</p>
            </>
          ) : (
            <p className="mb-2 text-xs text-ink-muted">Alle Ereignisse im gewählten Zeitraum als Rohdaten (eine Zeile pro Ereignis).</p>
          )}
          <div className="flex gap-2">
            <a href={fullExportHref("csv")} className={LINK_BUTTON_CLASS}>
              <FileText className="h-4 w-4" />
              CSV
            </a>
            <a href={fullExportHref("xlsx")} className={LINK_BUTTON_CLASS}>
              <FileSpreadsheet className="h-4 w-4" />
              Excel
            </a>
          </div>
        </div>

        {savedReports.length > 0 && (
          <div className="rounded border border-border bg-white p-4">
            <h3 className="mb-2 text-xs font-semibold uppercase tracking-wide text-ink-muted">Gespeicherte Berichte</h3>
            <ul className="flex flex-col divide-y divide-border">
              {savedReports.map((r) => (
                <li key={r.id} className="flex items-center justify-between py-1.5 text-sm">
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => applySavedReport(r.config)}
                    className="!px-0 !justify-start text-left hover:!bg-transparent hover:text-brand-700 hover:underline"
                  >
                    {r.name}
                  </Button>
                  <Button
                    variant="icon"
                    onClick={() => handleDeleteReport(r.id)}
                    aria-label={`Bericht ${r.name} löschen`}
                    className="hover:!text-danger-solid"
                  >
                    <Trash2 className="h-3.5 w-3.5" />
                  </Button>
                </li>
              ))}
            </ul>
          </div>
        )}
      </div>

      <div className="rounded border border-border bg-white p-4">
        <div className="mb-4 flex flex-wrap items-center justify-between gap-2">
          <div>
            <h2 className="text-base font-bold text-ink">{heading}</h2>
            <p className="text-xs text-ink-muted">{recordCount} {mode === "snapshot" ? "Datensätze" : "Ereignisse"}</p>
          </div>
          <div className="flex gap-2">
            <a href={reportExportHref("csv")} className={LINK_BUTTON_CLASS}>
              <FileText className="h-4 w-4" />
              CSV
            </a>
            <a href={reportExportHref("xlsx")} className={LINK_BUTTON_CLASS}>
              <FileSpreadsheet className="h-4 w-4" />
              Excel
            </a>
            <Button variant="secondary" size="sm" onClick={() => setSaveModalOpen(true)}>
              <Save className="h-4 w-4" />
              Bericht speichern
            </Button>
          </div>
        </div>

        <p className="mb-4 text-2xl font-extrabold text-ink">{totalDisplay}</p>
        {showWeekdayMultiCountNote && (
          <p className="mb-3 text-xs text-ink-muted">
            Mitarbeitende mit mehreren Arbeitstagen zählen bei „Wochentag“ an jedem ihrer Arbeitstage mehrfach – Summe und Anteile ergeben daher mehr als den Gesamt-Headcount bzw. 100%.
          </p>
        )}

        {((mode === "snapshot" && props.split) || (mode === "events" && props.eventSplit)) && (
          <div className="mb-3 flex flex-wrap gap-3">
            {splitKeys.map((key, i) => (
              <span key={key} className="flex items-center gap-1.5 text-xs text-ink-body">
                <span className={`h-2.5 w-2.5 rounded-full ${SPLIT_COLORS[i % SPLIT_COLORS.length]}`} />
                {key}
              </span>
            ))}
          </div>
        )}

        <div className="flex flex-col gap-3">
          {rows.map((row) => {
            const share = total > 0 ? (row.value / total) * 100 : 0;
            const isExpanded = expandedKey === row.key;
            return (
              <div key={row.key}>
                <button type="button" onClick={() => setExpandedKey(isExpanded ? null : row.key)} className="w-full text-left">
                  <div className="mb-1 flex items-center justify-between text-sm">
                    <span className="font-semibold text-ink">{row.key}</span>
                    <span className="text-ink-body">
                      {mode === "snapshot" ? formatValue(props.measure, row.value) : Math.round(row.value)}{" "}
                      <span className="text-xs text-ink-muted">({share.toFixed(1)}%)</span>
                    </span>
                  </div>
                  <div className="flex h-2.5 overflow-hidden rounded bg-surface">
                    {row.split ? (
                      row.split.map((s, i) => (
                        <div key={s.key} className={SPLIT_COLORS[i % SPLIT_COLORS.length]} style={{ width: `${maxValue > 0 ? (s.value / maxValue) * 100 : 0}%` }} />
                      ))
                    ) : (
                      <div className="bg-brand-500" style={{ width: `${(row.value / maxValue) * 100}%` }} />
                    )}
                  </div>
                </button>
                {isExpanded && (
                  <div className="mt-2 rounded border border-border bg-surface p-3">
                    <ul className="flex flex-col divide-y divide-border">
                      {row.people.slice(0, 12).map((p, i) => (
                        <li key={`${p.id}-${i}`} className="flex items-center justify-between py-1.5 text-sm">
                          <Link href={`/employees/${p.id}`} className="font-semibold text-ink hover:text-brand-700 hover:underline">
                            {p.name}
                          </Link>
                          <span className="text-xs text-ink-muted">
                            {p.title} · {p.team} · {fmtDate(p.entry_date)}
                          </span>
                        </li>
                      ))}
                    </ul>
                    {row.people.length > 12 && <p className="mt-2 text-xs text-ink-muted">+{row.people.length - 12} weitere</p>}
                  </div>
                )}
              </div>
            );
          })}
          {rows.length === 0 && <p className="text-sm text-ink-muted">Keine Daten für diese Auswahl.</p>}
        </div>
      </div>

      <Modal
        open={saveModalOpen}
        onClose={() => setSaveModalOpen(false)}
        title="Bericht speichern"
        footer={
          <>
            <Button variant="ghost" onClick={() => setSaveModalOpen(false)}>
              Abbrechen
            </Button>
            <Button onClick={handleConfirmSaveReport} pending={savingReport}>
              Speichern
            </Button>
          </>
        }
      >
        <TextField
          label="Name für diesen Bericht"
          required
          value={newReportName}
          onChange={setNewReportName}
          onKeyDown={(e) => e.key === "Enter" && handleConfirmSaveReport()}
          autoFocus
        />
      </Modal>
    </div>
  );
}
