import Image from "next/image";
import {
  loadBaselineMetrics,
  getScenarioConfig,
  getPortfolioGoal,
  type ScenarioConfig,
} from "@/app/portfolio/[slug]/(portfolio)/reporting/databaseFunctions";
import { measureLabel } from "@/lib/reporting/measures";
import {
  buildHeadline,
  carsOffTheRoad,
  countBelowBand,
  shapeKpiDelta,
  toBandCounts,
} from "@/lib/reporting/model";
import { sapToEpc, formatNumber, getEpcColorClass } from "@/app/utils";
import { EPC_BANDS } from "@/lib/epc/bands";
import {
  parseReportingViewState,
  serializeReportingViewState,
  isTagFilterActive,
  type ReportingViewState,
} from "@/lib/reporting/viewState";
import { EpcChip } from "../components/primitives";
import {
  InvestmentLedger,
  type LedgerView,
} from "../components/InvestmentLedger";
import { getPortfolio } from "@/app/portfolio/[slug]/utils";
import type { BaselineMetrics } from "../types";
import { AutoPrint } from "./AutoPrint";

/**
 * The report PDF (PRD #370) — the print register of the reporting screen.
 * Rebuilt on the same model functions, primitives and (restyled) Investment
 * ledger as the screen, so the pack and the tool tell one story. Reflects the
 * on-screen view state exactly: the selected view (current stock / recommended
 * / a scenario) plus the active tag + scenario filters, all carried in the URL.
 *
 * Print-safe by construction: the content is div/span only (globals.css hides
 * every <button> in print), and background colours are forced to print via the
 * print-color-adjust rule on .print-root.
 */

function getBaseUrl() {
  if (process.env.VERCEL_BRANCH_URL)
    return `https://${process.env.VERCEL_BRANCH_URL}`;
  if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`;
  // Local dev: the server may be on any port (not always 3000).
  return `http://localhost:${process.env.PORT ?? 3000}`;
}

/** Fetch the scenario/recommended overlay, carrying the view's filters + tags. */
async function fetchScenarioReport(
  portfolioId: number,
  segment: number | "default",
  state: ReportingViewState,
) {
  const qs = serializeReportingViewState(state).toString();
  const res = await fetch(
    `${getBaseUrl()}/api/portfolio/${portfolioId}/scenario/${segment}/metrics${qs ? `?${qs}` : ""}`,
    { cache: "no-store" },
  );
  if (!res.ok) throw new Error("Failed to load scenario report");
  return res.json();
}

function money(n: number): string {
  const sign = n < 0 ? "−" : "";
  return `${sign}£${Math.abs(Math.round(n)).toLocaleString("en-GB")}`;
}

const generatedOn = () =>
  new Date().toLocaleDateString("en-GB", {
    day: "numeric",
    month: "short",
    year: "numeric",
  });

// ── Shared presentational pieces (print-safe: no <button>) ──────────────────

function Cover({ title, subtitle }: { title: string; subtitle: string }) {
  return (
    <header className="flex items-center gap-3 border-b-2 border-[#14163d] pb-3">
      <Image
        src="/domna_logo_blue_transparent_background.png"
        alt="Domna"
        width={124}
        height={36}
      />
      <div className="ml-1 border-l border-gray-300 pl-3">
        <div className="text-[0.7rem] font-bold uppercase tracking-wide text-[#a07c42]">
          Retrofit report
        </div>
        <div className="text-[1.05rem] font-semibold leading-tight text-[#14163d]">
          {title}
        </div>
      </div>
      <div className="ml-auto text-right text-[0.72rem] text-gray-500">
        <div className="font-medium text-gray-700">{subtitle}</div>
        <div>Generated {generatedOn()}</div>
      </div>
    </header>
  );
}

