"use client";

import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import {
  groupMeasures,
  measureLabel,
  type Measure,
  type MeasureGroup,
} from "@/lib/reporting/measures";
import { InfoDot, moneyCompact, moneyFull } from "./primitives";
import { COST_HELP } from "./costHelp";
import { loadScenarioMeasures } from "../actions";
import type { DrillTarget } from "./DrillDownShelf";
import type { TagFilter } from "@/lib/reporting/viewState";

/** Palette for the allocation bar — navy through tan, quiet greys for the tail. */
const SEGMENT_COLORS = [
  "#14163d",
  "#3943b7",
  "#7a81dd",
  "#a07c42",
  "#c9bd9b",
  "#c5cad8",
];

/**
 * "Where the money goes" (Screen B lower). A single allocation bar by
 * measure category answers the shape of the spend; the full grouped table
 * expands inline (no modal) and each measure drills to its homes via the
 * shared shelf.
 */
export function MeasureAllocation({
  portfolioId,
  scenarioId,
  tags,
  onDrillMeasure,
}: {
  portfolioId: number;
  scenarioId: number | "default";
  tags: TagFilter;
  /** Undefined disables per-measure drill (e.g. the default pseudo-scenario has no numeric id). */
  onDrillMeasure?: (t: DrillTarget) => void;
}) {
  const [expanded, setExpanded] = useState(false);
  // Load on demand. The measure breakdown is a heavy aggregate on large
  // portfolios; auto-firing it on every page load let slow/killed queries
  // pile up and saturate the DB, taking the whole reporting page down. The
  // user opts in, so a slow breakdown can never knock over the page.
  const [requested, setRequested] = useState(false);

  const { data, isLoading, isError, refetch } = useQuery<Measure[]>({
    // `tags` in the key so the breakdown re-queries when the tag filter changes.
    queryKey: ["scenario-measures", portfolioId, scenarioId, tags],
    queryFn: () => loadScenarioMeasures(portfolioId, scenarioId, tags),
    enabled: requested,
    refetchOnWindowFocus: false,
    retry: false,
    // Measures for a scenario don't change within a session — keep them
    // cached so switching scenarios and back is instant, not a re-query.
    staleTime: 5 * 60 * 1000,
    cacheTime: 30 * 60 * 1000,
  });

  const groups: MeasureGroup[] = data ? groupMeasures(data) : [];
  const grandTotal = groups.reduce((s, g) => s + g.costTotal, 0);
  const installations = groups.reduce(
    (s, g) => s + g.rows.reduce((n, r) => n + r.homesCount, 0),
    0,
  );

  const drillHref = onDrillMeasure
    ? (t: DrillTarget) => () => onDrillMeasure(t)
    : undefined;

  return (
    <section className="overflow-hidden rounded-lg border border-gray-200 bg-white">
      <header className="flex items-baseline justify-between gap-3 px-5 pt-4">
        <h3 className="text-[0.88rem] font-semibold text-brandblue">
          Where the money goes
          {installations > 0 && (
            <span className="ml-2 text-[0.74rem] font-normal text-gray-600">
              {installations} installations
            </span>
          )}
        </h3>
        {data && (
          <button
            onClick={() => setExpanded((e) => !e)}
            className="text-[0.76rem] font-semibold text-midblue"
          >
            {expanded ? "Hide measures" : "All measures & CSV →"}
          </button>
        )}
      </header>

      <div className="px-5 pb-5 pt-4">
        {!requested && (
          <div className="flex flex-col items-start gap-2">
            <button
              onClick={() => setRequested(true)}
              className="inline-flex h-8 items-center rounded-lg border border-brandblue bg-brandblue px-3.5 text-[0.8rem] font-medium text-white"
            >
              Show spend breakdown
            </button>
            <p className="text-[0.74rem] text-gray-600">
              The measure-by-measure breakdown is a heavier query on large
              portfolios, so it loads on request.
            </p>
          </div>
        )}

        {requested && isLoading && (
          <div className="animate-pulse" aria-label="Loading measures">
            <div className="h-[22px] w-full rounded bg-gray-100" />
            <div className="mt-3.5 grid grid-cols-1 gap-x-6 gap-y-2 sm:grid-cols-2 lg:grid-cols-3">
              {Array.from({ length: 6 }).map((_, i) => (
                <div key={i} className="flex items-center gap-2">
                  <span className="h-2.5 w-2.5 flex-none rounded-sm bg-gray-200" />
                  <span className="h-3 w-32 rounded bg-gray-100" />
                </div>
              ))}
            </div>
          </div>
        )}
        {requested && isError && (
          <div
            role="alert"
            className="flex items-center gap-3 text-sm text-red-600"
          >
            Could not load the spend breakdown.
            <button
              onClick={() => refetch()}
              className="rounded-md border border-gray-200 px-2.5 py-1 text-[0.78rem] font-medium text-gray-700"
            >
              Retry
            </button>
          </div>
        )}

        {data && groups.length > 0 && (
          <>
            <div className="flex h-[22px] overflow-hidden rounded">
              {groups.map((g, i) => (
                <span
                  key={g.category}
                  title={`${g.category} · ${moneyCompact(g.costTotal)}`}
                  style={{
                    width: `${(g.costTotal / grandTotal) * 100}%`,
                    background: SEGMENT_COLORS[i % SEGMENT_COLORS.length],
                  }}
                />
              ))}
            </div>
            <div className="mt-3.5 grid grid-cols-1 gap-x-6 gap-y-2 sm:grid-cols-2 lg:grid-cols-3">
              {groups.map((g, i) => (
                <span
                  key={g.category}
                  className="flex items-center gap-2 text-[0.78rem] text-gray-500"
                >
                  <span
                    className="h-2.5 w-2.5 flex-none rounded-sm"
                    style={{
                      background: SEGMENT_COLORS[i % SEGMENT_COLORS.length],
                    }}
                  />
                  {g.category}{" "}
                  <b className="font-semibold text-gray-900">
                    {moneyCompact(g.costTotal)}
                  </b>{" "}
                  · {g.homesTotal} homes
                </span>
              ))}
            </div>
            <p className="mt-3 flex items-center gap-1 text-[0.72rem] text-gray-500">
              Construction works only — excludes project delivery and
              contingency.
              <InfoDot
                label="Where the money goes"
                tip={COST_HELP.whereMoneyGoes}
              />
            </p>
          </>
        )}

        {data && groups.length === 0 && (
          <p className="text-sm text-gray-600">
            No measures in this scenario yet.
          </p>
        )}
      </div>

      {expanded && data && (
        <div className="border-t border-gray-100">
          <div className="flex items-center justify-between px-5 py-2.5">
            <span className="text-[0.74rem] text-gray-600">
              {data.length} measure types
            </span>
            <button
              onClick={() => downloadCsv(groups)}
              className="rounded-md border border-gray-200 px-3 py-1.5 text-[0.78rem] font-medium"
            >
              Download CSV
            </button>
          </div>
          <div className="overflow-x-auto">
            <table className="w-full text-[0.82rem]">
              <thead>
                <tr className="text-[0.68rem] uppercase tracking-wide text-gray-600">
                  <th className="px-5 py-2 text-left font-bold">Measure</th>
                  <th className="px-5 py-2 text-right font-bold">Homes</th>
                  <th className="px-5 py-2 text-right font-bold">Total</th>
                  <th className="px-5 py-2 text-right font-bold">Avg</th>
                  <th className="px-5 py-2" />
                </tr>
              </thead>
              <tbody>
                {groups.map((g) => (
                  <MeasureGroupRows
                    key={g.category}
                    group={g}
                    onDrill={drillHref}
                  />
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </section>
  );
}

function MeasureGroupRows({
  group,
  onDrill,
}: {
  group: MeasureGroup;
  onDrill?: (t: DrillTarget) => () => void;
}) {
  return (
    <>
      <tr>
        <td
          colSpan={5}
          className="bg-gray-50 px-5 py-2 text-[0.74rem] font-semibold text-brandblue"
        >
          {group.category} · {group.homesTotal} homes ·{" "}
          {moneyFull(group.costTotal)}
        </td>
      </tr>
      {group.rows.map((r) => (
        <tr key={r.measureType} className="border-t border-gray-100">
          <td className="px-5 py-2">{measureLabel(r.measureType)}</td>
          <td className="px-5 py-2 text-right tabular-nums">{r.homesCount}</td>
          <td className="px-5 py-2 text-right tabular-nums">
            {moneyFull(r.totalCost)}
          </td>
          <td className="px-5 py-2 text-right tabular-nums text-gray-500">
            {moneyFull(r.averageCost)}
          </td>
          <td className="px-5 py-2 text-right">
            {onDrill && (
              <button
                onClick={onDrill({
                  filter: "measure",
                  measureType: r.measureType,
                  title: measureLabel(r.measureType),
                })}
                className="whitespace-nowrap font-semibold text-midblue"
              >
                Homes →
              </button>
            )}
          </td>
        </tr>
      ))}
    </>
  );
}

function downloadCsv(groups: MeasureGroup[]) {
  const lines = ["Category,Measure,Homes,Total cost (£),Average cost (£)"];
  for (const g of groups) {
    for (const r of g.rows) {
      lines.push(
        [
          g.category,
          measureLabel(r.measureType),
          r.homesCount,
          r.totalCost.toFixed(0),
          r.averageCost.toFixed(0),
        ].join(","),
      );
    }
    lines.push(
      [g.category, "Subtotal", g.homesTotal, g.costTotal.toFixed(0), ""].join(
        ",",
      ),
    );
  }
  const blob = new Blob([lines.join("\n")], {
    type: "text/csv;charset=utf-8;",
  });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = "scenario-measures.csv";
  a.click();
  URL.revokeObjectURL(url);
}
