import Link from "next/link";
import { format } from "date-fns";
import { de } from "date-fns/locale";
import { Users, CalendarCheck2, ShieldCheck, AlertTriangle, ClipboardList } from "lucide-react";
import { DutyAssignmentStatus, UserRole, NotdienstPlanStatus, TerminStatus } from "@prisma/client";

import { requireKitaSession } from "@/lib/auth-utils";
import { prisma } from "@/lib/prisma";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { OnboardingDialog } from "@/components/OnboardingDialog";
import { AlertButton } from "./alert-button";
import { AbsenceCard } from "./absence-card";
import { NewsTicker } from "./news-ticker";
import { RsvpActionCard } from "./rsvp-action-card";

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

export default async function DashboardPage() {
  const session = await requireKitaSession();
  const now = new Date();

  const kita = await prisma.kita.findUniqueOrThrow({
    where: { id: session.user.kitaId },
    select: {
      name: true,
      notdienstModuleEnabled: true,
      terminModuleEnabled: true,
      adressbuchModuleEnabled: true,
    },
  });

  const today = new Date();
  today.setHours(0, 0, 0, 0);

  // Schnelle Statistiken und persönliche Dienste für die Übersicht.
  const [
    familyCount,
    childCount,
    upcomingDuties,
    onboardingUser,
    absenceChildren,
    upcomingAbsences,
    latestAnnouncements,
  ] = await Promise.all([
    prisma.family.count({
      where: { kitaId: session.user.kitaId },
    }),
    prisma.child.count({
      where: { kitaId: session.user.kitaId },
    }),
    session.user.familyId
      ? prisma.dutyAssignment.findMany({
          where: {
            kitaId: session.user.kitaId,
            familyId: session.user.familyId,
            status: DutyAssignmentStatus.PLANNED,
            endDate: { gte: today },
          },
          select: {
            id: true,
            startDate: true,
            endDate: true,
            dutyType: {
              select: {
                name: true,
              },
            },
          },
          orderBy: { startDate: "asc" },
          take: 5,
        })
      : Promise.resolve([]),
    prisma.user.findFirstOrThrow({
      where: {
        id: session.user.id,
        kitaId: session.user.kitaId,
      },
      select: {
        phone: true,
        street: true,
        postalCode: true,
        city: true,
        familyId: true,
        role: true,
        family: {
          select: {
            _count: {
              select: {
                children: true,
              },
            },
          },
        },
      },
    }),
    session.user.familyId
      ? prisma.child.findMany({
          where: {
            kitaId: session.user.kitaId,
            familyId: session.user.familyId,
            active: true,
          },
          select: {
            id: true,
            firstName: true,
            lastName: true,
          },
          orderBy: [{ lastName: "asc" }, { firstName: "asc" }],
        })
      : Promise.resolve([]),
    session.user.familyId
      ? prisma.absence.findMany({
          where: {
            kitaId: session.user.kitaId,
            endDate: { gte: today },
            child: {
              familyId: session.user.familyId,
            },
          },
          select: {
            id: true,
            reason: true,
            note: true,
            startDate: true,
            endDate: true,
            child: {
              select: {
                firstName: true,
                lastName: true,
              },
            },
          },
          orderBy: [{ startDate: "asc" }],
          take: 6,
        })
      : Promise.resolve([]),
    prisma.announcement.findMany({
      where: { kitaId: session.user.kitaId },
      select: {
        id: true,
        title: true,
        content: true,
        createdAt: true,
        author: {
          select: {
            firstName: true,
            lastName: true,
          },
        },
        attachments: {
          select: {
            id: true,
            fileName: true,
            fileUrl: true,
            fileType: true,
          },
        },
        reads: {
          where: { userId: session.user.id },
          select: { id: true },
          take: 1,
        },
      },
      orderBy: { createdAt: "desc" },
      take: 3,
    }),
  ]);

  const familyChildIds = absenceChildren.map((child) => child.id);
  const openRsvpTermine =
    session.user.familyId && familyChildIds.length > 0
      ? await prisma.termin.findMany({
          where: {
            kitaId: session.user.kitaId,
            status: TerminStatus.CONFIRMED,
            requiresRsvp: true,
            OR: [
              { rsvpDeadline: { gt: now } },
              { rsvpDeadline: null, startDate: { gt: now } },
            ],
          },
          select: {
            id: true,
            title: true,
            startDate: true,
            rsvpDeadline: true,
            participations: {
              where: {
                childId: { in: familyChildIds },
              },
              select: {
                childId: true,
                status: true,
              },
            },
          },
          orderBy: { startDate: "asc" },
          take: 5,
        })
      : [];

  const rsvpActionEvents = openRsvpTermine
    .map((termin) => {
      const statusByChildId = new Map(
        termin.participations.map((participation) => [
          participation.childId,
          participation.status,
        ]),
      );

      return {
        id: termin.id,
        title: termin.title,
        startDate: termin.startDate.toISOString(),
        rsvpDeadline: termin.rsvpDeadline?.toISOString() ?? null,
        children: absenceChildren.map((child) => ({
          id: child.id,
          name: `${child.firstName} ${child.lastName}`,
          status: statusByChildId.get(child.id) ?? null,
        })),
      };
    })
    .filter((termin) => termin.children.some((child) => !child.status));

  const isAdmin =
    session.user.role === UserRole.ADMIN ||
    session.user.role === UserRole.SUPERADMIN;
  const canReportAbsences = session.user.role !== UserRole.ERZIEHER;

  return (
    <div className="px-8 py-8">
      <OnboardingDialog
        user={{
          phone: onboardingUser.phone,
          street: onboardingUser.street,
          postalCode: onboardingUser.postalCode,
          city: onboardingUser.city,
          familyId: onboardingUser.familyId,
          role: onboardingUser.role,
        }}
        family={
          onboardingUser.family
            ? { childrenCount: onboardingUser.family._count.children }
            : null
        }
      />

      <div className="mb-8">
        <h1 className="text-2xl font-semibold tracking-tight">
          Willkommen, {session.user.name?.split(" ")[0] ?? "zusammen"}!
        </h1>
        <p className="mt-1 text-sm text-muted-foreground">
          Hier ist die Übersicht für <strong>{kita.name}</strong>.
        </p>
      </div>

      <RsvpActionCard events={rsvpActionEvents} />

      <NewsTicker
        items={latestAnnouncements.map((announcement) => ({
          id: announcement.id,
          title: announcement.title,
          content: announcement.content,
          createdAt: format(announcement.createdAt, "dd.MM.yyyy", {
            locale: de,
          }),
          authorName: `${announcement.author.firstName} ${announcement.author.lastName}`,
          isUnread: announcement.reads.length === 0,
          attachments: announcement.attachments.map((attachment) => ({
            id: attachment.id,
            fileName: attachment.fileName,
            fileUrl: attachment.fileUrl,
            fileType: attachment.fileType,
          })),
        }))}
      />

      {/* Heutiger Notdienst (Nur für Admins/Koordinatoren) */}
      {isAdmin && (
        <div className="mb-8">
          <TodaysNotdienstCard kitaId={session.user.kitaId!} />
        </div>
      )}

      {canReportAbsences && (
        <AbsenceCard
          today={format(today, "yyyy-MM-dd")}
          childOptions={absenceChildren.map((child) => ({
            id: child.id,
            name: `${child.firstName} ${child.lastName}`,
          }))}
          absences={upcomingAbsences.map((absence) => ({
            id: absence.id,
            childName: `${absence.child.firstName} ${absence.child.lastName}`,
            reason: absence.reason,
            note: absence.note,
            startDate: format(absence.startDate, "yyyy-MM-dd"),
            endDate: format(absence.endDate, "yyyy-MM-dd"),
          }))}
        />
      )}

      {upcomingDuties.length > 0 && (
        <Card className="mb-8 border-emerald-200 bg-emerald-50/50">
          <CardHeader className="pb-3">
            <CardTitle className="flex items-center gap-2 text-lg">
              <ClipboardList className="h-5 w-5 text-emerald-700" />
              Deine anstehenden Dienste
            </CardTitle>
            <CardDescription>
              Die nächsten Einteilungen für deinen Haushalt.
            </CardDescription>
          </CardHeader>
          <CardContent className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
            {upcomingDuties.map((duty) => (
              <div key={duty.id} className="rounded-md border bg-background p-3">
                <p className="font-medium">{duty.dutyType.name}</p>
                <p className="mt-1 text-sm text-muted-foreground">
                  {format(duty.startDate, "dd.MM.", { locale: de })} bis{" "}
                  {format(duty.endDate, "dd.MM.yyyy", { locale: de })}
                </p>
              </div>
            ))}
          </CardContent>
        </Card>
      )}

      {/* Statistik-Kacheln */}
      <div className="mb-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
        <StatCard
          label="Familien"
          value={familyCount}
          description="registrierte Familien"
          icon={<Users className="h-5 w-5 text-muted-foreground" />}
        />
        <StatCard
          label="Kinder"
          value={childCount}
          description="in der Einrichtung"
          icon={<ShieldCheck className="h-5 w-5 text-muted-foreground" />}
        />
      </div>

      {/* Schnell-Aktionen für Admins */}
      {isAdmin && (
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Schnellstart</CardTitle>
            <CardDescription>
              Die nächsten Schritte, um deine Kita einzurichten.
            </CardDescription>
          </CardHeader>
          <CardContent className="flex flex-wrap gap-3">
            <Button asChild size="sm">
              <Link href="/dashboard/families">
                <Users className="mr-2 h-4 w-4" />
                Familien verwalten
              </Link>
            </Button>
            {kita.terminModuleEnabled && (
              <Button asChild size="sm" variant="outline">
                <Link href="/dashboard/kalender">
                  <CalendarCheck2 className="mr-2 h-4 w-4" />
                  Terminkalender
                </Link>
              </Button>
            )}
          </CardContent>
        </Card>
      )}
    </div>
  );
}