function FilterNote({ state }: { state: ReportingViewState }) {
  const parts: string[] = [];
  const nTags = state.tags.include.length + state.tags.exclude.length;
  if (isTagFilterActive(state.tags))
    parts.push(`${nTags} tag filter${nTags > 1 ? "s" : ""}`);
  if (state.hideNonCompliant) parts.push("only homes that reach target");
  if (state.useLodgedBaseline) parts.push("judged by lodged EPC");
  if (state.complianceWindow)
    parts.push(`skipping homes compliant past ${state.complianceWindow.date}`);
  if (!parts.length) return null;
  return (
    <div className="inline-flex items-center gap-2 rounded-md bg-[#f2f3f9] px-3 py-1.5 text-[0.72rem] text-[#14163d]">
      <span className="font-semibold text-[#a07c42]">Filtered view</span>
      <span className="text-gray-600">{parts.join(" · ")}</span>
    </div>
  );
}

function Tile({
  label,
  value,
  sub,
}: {
  label: string;
  value: React.ReactNode;
  sub?: React.ReactNode;
}) {
  return (
    <div className="rounded-lg border border-gray-200 px-3.5 py-3">
      <div className="text-[0.62rem] font-bold uppercase tracking-wide text-gray-500">
        {label}
      </div>
      <div className="mt-1 flex items-baseline gap-1.5 text-[1.15rem] font-semibold leading-none tabular-nums text-[#14163d]">
        {value}
      </div>
      {sub && (
        <div className="mt-1 text-[0.66rem] tabular-nums text-gray-500">
          {sub}
        </div>
      )}
    </div>
  );
}

function Delta({ text, improved }: { text: string; improved: boolean }) {
  return (
    <span
      className={`ml-0.5 rounded-[4px] px-1 py-0.5 text-[0.6rem] font-bold ${
        improved ? "bg-[#e9f4ef] text-[#0c6b4a]" : "bg-[#fbeaea] text-[#b91c1c]"
      }`}
    >
      {text}
    </span>
  );
}

/** EPC distribution as div bars (EpcLadder is button-based → hidden in print). */
function EpcDistribution({
  bandCounts,
  scenarioBands,
}: {
  bandCounts: Record<string, number>;
  scenarioBands?: Record<string, number>;
}) {
  const bands = EPC_BANDS.filter(
    (b) => (bandCounts[b] ?? 0) > 0 || (scenarioBands?.[b] ?? 0) > 0,
  );
  const max = Math.max(
    1,
    ...bands.map((b) => Math.max(bandCounts[b] ?? 0, scenarioBands?.[b] ?? 0)),
  );
  return (
    <div className="flex flex-col gap-2">
      {bands.map((band) => {
        const before = bandCounts[band] ?? 0;
        const after = scenarioBands?.[band];
        return (
          <div
            key={band}
            className="grid grid-cols-[24px_1fr_96px] items-center gap-x-3"
          >
            <EpcChip band={band} size="sm" />
            <span className="flex flex-col gap-[3px]">
              <span
                className={`h-[15px] rounded-sm ${getEpcColorClass(band)}`}
                style={{ width: `${Math.max((before / max) * 100, 0.5)}%` }}
              />
              {after !== undefined && (
                <span
                  className="h-[7px] rounded-sm bg-[#14163d]"
                  style={{ width: `${Math.max((after / max) * 100, 0.5)}%` }}
                />
              )}
            </span>
            <span className="text-right text-[0.72rem] tabular-nums text-gray-600">
              {after !== undefined ? (
                <>
                  {before} → <b className="text-gray-900">{after}</b>
                </>
              ) : (
                <b className="text-gray-900">{before}</b>
              )}
            </span>
          </div>
        );
      })}
      <p className="mt-1 text-[0.68rem] text-gray-500">
        {scenarioBands
          ? "Bar = current stock (band colour); line beneath = after scenario (navy)."
          : "Homes by current effective EPC band."}
      </p>
    </div>
  );
}

function SectionTitle({ children }: { children: React.ReactNode }) {
  return (
    <h2 className="mb-3 text-[0.82rem] font-semibold text-[#14163d]">
      {children}
    </h2>
  );
}

