import {
  DutyAssignmentStatus,
  EventParticipationStatus,
  TerminStatus,
  TerminType,
  UserRole,
} from "@prisma/client";
import { HelpCircle, ListFilter, Search } from "lucide-react";

import { requireKitaSession } from "@/lib/auth-utils";
import { prisma } from "@/lib/prisma";
import { Input } from "@/components/ui/input";
import { AdminTerminModal } from "./_components/admin-termin-modal";
import { PendingAnfragen, type PendingTerminDto } from "./_components/pending-anfragen";
import { TerminList, type CalendarListItemDto } from "./_components/termin-list";
import { TerminRequestModal } from "./_components/termin-request-modal";

export const metadata = { title: "Terminkalender · Kita-Planer" };

export default async function KalenderPage({
  searchParams,
}: {
  searchParams: Promise<{ tab?: string }>;
}) {
  const session = await requireKitaSession();
  const isAdmin =
    session.user.role === UserRole.ADMIN ||
    session.user.role === UserRole.KOORDINATOR;
  const familyIdForParticipation = session.user.familyId ?? "__no_family__";

  const resolvedSearchParams = await searchParams;
  const currentTab = resolvedSearchParams.tab || "übersicht";
  const now = new Date();

  const confirmedTermineRows = await prisma.termin.findMany({
    where: {
      kitaId: session.user.kitaId,
      status: TerminStatus.CONFIRMED,
    },
    select: {
      id: true,
      title: true,
      description: true,
      type: true,
      status: true,
      startDate: true,
      endDate: true,
      allDay: true,
      mitbringselListEnabled: true,
      requiresRsvp: true,
      participantInfo: true,
      mitbringselItems: {
        select: {
          id: true,
          userId: true,
          content: true,
          user: {
            select: {
              firstName: true,
              lastName: true,
            },
          },
        },
      },
      participations: {
        where: {
          child: {
            familyId: familyIdForParticipation,
          },
        },
        select: {
          childId: true,
          status: true,
        },
      },
    },
    orderBy: { startDate: "asc" },
  });

  const myPendingTermineRows = await prisma.termin.findMany({
    where: {
      kitaId: session.user.kitaId,
      status: TerminStatus.PENDING,
      createdById: session.user.id,
    },
    select: {
      id: true,
      title: true,
      description: true,
      type: true,
      status: true,
      startDate: true,
      endDate: true,
      allDay: true,
      mitbringselListEnabled: true,
      requiresRsvp: true,
      participantInfo: true,
      mitbringselItems: {
        select: {
          id: true,
          userId: true,
          content: true,
          user: {
            select: {
              firstName: true,
              lastName: true,
            },
          },
        },
      },
      participations: {
        where: {
          child: {
            familyId: familyIdForParticipation,
          },
        },
        select: {
          childId: true,
          status: true,
        },
      },
    },
    orderBy: { startDate: "asc" },
  });

  const dutyAssignmentRows = await prisma.dutyAssignment.findMany({
    where: {
      kitaId: session.user.kitaId,
      status: DutyAssignmentStatus.PLANNED,
      endDate: { gte: now },
    },
    select: {
      id: true,
      startDate: true,
      endDate: true,
      status: true,
      dutyType: {
        select: {
          name: true,
        },
      },
      family: {
        select: {
          name: true,
        },
      },
    },
    orderBy: { startDate: "asc" },
  });

  const allUserTermine: CalendarListItemDto[] = [
    ...confirmedTermineRows.map((termin) => ({
      ...termin,
      kind: "termin" as const,
      showParticipantInfo:
        isAdmin ||
        termin.participations.some(
          (participation) =>
            participation.status === EventParticipationStatus.ATTENDING,
        ),
    })),
    ...myPendingTermineRows.map((termin) => ({
      ...termin,
      kind: "termin" as const,
      showParticipantInfo:
        isAdmin ||
        termin.participations.some(
          (participation) =>
            participation.status === EventParticipationStatus.ATTENDING,
        ),
    })),
    ...dutyAssignmentRows.map((assignment) => ({
      kind: "duty" as const,
      id: assignment.id,
      title: assignment.dutyType.name,
      familyName: assignment.family.name,
      status: assignment.status,
      startDate: assignment.startDate,
      endDate: assignment.endDate,
    })),
  ].sort((a, b) => a.startDate.getTime() - b.startDate.getTime());

  let allPendingTermine: PendingTerminDto[] = [];
  if (isAdmin) {
    const pendingRows = await prisma.termin.findMany({
      where: {
        kitaId: session.user.kitaId,
        status: TerminStatus.PENDING,
      },
      select: {
        id: true,
        title: true,
        startDate: true,
        createdAt: true,
        type: true,
        allDay: true,
        createdBy: {
          select: {
            firstName: true,
            lastName: true,
          },
        },
      },
      orderBy: { createdAt: "desc" },
    });
    allPendingTermine = pendingRows.map((termin) => ({
      ...termin,
      ageInDays: Math.floor(
        (now.getTime() - termin.createdAt.getTime()) / (1000 * 60 * 60 * 24),
      ),
    }));
  }

  return (
    <div className="mx-auto max-w-[1280px] px-11 py-9 pb-16 max-[760px]:px-5">
      <header className="mb-7 flex items-end justify-between gap-8 max-[900px]:items-start max-[900px]:flex-col">
        <div>
          <p className="text-[11px] font-semibold uppercase text-[var(--accent-deep)] [letter-spacing:0.18em]">
            TERMINKALENDER
          </p>
          <h1 className="mt-2 text-[36px] font-normal leading-tight tracking-[-0.025em] text-[var(--ink)]">
            Was steht{" "}
            <em className="font-normal italic text-[var(--accent-deep)]">
              an
            </em>
            ?
          </h1>
          <p className="mt-2 max-w-2xl text-[15px] leading-6 text-[var(--ink-soft)]">
            Alle anstehenden Termine, Feste, Dienste und Schließtage im
            Überblick.
          </p>
        </div>
        <div className="flex shrink-0 flex-wrap items-center gap-2">
          <TerminRequestModal />
          <span className="group relative inline-flex h-9 w-9 items-center justify-center rounded-full border border-[var(--hairline)] bg-[var(--surface)] text-[var(--ink-muted)]">
            <HelpCircle className="h-4 w-4 [stroke-width:1.7]" />
            <span className="pointer-events-none absolute right-0 top-11 z-30 hidden w-72 rounded-lg bg-[oklch(0.22_0.015_45)] px-3 py-2 text-left text-xs leading-5 text-white shadow-lg group-hover:block">
              Anfragen müssen vom Vorstand bestätigt werden, direkte Anlage
              erscheint sofort im Kalender.
            </span>
          </span>
          {isAdmin && <AdminTerminModal />}
        </div>
      </header>

      {isAdmin ? (
        <div className="flex flex-col gap-5">
          <TabBar
            currentTab={currentTab}
            overviewCount={allUserTermine.length}
            pendingCount={allPendingTermine.length}
          />

          <div>
            {currentTab === "übersicht" ? (
              <CalendarOverview
                termine={allUserTermine}
                userId={session.user.id}
                isAdmin={isAdmin}
              />
            ) : currentTab === "anfragen" ? (
              <PendingAnfragen termine={allPendingTermine} />
            ) : (
              <CalendarOverview
                termine={[]}
                userId={session.user.id}
                isAdmin={isAdmin}
              />
            )}
          </div>
        </div>
      ) : (
        <CalendarOverview
          termine={allUserTermine}
          userId={session.user.id}
          isAdmin={isAdmin}
        />
      )}
    </div>
  );
}