function StatCard({
  label,
  value,
  description,
  icon,
}: {
  label: string;
  value: number;
  description: string;
  icon: React.ReactNode;
}) {
  return (
    <Card>
      <CardHeader className="flex flex-row items-center justify-between pb-2">
        <CardTitle className="text-sm font-medium text-muted-foreground">
          {label}
        </CardTitle>
        {icon}
      </CardHeader>
      <CardContent>
        <div className="text-3xl font-bold">{value}</div>
        <p className="mt-1 text-xs text-muted-foreground">{description}</p>
      </CardContent>
    </Card>
  );
}

async function TodaysNotdienstCard({ kitaId }: { kitaId: string }) {
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  // Wir suchen das Assignment für heute, aber nur wenn der Plan PUBLISHED ist
  const assignment = await prisma.notdienstAssignment.findFirst({
    where: {
      kitaId,
      date: today,
      plan: { status: NotdienstPlanStatus.PUBLISHED },
    },
    select: {
      id: true,
      child: {
        select: {
          firstName: true,
          lastName: true,
          family: {
            select: {
              name: true,
              users: {
                select: {
                  firstName: true,
                  lastName: true,
                },
              },
            },
          },
        },
      },
      alerts: {
        select: {
          status: true,
        },
      },
    },
  });

  if (!assignment) return null;

  const parentNames = assignment.child.family.users
    .map((parent) => `${parent.firstName} ${parent.lastName}`)
    .join(", ");
  const existingAlert = assignment.alerts[0]; // Kann PENDING, CONFIRMED oder CANCELLED sein

  return (
    <Card className="border-primary/20 bg-primary/5">
      <CardHeader className="pb-3">
        <CardTitle className="text-lg flex items-center gap-2">
          <AlertTriangle className="h-5 w-5 text-primary" />
          Heutiger Notdienst
        </CardTitle>
        <CardDescription>
          Laut dem veröffentlichten Plan ist heute folgende Familie eingeteilt:
        </CardDescription>
      </CardHeader>
      <CardContent className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <p className="font-medium text-base">
            {parentNames || assignment.child.family.name}
          </p>
          <p className="text-sm text-muted-foreground">
            Kind: {assignment.child.firstName} {assignment.child.lastName}
          </p>
        </div>

        <div className="flex items-center gap-3">
          {existingAlert ? (
            <Badge
              variant={
                existingAlert.status === "CONFIRMED"
                  ? "success"
                  : existingAlert.status === "PENDING"
                    ? "warning"
                    : "destructive"
              }
              className="px-3 py-1 text-sm"
            >
              {existingAlert.status === "CONFIRMED"
                ? "Einsatz bestätigt"
                : existingAlert.status === "PENDING"
                  ? "Wartet auf Bestätigung"
                  : "Abgebrochen"}
            </Badge>
          ) : (
            <AlertButton assignmentId={assignment.id} />
          )}
        </div>
      </CardContent>
    </Card>
  );
}
