import Link from "next/link";
import { redirect } from "next/navigation";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { isAdminEmail } from "@/lib/admin";
import { prisma } from "@/lib/prisma";
import { systemHealthService } from "@/server/services/system-health.service";

interface JobSummary {
  jobName: string;
  lastRun: { at: Date; status: string; errorMessage: string | null } | null;
  lastSuccess: Date | null;
  totalRuns7d: number;
  failedRuns7d: number;
}

async function getJobSummary(jobName: string): Promise<JobSummary> {
  const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
  const [lastRun, lastSuccessRow, totalRuns7d, failedRuns7d] =
    await Promise.all([
      prisma.cronRun.findFirst({
        where: { jobName },
        orderBy: { startedAt: "desc" },
        select: { startedAt: true, status: true, errorMessage: true },
      }),
      prisma.cronRun.findFirst({
        where: { jobName, status: "SUCCESS" },
        orderBy: { startedAt: "desc" },
        select: { startedAt: true },
      }),
      prisma.cronRun.count({
        where: { jobName, startedAt: { gte: sevenDaysAgo } },
      }),
      prisma.cronRun.count({
        where: {
          jobName,
          status: "FAILED",
          startedAt: { gte: sevenDaysAgo },
        },
      }),
    ]);
  return {
    jobName,
    lastRun: lastRun
      ? {
          at: lastRun.startedAt,
          status: lastRun.status,
          errorMessage: lastRun.errorMessage,
        }
      : null,
    lastSuccess: lastSuccessRow?.startedAt ?? null,
    totalRuns7d,
    failedRuns7d,
  };
}

// Daftar cron yang dipantau. Tambah entry baru saat menambah cron route handler.
const TRACKED_JOBS = ["auto-complete-trips", "process-email-jobs"] as const;

function healthOf(summary: JobSummary): "ok" | "stale" | "failed" {
  if (summary.lastRun?.status === "FAILED") return "failed";
  if (!summary.lastSuccess) return "stale";
  const hoursSince =
    (Date.now() - summary.lastSuccess.getTime()) / (1000 * 60 * 60);
  // Asumsi cron daily — > 25 jam dianggap stale.
  if (hoursSince > 25) return "stale";
  return "ok";
}

