"use client";

/**
 * Section7Concept — «7. Концепция» (epic #1953, unify-concept rewrite).
 *
 * ONE engine. The section folds the generative concept tooling into the LIGHT
 * analysis report after «6. Прогноз». A SINGLE source of numbers: POST /concepts
 * with a `building_program` set drives the placement map + ТЭП + финмодель
 * (ConceptVariantsResult). The old two-engine split (live 3D massing + a
 * separate params form / greedy run) is gone — it produced incoherent numbers
 * and a torn layout.
 *
 * «Число корпусов» maps directly to a single-type program item
 * `[{ section_type, floors, count }]`: the backend's `place_program` lays out
 * EXACTLY `count` footprints, so scatter is structurally impossible while the
 * «уплотнить» toggle is OFF. Toggle ON → building_program is omitted → greedy
 * max-FAR (the explicit, opt-in dense buildout).
 *
 * Inputs are seeded from the analysis the report already has (no re-entry):
 *   • parcel polygon  ← extractPolygon(analysis.geom_geojson)
 *   • housing_class   ← financial_estimate.housing_class_inferred
 *   • development_type← financial_estimate.development_type_inferred
 *   • land_cost_rub   ← egrn.cadastral_value_rub
 * Falls back to comfort / mid_rise when those are null.
 *
 * The section defaults to collapsed (above-the-fold rule). On first expand it
 * auto-runs once with the default program (count = 3) so the user lands on a
 * result, not an empty form.
 *
 * СЗЗ / financial_estimate === null is NOT a dead end: /concepts only needs a
 * polygon + form inputs (independent of the financial_estimate regulatory gate),
 * so we show an honest banner and STILL allow a run.
 */

import dynamic from "next/dynamic";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";

import { HeadlineBar } from "@/components/ui/HeadlineBar";
import { Section } from "@/components/analytics/Section";
import {
  ConceptProgramForm,
  type ConceptProgramFormState,
} from "@/components/concept/ConceptProgramForm";
import {
  extractPolygon,
  polygonAreaSqm,
  useCreateConcept,
  useHouseTypes,
  type BuildingProgramItem,
  type DevelopmentType,
  type HousingClass,
  type HouseTypeCatalogItem,
} from "@/lib/concept-api";
import type { ParcelAnalysis } from "@/types/site-finder";

// ConceptVariantsResult hosts a Leaflet placement map — lazy-mount, no SSR, so
// it never bloats the main report bundle (loaded only when results exist).
const ConceptVariantsResult = dynamic(
  () =>
    import("@/components/concept/ConceptVariantsResult").then(
      (m) => m.ConceptVariantsResult,
    ),
  {
    ssr: false,
    loading: () => (
      <div
        style={{
          height: 360,
          background: "var(--bg-card-alt)",
          border: "1px solid var(--border-card)",
          borderRadius: 12,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          color: "var(--fg-tertiary)",
          fontSize: 13,
        }}
      >
        Загрузка результата…
      </div>
    ),
  },
);

const SCROLL_MARGIN = 72;

// Fallback floors when neither the catalog nor a selection is available yet.
const FLOORS_FALLBACK = 9;
const CORPUSES_DEFAULT = 3;

// ── Narrowing helpers (inferred values are typed `string` on the analysis) ────

const HOUSING_CLASSES: readonly HousingClass[] = [
  "econom",
  "comfort",
  "business",
];
const DEVELOPMENT_TYPES: readonly DevelopmentType[] = [
  "spot",
  "mid_rise",
  "high_rise",
];

function asHousingClass(value: string | undefined): HousingClass | null {
  return value != null && (HOUSING_CLASSES as readonly string[]).includes(value)
    ? (value as HousingClass)
    : null;
}

function asDevelopmentType(value: string | undefined): DevelopmentType | null {
  return value != null &&
    (DEVELOPMENT_TYPES as readonly string[]).includes(value)
    ? (value as DevelopmentType)
    : null;
}

