import Link from "next/link";
import { getServerSession } from "next-auth";
import { Prisma } from "@prisma/client";
import { authOptions } from "../lib/auth/options";
import { prisma } from "../lib/db/prisma";
import { ChartCard } from "../components/chart-card";
import { EmptyState } from "../components/empty-state";
import { formatHours } from "../lib/ui/format";
import { localDateKey, rangeDateKeys, rangeDates } from "../lib/timezone";

function hours(minutes?: number | null) {
  return Math.round(((minutes ?? 0) / 60) * 10) / 10;
}

function dashboardHref(searchParams: { range?: string; from?: string; to?: string }, drilldown: string, id: string | null) {
  const params = new URLSearchParams();
  params.set("range", searchParams.range ?? "7");
  if (searchParams.from) params.set("from", searchParams.from);
  if (searchParams.to) params.set("to", searchParams.to);
  params.set("drilldown", drilldown);
  if (id) params.set("id", id);
  return `/admin?${params.toString()}`;
}

export default async function AdminDashboardPage({ searchParams }: { searchParams: { range?: string; from?: string; to?: string; drilldown?: string; id?: string } }) {
  const session = await getServerSession(authOptions);
  const organizationId = session?.user.organizationId;
  const systemAdmin = session?.user.systemRole === "SYSTEM_ADMIN";
  const tenantWhere = systemAdmin ? {} : { organizationId: organizationId! };
  const settings = organizationId ? await prisma.organizationSettings.findUnique({ where: { organizationId } }) : null;
  const timezone = settings?.timezone ?? "UTC";
  const { range, from, to, fromKey, toKey } = rangeDates(searchParams, timezone);
  const timeWhere: Prisma.TimeEntryWhereInput = { ...tenantWhere, startAt: { gte: from, lte: to } };

  const morningStart = new Date();
  morningStart.setHours(9, 0, 0, 0);
  const [organizations, users, projects, pendingAdhoc, screenshotCount, runningNow, byUser, byProject, byTeam, activeUsers, latestEntries, rangeEntries, rangeScreenshots] = await Promise.all([
    systemAdmin ? prisma.organization.count() : Promise.resolve(organizationId ? 1 : 0),
    prisma.user.count({ where: tenantWhere }),
    prisma.project.count({ where: tenantWhere }),
    prisma.adhocRecord.count({ where: { ...tenantWhere, status: "pending" } }),
    prisma.screenshot.count({ where: { ...tenantWhere, capturedAt: { gte: from, lte: to } } }),
    prisma.timeEntry.count({ where: { ...tenantWhere, isRunning: true } }),
    prisma.timeEntry.groupBy({ by: ["userId"], where: timeWhere, _sum: { durationMinutes: true } }),
    prisma.timeEntry.groupBy({ by: ["projectId"], where: timeWhere, _sum: { durationMinutes: true } }),
    prisma.timeEntry.groupBy({ by: ["teamId"], where: timeWhere, _sum: { durationMinutes: true } }),
    prisma.user.findMany({ where: { ...tenantWhere, status: "active" }, include: { team: true } }),
    prisma.timeEntry.findMany({
      where: tenantWhere,
      orderBy: { startAt: "desc" },
      distinct: ["userId"],
      select: { userId: true, startAt: true }
    }),
    prisma.timeEntry.findMany({
      where: timeWhere,
      orderBy: { startAt: "desc" },
      include: {
        user: { select: { id: true, name: true, email: true } },
        project: { select: { id: true, name: true } }
      }
    }),
    prisma.screenshot.findMany({ where: { ...tenantWhere, capturedAt: { gte: from, lte: to } }, select: { capturedAt: true } })
  ]);

  const projectRows = await prisma.project.findMany({ where: tenantWhere });
  const userMap = new Map(activeUsers.map((user) => [user.id, user.name ?? user.email]));
  const projectMap = new Map(projectRows.map((project) => [project.id, project.name]));
  const teamMap = new Map(activeUsers.map((user) => [user.teamId, user.team?.name ?? "No team"]));
  const latestByUser = new Map(latestEntries.map((entry) => [entry.userId, entry.startAt]));
  const missingMorning = activeUsers.filter((user) => {
    const lastClockIn = latestByUser.get(user.id);
    return !lastClockIn || lastClockIn < morningStart;
  });
  const totalMinutes = byUser.reduce((sum, item) => sum + (item._sum.durationMinutes ?? 0), 0);
  const days = rangeDateKeys(from, to, timezone);
  const dailyHours = new Map(days.map((day) => [day, 0]));
  const dailyScreenshots = new Map(days.map((day) => [day, 0]));
  for (const entry of rangeEntries) {
    const key = localDateKey(entry.startAt, timezone);
    dailyHours.set(key, (dailyHours.get(key) ?? 0) + hours(entry.durationMinutes));
  }
  for (const shot of rangeScreenshots) {
    const key = localDateKey(shot.capturedAt, timezone);
    dailyScreenshots.set(key, (dailyScreenshots.get(key) ?? 0) + 1);
  }

  const drilldown = searchParams.drilldown;
  const drilldownId = searchParams.id ?? null;
  const drilldownEntries = rangeEntries.filter((entry) => {
    if (drilldown === "user") return entry.userId === drilldownId;
    if (drilldown === "project") return entry.projectId === drilldownId;
    if (drilldown === "team") return entry.teamId === drilldownId;
    if (drilldown === "day") return localDateKey(entry.startAt, timezone) === drilldownId;
    return false;
  }).slice(0, 25);

  const stats = [
    ["Organizations", organizations],
    ["Users", users],
    ["Projects", projects],
    ["Pending adhoc", pendingAdhoc],
    ["Screenshots", screenshotCount],
    ["Running now", runningNow]
  ];

  const rangeLinks = [
    ["7", "Last 7 days"],
    ["15", "Last 15 days"],
    ["30", "Last 30 days"]
  ];

  return (
    <div>
      <div className="admin-card bg-white p-6">
        <div className="flex flex-wrap items-start justify-between gap-4">
          <div>
            <p className="text-sm font-semibold uppercase tracking-wide text-brand-primary">Overview</p>
            <h1 className="mt-1 text-3xl font-semibold">Dashboard</h1>
            <p className="mt-2 text-slate-600">Tenant-isolated analytics from {fromKey} to {toKey} in {timezone}.</p>
          </div>
          <div className="flex flex-wrap gap-2">
            {rangeLinks.map(([value, label]) => (
              <Link className={`rounded-lg border px-3 py-2 text-sm font-semibold transition ${range === value ? "border-slate-950 bg-slate-950 text-white" : "border-slate-200 bg-white text-slate-700 hover:border-slate-400"}`} href={`/admin?range=${value}`} key={value}>
                {label}
              </Link>
            ))}
          </div>
        </div>
      </div>

      <form className="admin-card mt-4 flex flex-wrap items-end gap-3 p-4">
        <input type="hidden" name="range" value="custom" />
        <label className="admin-label">From<input className="admin-input" name="from" type="date" defaultValue={fromKey} /></label>
        <label className="admin-label">To<input className="admin-input" name="to" type="date" defaultValue={toKey} /></label>
        <button className="brand-button" type="submit">Apply</button>
      </form>

      <section className="mt-6 grid gap-4 md:grid-cols-3 xl:grid-cols-6">
        {stats.map(([label, value]) => (
          <article className="admin-card p-5" key={label}>
            <p className="text-sm font-semibold text-slate-500">{label}</p>
            <strong className="mt-2 block text-3xl tracking-tight">{value}</strong>
          </article>
        ))}
      </section>

      <section className="mt-6 grid gap-5 xl:grid-cols-3">
        <ChartCard title="Daily work hours" data={days.map((day) => ({ label: day, value: dailyHours.get(day) ?? 0, href: dashboardHref(searchParams, "day", day) }))} />
        <ChartCard title="User-wise work hours" data={byUser.map((item) => ({ label: userMap.get(item.userId) ?? "Unknown user", value: hours(item._sum.durationMinutes), href: dashboardHref(searchParams, "user", item.userId) }))} />
        <ChartCard title="Project-wise work hours" data={byProject.map((item) => ({ label: item.projectId ? projectMap.get(item.projectId) ?? "Unknown project" : "No project", value: hours(item._sum.durationMinutes), href: dashboardHref(searchParams, "project", item.projectId) }))} />
      </section>

      <section className="mt-6 grid gap-5 xl:grid-cols-2">
        <ChartCard title="Team-wise work hours" data={byTeam.map((item) => ({ label: item.teamId ? teamMap.get(item.teamId) ?? "Unknown team" : "No team", value: hours(item._sum.durationMinutes), href: dashboardHref(searchParams, "team", item.teamId) }))} />
        <ChartCard title="Daily screenshots" suffix="" data={days.map((day) => ({ label: day, value: dailyScreenshots.get(day) ?? 0, href: dashboardHref(searchParams, "day", day) }))} />
      </section>

      {drilldown ? (
        <section className="admin-card mt-6 overflow-hidden p-5">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <div>
              <h2 className="text-lg font-semibold">Drilldown</h2>
              <p className="mt-1 text-sm text-slate-500">{drilldown} details for the selected range.</p>
            </div>
            <Link className="brand-button-secondary" href={`/admin?range=${range}${range === "custom" ? `&from=${fromKey}&to=${toKey}` : ""}`}>Clear</Link>
          </div>
          <div className="mt-4 overflow-x-auto">
            <table className="min-w-full text-left text-sm">
              <thead className="text-xs uppercase tracking-wide text-slate-500">
                <tr>
                  <th className="py-2 pr-4">Employee</th>
                  <th className="py-2 pr-4">Project</th>
                  <th className="py-2 pr-4">Team</th>
                  <th className="py-2 pr-4">Start</th>
                  <th className="py-2 pr-4">Duration</th>
                </tr>
              </thead>
              <tbody>
                {drilldownEntries.map((entry) => (
                  <tr className="border-t border-slate-100" key={entry.id}>
                    <td className="py-2 pr-4">{entry.user.name ?? entry.user.email}</td>
                    <td className="py-2 pr-4">{entry.project?.name ?? "No project"}</td>
                    <td className="py-2 pr-4">{entry.teamId ? teamMap.get(entry.teamId) ?? "Unknown team" : "No team"}</td>
                    <td className="py-2 pr-4">{entry.startAt.toLocaleString("en", { timeZone: timezone })}</td>
                    <td className="py-2 pr-4">{formatHours(entry.durationMinutes ?? 0)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
            {!drilldownEntries.length ? <EmptyState title="No matching entries" description="This drilldown has no tracked time in the selected range." /> : null}
          </div>
        </section>
      ) : null}

      <section className="admin-card mt-6 p-5">
        <div className="flex flex-wrap items-center justify-between gap-3">
          <h2 className="text-lg font-semibold">WorkOnClock not running since morning</h2>
          <span className="rounded-lg bg-slate-100 px-3 py-1.5 text-sm font-medium text-slate-500">Morning starts at 9:00 AM local time</span>
        </div>
        <div className="mt-4 grid gap-2">
          {missingMorning.length ? missingMorning.map((user) => (
            <div className="flex flex-wrap items-center justify-between gap-3 rounded-lg border border-slate-200 bg-slate-50 p-3 dark:border-slate-800 dark:bg-slate-950" key={user.id}>
              <span className="font-medium">{user.name ?? user.email}</span>
              <span className="text-sm text-slate-500">{user.team?.name ?? "No team"} · {user.email}</span>
            </div>
          )) : <EmptyState title="Everyone is active" description="All active employees have clocked in since morning." />}
        </div>
        <p className="mt-4 text-sm text-slate-500">Total tracked time in this range: {formatHours(totalMinutes)}</p>
      </section>
    </div>
  );
}