function CalendarOverview({
  termine,
  userId,
  isAdmin,
}: {
  termine: CalendarListItemDto[];
  userId: string;
  isAdmin: boolean;
}) {
  return (
    <div className="space-y-5">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <div className="inline-flex overflow-hidden rounded-full border border-[var(--hairline)] bg-[var(--surface)]">
          {["Liste", "Monat", "Agenda"].map((label, index) => (
            <button
              key={label}
              type="button"
              className={[
                "h-9 px-4 text-[13px] font-semibold transition",
                index > 0 ? "border-l border-[var(--hairline-soft)]" : "",
                index === 0
                  ? "bg-[var(--accent-soft)] text-[var(--accent-deep)]"
                  : "text-[var(--ink-soft)] hover:bg-[var(--surface-2)] hover:text-[var(--ink)]",
              ].join(" ")}
            >
              {label}
            </button>
          ))}
        </div>

        <div className="flex flex-1 flex-wrap items-center justify-end gap-2">
          <CategoryChips />
          <div className="relative min-w-56">
            <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--ink-muted)] [stroke-width:1.7]" />
            <Input placeholder="Termine suchen" className="h-9 pl-9" />
          </div>
        </div>
      </div>

      <TerminList termine={termine} userId={userId} isAdmin={isAdmin} />
    </div>
  );
}

