import Link from "next/link";

import { db } from "@/db/client";
import { releaseSizeRules } from "@/db/schema";
import { sql } from "drizzle-orm";

import { saveSizeRulesAction } from "./actions";

export const dynamic = "force-dynamic";

// The runtimes the preview is drawn at. Deliberately not round numbers only:
// MB per minute is an abstract unit and nobody can judge it directly, but
// everyone knows what a half-hour episode and a two-hour film should weigh.
const PREVIEW_RUNTIMES = [
  { minutes: 22, label: "22 min", note: "half-hour episode" },
  { minutes: 45, label: "45 min", note: "drama episode" },
  { minutes: 110, label: "110 min", note: "typical film" },
  { minutes: 180, label: "180 min", note: "epic" },
];

const QUALITY_ORDER = ["sd", "720p", "1080p", "4k"] as const;

type Rule = {
  quality: string;
  min: number;
  max: number;
  atmosMax: number | null;
  timelessMax: number | null;
  observed: { n: number; p05: number; p50: number; p95: number } | null;
};

function gb(mbPerMinute: number, minutes: number) {
  return ((mbPerMinute * minutes) / 1024).toFixed(2);
}

export default async function AdminSizeRulesPage() {
  const rows = await db.select().from(releaseSizeRules);

  // What the library actually holds, alongside what the rules allow. A limit
  // set without the distribution in front of you is a guess, and the whole
  // point of these numbers is that they were measured rather than guessed.
  //
  // Probed files only, and only those with a real duration: filenames in this
  // library are wrong about quality on 47% of files, so an unprobed row cannot
  // say what a 1080p file weighs.
  const { rows: observed } = await db.execute<{
    quality: string;
    n: number;
    p05: number;
    p50: number;
    p95: number;
  }>(sql`
    select sf.quality::text as quality,
           count(*)::int as n,
           round(percentile_cont(0.05) within group (
             order by sf.size_bytes / 1048576.0 / (sf.duration_seconds / 60.0))::numeric, 1)::float8 as p05,
           round(percentile_cont(0.50) within group (
             order by sf.size_bytes / 1048576.0 / (sf.duration_seconds / 60.0))::numeric, 1)::float8 as p50,
           round(percentile_cont(0.95) within group (
             order by sf.size_bytes / 1048576.0 / (sf.duration_seconds / 60.0))::numeric, 1)::float8 as p95
      from storage_files sf
     where sf.missing_at is null
       and sf.probed_at is not null
       and sf.duration_seconds > 300
       and sf.size_bytes > 0
       and sf.quality is not null
     group by 1`);

  const observedByQuality = new Map(observed.map((row) => [row.quality, row]));

  const rules: Rule[] = QUALITY_ORDER.flatMap((quality) => {
    const row = rows.find((entry) => entry.quality === quality);
    if (!row) return [];
    const stat = observedByQuality.get(quality);
    return [{
      quality,
      min: Number(row.minMbPerMinute),
      max: Number(row.maxMbPerMinute),
      atmosMax: row.atmosMaxMbPerMinute === null ? null : Number(row.atmosMaxMbPerMinute),
      timelessMax: row.timelessMaxMbPerMinute === null ? null : Number(row.timelessMaxMbPerMinute),
      observed: stat ? { n: stat.n, p05: stat.p05, p50: stat.p50, p95: stat.p95 } : null,
    }];
  });

  return (
    <div className="space-y-6">
      <div className="flex flex-wrap items-end justify-between gap-4">
        <div>
          <p className="text-xs font-semibold uppercase tracking-[0.32em] text-admin-accent">Policy</p>
          <h1 className="mt-2 font-serif text-3xl font-semibold">Release size limits</h1>
          <p className="mt-2 max-w-3xl text-sm text-admin-muted">
            How large a release may be, per minute of runtime. Per minute because runtime is
            the great leveller: a three-hour film and a half-hour episode are not the same
            file and never were. These apply to what gets <em>downloaded</em> — nothing here
            filters or removes anything already in the library.
          </p>
        </div>
        <Link href="/admin/policy" className="admin-nav-button px-3 py-2 text-sm font-medium">
          Policy overview
        </Link>
      </div>

      <form action={saveSizeRulesAction} className="space-y-6">
        <div className="overflow-x-auto">
          <table className="w-full min-w-[52rem] border-collapse text-sm">
            <thead>
              <tr className="border-b border-admin-line text-left text-xs uppercase tracking-wider text-admin-muted">
                <th className="py-2 pr-4">Quality</th>
                <th className="py-2 pr-4 text-right">Min MB/min</th>
                <th className="py-2 pr-4 text-right">Max MB/min</th>
                <th className="py-2 pr-4 text-right">Atmos max</th>
                <th className="py-2 pr-4 text-right">Timeless max</th>
                <th className="py-2 pr-4">What the library holds</th>
              </tr>
            </thead>
            <tbody>
              {rules.map((rule) => (
                <tr key={rule.quality} className="border-b border-admin-line/50">
                  <td className="py-3 pr-4 font-medium uppercase">{rule.quality}</td>
                  <td className="py-3 pr-4 text-right">
                    <input
                      type="number" step="0.1" min="0.1" required
                      name={`${rule.quality}-min`} defaultValue={rule.min}
                      className="w-24 rounded border border-admin-line bg-transparent px-2 py-1 text-right font-mono"
                    />
                  </td>
                  <td className="py-3 pr-4 text-right">
                    <input
                      type="number" step="0.1" min="0.1" required
                      name={`${rule.quality}-max`} defaultValue={rule.max}
                      className="w-24 rounded border border-admin-line bg-transparent px-2 py-1 text-right font-mono"
                    />
                  </td>
                  <td className="py-3 pr-4 text-right">
                    <input
                      type="number" step="0.1" min="0.1"
                      name={`${rule.quality}-atmos`}
                      defaultValue={rule.atmosMax ?? ""}
                      placeholder="—"
                      className="w-24 rounded border border-admin-line bg-transparent px-2 py-1 text-right font-mono"
                    />
                  </td>
                  <td className="py-3 pr-4 text-right">
                    <input
                      type="number" step="0.1" min="0.1"
                      name={`${rule.quality}-timeless`}
                      defaultValue={rule.timelessMax ?? ""}
                      placeholder="—"
                      className="w-24 rounded border border-admin-line bg-transparent px-2 py-1 text-right font-mono"
                    />
                  </td>
                  <td className="py-3 pr-4 text-xs text-admin-muted">
                    {rule.observed ? (
                      <span className="font-mono">
                        n={rule.observed.n} · p05 {rule.observed.p05} · median {rule.observed.p50} · p95 {rule.observed.p95}
                      </span>
                    ) : (
                      <span className="font-mono">nothing probed</span>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        <p className="max-w-3xl text-xs text-admin-muted">
          The Atmos column is an <em>allowance</em>, not a second ceiling: leave it blank and
          the ordinary maximum applies whatever the release calls itself. Only 4K carries one,
          because that is where it was measured to matter — on 4K files, probed TrueHD runs
          about 1.8&times; E-AC-3 and 4&times; AAC per minute. It is read from the release
          title, which is trustworthy in a way our own filenames are not: an encoder advertises
          &ldquo;TrueHD 7.1 Atmos&rdquo; because it sells the release.
        </p>

        <p className="max-w-3xl text-xs text-admin-muted">
          The <strong>Timeless</strong> column is the only ceiling that admits a remux — the
          disc&rsquo;s own streams repackaged without re-encoding, three to four times the size
          of a good WEB-DL. It applies to nothing except titles marked timeless, and that is
          the point: as a global ceiling it would stop being an allowance for the films worth
          keeping losslessly and simply become the size everything arrives at. It outranks the
          Atmos allowance, since a lossless copy carries its object-based track anyway. There
          is no 720p remux — the format is a re-encode by definition — so leaving those blank
          is correct.
        </p>

        <button type="submit" className="admin-nav-button px-4 py-2 text-sm font-medium">
          Save limits
        </button>
      </form>

      <section className="space-y-3">
        <h2 className="font-serif text-xl font-semibold">What these allow</h2>
        <p className="max-w-3xl text-sm text-admin-muted">
          The same limits in gigabytes, which is the unit anyone can actually judge. Saved
          values only — edit and save to see this change.
        </p>
        <div className="overflow-x-auto">
          <table className="w-full min-w-[48rem] border-collapse text-sm">
            <thead>
              <tr className="border-b border-admin-line text-left text-xs uppercase tracking-wider text-admin-muted">
                <th className="py-2 pr-4">Runtime</th>
                {rules.map((rule) => (
                  <th key={rule.quality} className="py-2 pr-4 text-right uppercase">{rule.quality}</th>
                ))}
                <th className="py-2 pr-4 text-right">4K + Atmos</th>
                <th className="py-2 pr-4 text-right">4K timeless</th>
              </tr>
            </thead>
            <tbody>
              {PREVIEW_RUNTIMES.map((runtime) => {
                const fourK = rules.find((rule) => rule.quality === "4k");
                return (
                  <tr key={runtime.minutes} className="border-b border-admin-line/50">
                    <td className="py-3 pr-4">
                      <div>{runtime.label}</div>
                      <div className="text-xs text-admin-muted">{runtime.note}</div>
                    </td>
                    {rules.map((rule) => (
                      <td key={rule.quality} className="py-3 pr-4 text-right font-mono text-xs">
                        {gb(rule.min, runtime.minutes)}–{gb(rule.max, runtime.minutes)} GB
                      </td>
                    ))}
                    <td className="py-3 pr-4 text-right font-mono text-xs">
                      {fourK?.atmosMax
                        ? `${gb(fourK.min, runtime.minutes)}–${gb(fourK.atmosMax, runtime.minutes)} GB`
                        : "—"}
                    </td>
                    <td className="py-3 pr-4 text-right font-mono text-xs">
                      {fourK?.timelessMax
                        ? `${gb(fourK.min, runtime.minutes)}–${gb(fourK.timelessMax, runtime.minutes)} GB`
                        : "—"}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </section>
    </div>
  );
}