function goalPhrase(goal: string, goalValue: string | null): string {
  if (goal === "Increasing EPC") return `Reach EPC ${goalValue ?? "target"}`;
  if (goal === "Reducing CO2 emissions") return "Reduce CO₂ emissions";
  if (goal === "Energy Savings") return "Cut energy use";
  if (goal === "Valuation Improvement") return "Improve valuation";
  return goal;
}

function BriefRow({ label, value }: { label: string; value: React.ReactNode }) {
  return (
    <div className="flex items-baseline justify-between gap-4 border-t border-gray-100 py-1 text-[0.76rem] first:border-t-0">
      <span className="flex-none text-gray-500">{label}</span>
      <span className="text-right font-medium text-[#14163d]">{value}</span>
    </div>
  );
}

/**
 * Plain-language brief of the scenario's (immutable) configuration — the
 * question it answers and the constraints it was modelled under. Fills the
 * left column beneath the EPC distribution.
 */
function ScenarioBrief({ config }: { config: ScenarioConfig }) {
  const stock =
    config.housingType?.toLowerCase() === "social"
      ? "social homes"
      : config.housingType?.toLowerCase() === "private"
        ? "private homes"
        : "homes";
  const excluded = config.exclusions.length
    ? config.exclusions.map(measureLabel).join(", ")
    : "None — every measure available";
  const budget =
    config.budget != null
      ? `£${config.budget.toLocaleString("en-GB")} per home`
      : "No cap";
  // Lowercase the leading verb for mid-sentence use, keeping EPC/CO₂ caps.
  const gp = goalPhrase(config.goal, config.goalValue);
  const goalLead = gp.charAt(0).toLowerCase() + gp.slice(1);

  return (
    <section className="avoid-break rounded-lg border border-gray-200 p-4">
      <h2 className="mb-2 text-[0.82rem] font-semibold text-[#14163d]">
        About this scenario
      </h2>
      <p className="mb-2 text-[0.78rem] leading-relaxed text-gray-600">
        This scenario asks what it takes to {goalLead} across the
        portfolio&apos;s {stock}, and models the works and costs to get there.
      </p>
      <div>
        <BriefRow
          label="Goal"
          value={goalPhrase(config.goal, config.goalValue)}
        />
        <BriefRow label="Stock" value={config.housingType} />
        <BriefRow label="Budget" value={budget} />
        <BriefRow
          label="Fabric-first"
          value={config.fabricFirst ? "Enabled" : "Off"}
        />
        <BriefRow label="Excluded measures" value={excluded} />
      </div>
    </section>
  );
}

function RecommendedBrief() {
  return (
    <section className="avoid-break rounded-lg border border-gray-200 p-4">
      <h2 className="mb-2 text-[0.82rem] font-semibold text-[#14163d]">
        About recommended plans
      </h2>
      <p className="text-[0.78rem] leading-relaxed text-gray-600">
        Recommended plans take the engine&apos;s best plan for each home — the
        most cost-effective route to the biggest improvement — rather than one
        portfolio-wide target. The figures aggregate those per-home plans.
      </p>
    </section>
  );
}

function Footer() {
  return (
    <footer className="mt-2 border-t border-gray-200 pt-3 text-[0.64rem] leading-relaxed text-gray-400">
      Domna · Retrofit report · Generated {generatedOn()}. Figures are modelled
      estimates; gross cost = construction works + project delivery +
      contingency, net = gross − secured funding. Excludes VAT and internal
      staff time. Commercial-in-confidence.
    </footer>
  );
}

// ── Page ────────────────────────────────────────────────────────────────────