function TabBar({
  currentTab,
  overviewCount,
  pendingCount,
}: {
  currentTab: string;
  overviewCount: number;
  pendingCount: number;
}) {
  return (
    <div className="flex border-b border-[var(--hairline)]">
      <TabLink
        href="/dashboard/kalender?tab=übersicht"
        active={currentTab === "übersicht"}
        count={overviewCount}
      >
        Übersicht
      </TabLink>
      <TabLink
        href="/dashboard/kalender?tab=anfragen"
        active={currentTab === "anfragen"}
        count={pendingCount}
        attention={pendingCount > 0}
      >
        Ausstehende Anfragen
      </TabLink>
      <TabLink
        href="/dashboard/kalender?tab=vergangen"
        active={currentTab === "vergangen"}
      >
        Vergangene
      </TabLink>
    </div>
  );
}

function TabLink({
  href,
  active,
  count,
  attention,
  children,
}: {
  href: string;
  active: boolean;
  count?: number;
  attention?: boolean;
  children: React.ReactNode;
}) {
  return (
    <a
      href={href}
      className={[
        "-mb-px inline-flex h-11 items-center gap-2 border-b-2 px-1.5 text-sm transition first:pl-0",
        active
          ? "border-[var(--accent)] font-semibold text-[var(--ink)]"
          : "border-transparent font-medium text-[var(--ink-soft)] hover:text-[var(--ink)]",
      ].join(" ")}
    >
      {children}
      {typeof count === "number" && (
        <span
          className={[
            "rounded-full px-2 py-0.5 text-[11px] font-semibold tabular-nums",
            attention
              ? "bg-[var(--accent-deep)] text-[oklch(0.98_0.005_45)]"
              : "border border-[var(--hairline)] bg-[var(--surface-2)] text-[var(--ink-soft)]",
          ].join(" ")}
        >
          {count}
        </span>
      )}
    </a>
  );
}

function CategoryChips() {
  const categories = [
    ["Schließtag", TerminType.SCHLIESSTAG],
    ["Teamtag", TerminType.TEAMTAG],
    ["Elternabend", TerminType.ELTERNABEND],
    ["Fest", TerminType.KITA_FEST],
    ["Geburtstag", TerminType.GEBURTSTAG_INTERN],
    ["Sonstiges", TerminType.SONSTIGES],
  ] as const;

  return (
    <div className="flex flex-wrap gap-1.5">
      <span className="inline-flex h-9 items-center gap-1.5 rounded-full border border-[var(--hairline)] bg-[var(--surface)] px-3 text-[13px] font-medium text-[var(--ink-soft)]">
        <ListFilter className="h-3.5 w-3.5 [stroke-width:1.7]" />
        Filter
      </span>
      {categories.map(([label, type]) => (
        <span
          key={label}
          className="inline-flex h-9 items-center gap-1.5 rounded-full border border-[var(--hairline)] bg-[var(--surface)] px-3 text-[13px] font-medium text-[var(--ink-soft)]"
        >
          <span
            className="h-2 w-2 rounded-full"
            style={{ backgroundColor: getCategoryColor(type) }}
          />
          {label}
        </span>
      ))}
    </div>
  );
}

function getCategoryColor(type: TerminType) {
  switch (type) {
    case TerminType.SCHLIESSTAG:
    case TerminType.TEAMTAG:
      return "var(--danger)";
    case TerminType.ELTERNABEND:
      return "oklch(0.50 0.10 280)";
    case TerminType.KITA_FEST:
      return "var(--good)";
    case TerminType.GEBURTSTAG_INTERN:
      return "oklch(0.50 0.10 320)";
    default:
      return "var(--ink-muted)";
  }
}