export default async function AdminSystemPage() {
  const session = await getServerSession(authOptions);
  if (!session?.user) redirect("/login?callbackUrl=/admin/system");
  if (!isAdminEmail(session.user.email)) {
    return (
      <div className="mx-auto max-w-2xl px-4 py-12 text-center">
        <p className="text-sm text-neutral-600">
          Halaman ini hanya untuk admin SeTrip.
        </p>
      </div>
    );
  }

  const [summaries, recentRuns, stale] = await Promise.all([
    Promise.all(TRACKED_JOBS.map(getJobSummary)),
    prisma.cronRun.findMany({
      orderBy: { startedAt: "desc" },
      take: 20,
    }),
    systemHealthService.detectStale(),
  ]);

  const hasAnyStale =
    stale.stalePaymentsCount > 0 ||
    stale.awaitingPayPastDepartureCount > 0 ||
    stale.overduePayoutsCount > 0 ||
    stale.stuckRefundsCount > 0;

  return (
    <div className="mx-auto max-w-5xl px-4 py-8 sm:py-12">
      <header className="mb-6">
        <h1 className="text-2xl font-bold text-neutral-900 sm:text-3xl">
          System Health
        </h1>
        <p className="mt-1 text-sm text-neutral-500">
          Status cron job otomatis. Refresh halaman ini setelah trigger cron
          manual atau saat investigasi.
        </p>
      </header>

      {hasAnyStale && (
        <section className="mb-6 rounded-2xl border border-amber-300 bg-amber-50 p-4 sm:p-5">
          <h2 className="mb-2 text-sm font-bold text-amber-900">
            ⚠️ Stale State Alerts
          </h2>
          <ul className="space-y-1 text-xs text-amber-900">
            {stale.stalePaymentsCount > 0 && (
              <li>
                • <strong>{stale.stalePaymentsCount}</strong> Payment MIDTRANS
                AWAITING &gt; 25 jam — webhook mungkin tertunda. Cek manual lalu
                reconcile.
              </li>
            )}
            {stale.awaitingPayPastDepartureCount > 0 && (
              <li>
                • <strong>{stale.awaitingPayPastDepartureCount}</strong> Booking
                AWAITING_PAY tapi trip sudah lewat tanggal berangkat — peserta
                lupa bayar, butuh cleanup.
              </li>
            )}
            {stale.overduePayoutsCount > 0 && (
              <li>
                • <strong>{stale.overduePayoutsCount}</strong> Payout HELD lewat
                heldUntil &gt; 1 hari — cron release mungkin tidak jalan, cek
                cron history di bawah.{" "}
                <Link
                  href="/admin/payouts?tab=HELD"
                  className="font-semibold text-amber-700 hover:underline"
                >
                  Lihat HELD →
                </Link>
              </li>
            )}
            {stale.stuckRefundsCount > 0 && (
              <li>
                • <strong>{stale.stuckRefundsCount}</strong> Refund APPROVED
                &gt; 7 hari belum di-process.{" "}
                <Link
                  href="/admin/refunds?tab=APPROVED"
                  className="font-semibold text-amber-700 hover:underline"
                >
                  Lihat APPROVED →
                </Link>
              </li>
            )}
          </ul>
        </section>
      )}

      <section className="mb-8">
        <h2 className="mb-3 text-xs font-bold uppercase tracking-wide text-neutral-500">
          Cron Jobs
        </h2>
        <div className="grid gap-3 sm:grid-cols-2">
          {summaries.map((s) => {
            const health = healthOf(s);
            const cls =
              health === "ok"
                ? "border-emerald-200 bg-emerald-50/50"
                : health === "stale"
                  ? "border-amber-200 bg-amber-50/50"
                  : "border-red-200 bg-red-50/50";
            const badge =
              health === "ok"
                ? { label: "🟢 OK", cls: "bg-emerald-100 text-emerald-800" }
                : health === "stale"
                  ? {
                      label: "🟡 STALE",
                      cls: "bg-amber-100 text-amber-800",
                    }
                  : {
                      label: "🔴 FAILED",
                      cls: "bg-red-100 text-red-800",
                    };
            return (
              <div
                key={s.jobName}
                className={`rounded-2xl border p-4 shadow-sm sm:p-5 ${cls}`}
              >
                <div className="flex items-start justify-between gap-2">
                  <div>
                    <p className="text-[10px] font-semibold uppercase tracking-wide text-neutral-500">
                      Job
                    </p>
                    <p className="font-mono text-sm font-bold text-neutral-800">
                      {s.jobName}
                    </p>
                  </div>
                  <span
                    className={`rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide ${badge.cls}`}
                  >
                    {badge.label}
                  </span>
                </div>
                <dl className="mt-3 space-y-1 text-xs text-neutral-700">
                  <div>
                    <dt className="inline font-semibold">Last run:</dt>{" "}
                    <dd className="inline">
                      {s.lastRun
                        ? `${formatDateTime(s.lastRun.at)} · ${s.lastRun.status}`
                        : "Belum pernah"}
                    </dd>
                  </div>
                  <div>
                    <dt className="inline font-semibold">Last success:</dt>{" "}
                    <dd className="inline">
                      {s.lastSuccess
                        ? formatDateTime(s.lastSuccess)
                        : "Belum pernah"}
                    </dd>
                  </div>
                  <div>
                    <dt className="inline font-semibold">7 hari terakhir:</dt>{" "}
                    <dd className="inline">
                      {s.totalRuns7d} run, {s.failedRuns7d} failed
                    </dd>
                  </div>
                  {s.lastRun?.errorMessage && (
                    <div className="mt-2 rounded-lg bg-red-100 p-2 text-[11px] text-red-800">
                      Error terakhir: {s.lastRun.errorMessage}
                    </div>
                  )}
                </dl>
              </div>
            );
          })}
        </div>
      </section>

      <section>
        <h2 className="mb-3 text-xs font-bold uppercase tracking-wide text-neutral-500">
          Recent Runs (20 terakhir)
        </h2>
        {recentRuns.length === 0 ? (
          <div className="rounded-2xl border border-dashed border-neutral-300 bg-white p-8 text-center">
            <p className="text-sm text-neutral-500">
              Belum ada cron run tercatat. Setelah cron berikutnya jalan, baris
              pertama akan muncul di sini.
            </p>
          </div>
        ) : (
          <div className="overflow-x-auto rounded-2xl border border-neutral-200 bg-white shadow-sm">
            <table className="min-w-full divide-y divide-neutral-100 text-sm">
              <thead className="bg-neutral-50 text-[10px] font-semibold uppercase tracking-wide text-neutral-500">
                <tr>
                  <th className="px-3 py-2 text-left">Job</th>
                  <th className="px-3 py-2 text-left">Started</th>
                  <th className="px-3 py-2 text-left">Finished</th>
                  <th className="px-3 py-2 text-left">Status</th>
                  <th className="px-3 py-2 text-left">Note</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-neutral-100 text-xs text-neutral-700">
                {recentRuns.map((r) => (
                  <tr key={r.id}>
                    <td className="px-3 py-2 font-mono">{r.jobName}</td>
                    <td className="px-3 py-2">{formatDateTime(r.startedAt)}</td>
                    <td className="px-3 py-2">
                      {r.finishedAt ? formatDateTime(r.finishedAt) : "—"}
                    </td>
                    <td className="px-3 py-2">
                      <StatusBadge value={r.status} />
                    </td>
                    <td className="px-3 py-2 text-neutral-500">
                      {r.errorMessage ??
                        (r.payload
                          ? truncate(JSON.stringify(r.payload), 80)
                          : "—")}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </section>
    </div>
  );
}

function formatDateTime(d: Date): string {
  return d.toLocaleString("id-ID", {
    day: "2-digit",
    month: "short",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

function truncate(s: string, max: number): string {
  return s.length > max ? `${s.slice(0, max)}…` : s;
}

function StatusBadge({ value }: { value: string }) {
  const cls =
    value === "SUCCESS"
      ? "bg-emerald-100 text-emerald-800"
      : value === "FAILED"
        ? "bg-red-100 text-red-800"
        : "bg-amber-100 text-amber-800";
  return (
    <span
      className={`inline-block rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide ${cls}`}
    >
      {value}
    </span>
  );
}