export default async function ReportingPdfPage(props: {
  params: Promise<{ slug: string }>;
  searchParams: Promise<Record<string, string | string[] | undefined>>;
}) {
  const { slug } = await props.params;
  const state = parseReportingViewState(await props.searchParams);
  const portfolioId = Number(slug);
  const { view, tags } = state;

  const segment: number | "default" | null =
    view === "current-stock" ? null : view === "recommended" ? "default" : view;

  const [baseline, portfolio]: [BaselineMetrics, { name: string }] =
    await Promise.all([
      loadBaselineMetrics(portfolioId, tags),
      getPortfolio(slug),
    ]);
  const portfolioName = portfolio.name;
  const bandCounts = toBandCounts(baseline.epcBands);
  const avg = baseline.averages;
  const total = baseline.total;

  // ── Current stock (no scenario overlay, no ledger) ──────────────────────
  if (segment === null) {
    const belowC = countBelowBand(bandCounts, "C");
    return (
      <div className="print-page mx-auto max-w-[190mm] bg-white">
        <div className="print-root space-y-3 p-8 text-[#14163d] print:p-0">
          <AutoPrint />
          <Cover title="Current stock" subtitle={portfolioName} />

          <p className="max-w-[62ch] text-[1.02rem] font-medium leading-relaxed">
            {total.toLocaleString()} homes at an average EPC of{" "}
            {sapToEpc(avg.avg_sap ?? 0)} ({Math.round(avg.avg_sap ?? 0)} SAP).{" "}
            {belowC.toLocaleString()} sit below EPC C.
          </p>
          <FilterNote state={state} />

          <div className="print-grid-3 grid grid-cols-3 gap-3">
            <Tile
              label="Homes"
              value={total.toLocaleString()}
              sub={`${belowC.toLocaleString()} below EPC C`}
            />
            <Tile
              label="Average EPC"
              value={
                <span className="flex items-center gap-1.5">
                  <EpcChip band={sapToEpc(avg.avg_sap ?? 0)} size="sm" />
                  {Math.round(avg.avg_sap ?? 0)}
                  <span className="text-[0.62rem] font-medium text-gray-500">
                    SAP
                  </span>
                </span>
              }
            />
            <Tile
              label="Energy bills"
              value={`£${formatNumber(avg.avg_bills ?? 0)}`}
              sub="per home / year"
            />
            <Tile
              label="Carbon"
              value={`${formatNumber(avg.avg_carbon ?? 0)}`}
              sub="tCO₂e per home / year"
            />
            <Tile
              label="Energy use"
              value={`${formatNumber(avg.avg_energy_consumption ?? 0)}`}
              sub="kWh per home / year"
            />
            <Tile
              label="Portfolio bills"
              value={money(baseline.totals.total_bills ?? 0)}
              sub="per year across the portfolio"
            />
          </div>

          <section className="avoid-break">
            <SectionTitle>EPC distribution — current stock</SectionTitle>
            <EpcDistribution bandCounts={bandCounts} />
          </section>

          <Footer />
        </div>
      </div>
    );
  }

  // ── Scenario / recommended ──────────────────────────────────────────────
  const [scenarioData, config, portfolioGoal] = await Promise.all([
    fetchScenarioReport(portfolioId, segment, state),
    typeof segment === "number"
      ? getScenarioConfig(segment)
      : Promise.resolve(null),
    getPortfolioGoal(portfolioId),
  ]);

  const goal = config?.goal ?? portfolioGoal;
  const title =
    segment === "default"
      ? "Recommended plans"
      : (config?.name ?? `Scenario ${segment}`);

  const carbonSaved =
    (baseline.totals.total_carbon ?? 0) - Number(scenarioData.total_carbon);
  const billSaved =
    (baseline.totals.total_bills ?? 0) - Number(scenarioData.total_bills);
  const n = scenarioData.n_units_upgraded || 1;
  const capital = scenarioData.construction_cost + scenarioData.pc_cost;

  const ledger: LedgerView = {
    constructionCost: scenarioData.construction_cost,
    projectDelivery: scenarioData.pc_cost,
    contingency: scenarioData.contingency,
    funding: scenarioData.total_funding,
    grossCost: scenarioData.gross_cost,
    netCost: scenarioData.net_cost,
    grossPerHome: scenarioData.gross_per_unit,
    billSavings: billSaved,
    billSavingsPerHome: billSaved / n,
    carbonSaved,
    costPerSap:
      scenarioData.total_sap_uplift > 0
        ? capital / scenarioData.total_sap_uplift
        : 0,
    costPerCarbon: carbonSaved > 0 ? capital / carbonSaved : 0,
  };

  const headline = buildHeadline({
    goal,
    goalValue: config?.goalValue ?? null,
    homesUpgraded: scenarioData.n_units_upgraded,
    netCost: scenarioData.net_cost,
    carbonSavedPerYear: carbonSaved,
  });

  const scenarioBands: Record<string, number> =
    scenarioData.scenario_epc_counts;
  const belowCBefore = countBelowBand(bandCounts, "C");
  const belowCAfter = countBelowBand(scenarioBands, "C");

  const sapDelta = shapeKpiDelta({
    current: avg.avg_sap ?? 0,
    after: Number(scenarioData.avg_sap),
    improvesWhenLower: false,
  });

  return (
    <div className="print-page mx-auto max-w-[190mm] bg-white">
      <div className="print-root space-y-3 p-8 text-[#14163d] print:p-0">
        <AutoPrint />
        <Cover title={title} subtitle={portfolioName} />

        <p className="max-w-[62ch] text-[1.02rem] font-medium leading-relaxed">
          {headline}
        </p>
        <FilterNote state={state} />

        <div className="print-grid-3 grid grid-cols-3 gap-3">
          <Tile
            label="Homes upgraded"
            value={scenarioData.n_units_upgraded.toLocaleString()}
            sub={`of ${total.toLocaleString()} homes`}
          />
          <Tile
            label="Average EPC"
            value={
              <span className="flex items-center gap-1">
                <EpcChip band={sapToEpc(avg.avg_sap ?? 0)} size="sm" />→
                <EpcChip
                  band={sapToEpc(Number(scenarioData.avg_sap))}
                  size="sm"
                />
                <Delta
                  text={`${sapDelta.delta > 0 ? "+" : ""}${sapDelta.delta.toFixed(0)}`}
                  improved={sapDelta.improved}
                />
              </span>
            }
            sub={`${Math.round(avg.avg_sap ?? 0)} → ${Math.round(Number(scenarioData.avg_sap))} SAP`}
          />
          <Tile
            label="Homes below EPC C"
            value={
              <span>
                {belowCBefore.toLocaleString()} →{" "}
                <b>{belowCAfter.toLocaleString()}</b>
              </span>
            }
            sub={`≈ ${carsOffTheRoad(carbonSaved)} cars off the road`}
          />
          <Tile
            label="Bills saved / yr"
            value={money(billSaved)}
            sub={`${money(billSaved / n)} per home`}
          />
          <Tile
            label="Carbon saved / yr"
            value={`${formatNumber(carbonSaved)} t`}
            sub="vs current stock"
          />
          <Tile
            label="Net cost"
            value={money(scenarioData.net_cost)}
            sub={`${money(scenarioData.gross_per_unit)} gross / home`}
          />
        </div>

        <div className="grid grid-cols-[1.1fr_1fr] items-start gap-4">
          <div className="space-y-4">
            <section className="avoid-break">
              <SectionTitle>
                EPC distribution — current vs scenario
              </SectionTitle>
              <EpcDistribution
                bandCounts={bandCounts}
                scenarioBands={scenarioBands}
              />
            </section>
            {config ? (
              <ScenarioBrief config={config} />
            ) : segment === "default" ? (
              <RecommendedBrief />
            ) : null}
          </div>

          <section className="avoid-break">
            <SectionTitle>Investment ledger</SectionTitle>
            <InvestmentLedger v={ledger} />
          </section>
        </div>

        <Footer />
      </div>
    </div>
  );
}