/** First comfort-class catalog type (else first entry, else null). */
function pickDefaultType(
  catalog: HouseTypeCatalogItem[],
): HouseTypeCatalogItem | null {
  if (catalog.length === 0) return null;
  return catalog.find((ht) => ht.housing_class === "comfort") ?? catalog[0];
}

// ── Props ─────────────────────────────────────────────────────────────────────

interface Props {
  /** The /analyze response the report already holds — no re-fetch / re-entry. */
  analysis: ParcelAnalysis;
}

// ── Section7Concept ───────────────────────────────────────────────────────────

export function Section7Concept({ analysis }: Props) {
  // Parcel polygon from the analysis geometry (handles Polygon / MultiPolygon /
  // null → null; MultiPolygon collapses to its first ring per extractPolygon).
  const polygon = useMemo(
    () => extractPolygon(analysis.geom_geojson),
    [analysis.geom_geojson],
  );

  // Seed defaults from the analysis: inferred class/type + cadastral value.
  // financial_estimate is null under the regulatory gate (СЗЗ / ЗОУИТ / нет
  // зоны) — fall back to comfort / mid_rise so a manual run is still possible.
  const fin = analysis.financial_estimate;
  const seeded = useMemo(
    () => ({
      housing_class: asHousingClass(fin?.housing_class_inferred) ?? "comfort",
      development_type:
        asDevelopmentType(fin?.development_type_inferred) ?? "mid_rise",
      land_cost_rub: analysis.egrn?.cadastral_value_rub ?? null,
    }),
    [
      fin?.housing_class_inferred,
      fin?.development_type_inferred,
      analysis.egrn?.cadastral_value_rub,
    ],
  );

  const concept = useCreateConcept();
  // Lift the catalog to the parent so auto-run-on-first-expand can build the
  // default program from the real catalog (single source of truth, no hardcode).
  const houseTypes = useHouseTypes();
  const catalog = useMemo(() => houseTypes.data ?? [], [houseTypes.data]);

  const financeUnavailable = fin == null;

  const parcelAreaSqm = polygon ? polygonAreaSqm(polygon) : 0;

  // Build a concept.mutate payload from a fully-resolved form state. «Число
  // корпусов» → a single-type program item's `count` (toggle OFF). Toggle ON →
  // building_program omitted → greedy max-FAR (explicit dense opt-in).
  const handleGenerate = useCallback(
    (state: ConceptProgramFormState) => {
      if (!polygon) return;
      const building_program: BuildingProgramItem[] | undefined = state.densify
        ? undefined
        : [
            {
              section_type: state.section_type,
              floors: state.floors,
              count: state.corpuses,
            },
          ];
      concept.mutate({
        parcel_geojson: polygon,
        housing_class: state.housing_class,
        // Backward-compat scalar; the program item carries the real floors.
        target_floors: state.floors,
        development_type: state.development_type,
        land_cost_rub: state.land_cost_rub,
        building_program,
      });
    },
    [polygon, concept],
  );

  // ── Auto-run-on-first-expand ──────────────────────────────────────────────
  // When the <details> is opened the FIRST time AND a polygon + catalog exist
  // AND there's no result yet AND nothing is in flight → fire one run with the
  // default program (count = 3, comfort-class section type). A ref guards a
  // single execution; if the catalog isn't ready at open the effect re-fires
  // when it becomes ready (still only once, still only after first open). The
  // <details onToggle> flips `expanded`, which (re)triggers the effect.
  const autoRanRef = useRef(false);
  const [expanded, setExpanded] = useState(false);

  useEffect(() => {
    if (autoRanRef.current || !expanded) return;
    if (!polygon || catalog.length === 0) return;
    if (concept.isPending || concept.isSuccess || concept.isError) return;
    const def = pickDefaultType(catalog);
    if (!def) return;
    autoRanRef.current = true;
    handleGenerate({
      corpuses: CORPUSES_DEFAULT,
      floors: def.default_floors > 0 ? def.default_floors : FLOORS_FALLBACK,
      floor_height_m: 3.0,
      section_type: def.section_type,
      housing_class: seeded.housing_class,
      development_type: seeded.development_type,
      land_cost_rub: seeded.land_cost_rub,
      densify: false,
    });
  }, [expanded, polygon, catalog, concept, seeded, handleGenerate]);

  const handleToggle = useCallback(
    (e: React.SyntheticEvent<HTMLDetailsElement>) => {
      if (e.currentTarget.open) setExpanded(true);
    },
    [],
  );

  return (
    <section id="section-7" style={{ scrollMarginTop: SCROLL_MARGIN }}>
      <HeadlineBar
        title="7. Концепция"
        subtitle="Единая программа застройки: задайте число корпусов, этажность и класс — движок разложит ровно эту программу и посчитает ТЭП и финмодель по геометрии участка."
      />

      {/* Collapsed by default (above-the-fold rule). Auto-runs once on first
          expand so the user lands on a result, not an empty form. */}
      <details style={{ marginTop: 12 }} onToggle={handleToggle}>
        <summary
          style={{
            cursor: "pointer",
            fontSize: 14,
            fontWeight: 600,
            color: "var(--fg-primary)",
            padding: "8px 0",
          }}
        >
          Параметры и расчёт концепции
        </summary>

        <div style={{ display: "grid", gap: 24 }}>
          {!polygon ? (
            <Section title="Концепция застройки">
              <p
                style={{
                  margin: 0,
                  fontSize: 13,
                  color: "var(--fg-secondary)",
                }}
              >
                Геометрия участка недоступна — концепцию построить нельзя.
                Геометрия загружается из НСПД; повторите анализ позже либо
                воспользуйтесь страницей «Концепция застройки», где границы
                можно задать вручную.
              </p>
            </Section>
          ) : (
            <>
              {/* СЗЗ / нет финмодели по регламенту — честный баннер, но НЕ
                  тупик: /concepts работает по полигону + параметрам формы
                  независимо от регуляторного гейта financial_estimate. */}
              {financeUnavailable && (
                <div
                  role="note"
                  style={{
                    padding: "12px 16px",
                    background: "var(--warn-soft)",
                    border: "1px solid var(--warn)",
                    borderRadius: 12,
                    fontSize: 13,
                    lineHeight: "20px",
                    color: "var(--fg-primary)",
                  }}
                >
                  Финмодель по регламенту недоступна — на участке ЗОУИТ / СЗЗ
                  либо не определена территориальная зона. Концепцию можно
                  рассчитать вручную: задайте число корпусов, класс, тип
                  застройки и этажность ниже — движок построит застройку по
                  геометрии участка и заданным параметрам.
                </div>
              )}

              <ConceptProgramForm
                parcelAreaSqm={parcelAreaSqm}
                seeded={seeded}
                hasPolygon={polygon != null}
                isPending={concept.isPending}
                onSubmit={handleGenerate}
              />

              {/* Result region */}
              {concept.isError && (
                <Section title="Варианты застройки">
                  <p
                    style={{ margin: 0, fontSize: 13, color: "var(--danger)" }}
                    role="alert"
                  >
                    Не удалось рассчитать концепцию: {concept.error.message}
                  </p>
                </Section>
              )}

              {concept.isPending && (
                <div
                  style={{
                    minHeight: 700,
                    background: "var(--bg-card-alt)",
                    border: "1px solid var(--border-card)",
                    borderRadius: 12,
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                    color: "var(--fg-secondary)",
                    fontSize: 14,
                  }}
                >
                  Движок раскладывает корпуса и считает ТЭП и финмодель…
                </div>
              )}

              {concept.isSuccess && (
                <ConceptVariantsResult
                  parcel={polygon}
                  variants={concept.data.variants}
                />
              )}
            </>
          )}
        </div>
      </details>
    </section>
  );
}
