"use client";

import { useState } from "react";
import { Button } from "@/components/ui/button";
import { updateScenarioInputs, type ScenarioInputPayload, type CostItem } from "@/lib/api";

// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------

type Raw = Record<string, unknown>;

// Location config with expected CUF
const LOCATION_CUF: Record<string, number> = {
  RJ: 27.5,  // Rajasthan - high irradiance
  GJ: 26.0,  // Gujarat
  KA: 24.5,  // Karnataka
  AP: 25.0,  // Andhra Pradesh
  TN: 24.0,  // Tamil Nadu
  MP: 25.5,  // Madhya Pradesh
  MH: 24.0,  // Maharashtra
  HR: 23.5,  // Haryana
};

const LOCATIONS = [
  { value: "RJ", label: "Rajasthan" },
  { value: "GJ", label: "Gujarat" },
  { value: "KA", label: "Karnataka" },
  { value: "AP", label: "Andhra Pradesh" },
  { value: "TN", label: "Tamil Nadu" },
  { value: "MP", label: "Madhya Pradesh" },
  { value: "MH", label: "Maharashtra" },
  { value: "HR", label: "Haryana" },
  { value: "custom", label: "📤 Upload Custom Profile" },
];

const INDIAN_STATES = [
  { value: "RJ", label: "Rajasthan" },
  { value: "GJ", label: "Gujarat" },
  { value: "KA", label: "Karnataka" },
  { value: "AP", label: "Andhra Pradesh" },
  { value: "TN", label: "Tamil Nadu" },
  { value: "MP", label: "Madhya Pradesh" },
  { value: "MH", label: "Maharashtra" },
  { value: "HR", label: "Haryana" },
  { value: "UP", label: "Uttar Pradesh" },
  { value: "PB", label: "Punjab" },
  { value: "TS", label: "Telangana" },
  { value: "OR", label: "Odisha" },
];

const DEBT_SHAPES = [
  { value: "equal_principal", label: "Equal Principal" },
  { value: "equal_installment", label: "Equal Installment (EMI)" },
  { value: "dscr_sculpted", label: "DSCR Sculpted" },
  { value: "balloon", label: "Balloon" },
];

// Default cost items for each technology
const SOLAR_DEFAULT_ITEMS: CostItem[] = [
  { id: "solar_module", name: "Solar PV Module", category: "HardCost", basis: "PER_WP_DC", value: 18.0, depr_class: "Plant", attribution: "SolarOnly", phasing_id: "default" },
  { id: "solar_inverter", name: "Inverter", category: "HardCost", basis: "PER_WP_DC", value: 4.0, depr_class: "Plant", attribution: "SolarOnly", phasing_id: "default" },
  { id: "solar_dc_bos", name: "DC BOS (cables, mounting, earthing)", category: "HardCost", basis: "PER_WP_DC", value: 3.5, depr_class: "Plant", attribution: "SolarOnly", phasing_id: "default" },
  { id: "solar_ac_bos", name: "AC BOS (transformer, switchgear)", category: "HardCost", basis: "PER_WP_DC", value: 2.5, depr_class: "Plant", attribution: "SolarOnly", phasing_id: "default" },
  { id: "solar_land", name: "Land (per MW)", category: "HardCost", basis: "PER_WP_DC", value: 2.0, depr_class: "Land_NoDepr", attribution: "SolarOnly", phasing_id: "default" },
  { id: "solar_land_upfront", name: "Land Lease (upfront 5yr)", category: "HardCost", basis: "PER_ACRE", value: 30, depr_class: "LandLease_Amortized", attribution: "SolarOnly", phasing_id: "default" },
  { id: "solar_hr", name: "HR & Admin (pre-COD)", category: "SoftCost", basis: "PER_WP_DC", value: 0.5, depr_class: "Intangible", attribution: "SolarOnly", phasing_id: "default" },
  { id: "solar_epc_oh", name: "EPC Overhead", category: "EPCOverhead", basis: "PCT_OF_HARDCOST", value: 0.03, depr_class: "Plant", attribution: "SolarOnly", phasing_id: "default" },
  { id: "solar_contingency", name: "Contingency", category: "Contingency", basis: "PCT_OF_HARDCOST", value: 0.02, depr_class: "Plant", attribution: "SolarOnly", phasing_id: "default" },
];

const WIND_DEFAULT_ITEMS: CostItem[] = [
  { id: "wind_wtg", name: "WTG Supply", category: "HardCost", basis: "PER_MW_WIND", value: 5.50, depr_class: "Plant", attribution: "WindOnly", phasing_id: "default" },
  { id: "wind_tower", name: "Tower", category: "HardCost", basis: "PER_MW_WIND", value: 1.20, depr_class: "Plant", attribution: "WindOnly", phasing_id: "default" },
  { id: "wind_bop", name: "Balance of Plant", category: "HardCost", basis: "PER_MW_WIND", value: 0.80, depr_class: "Plant", attribution: "WindOnly", phasing_id: "default" },
  { id: "wind_land", name: "Land (per MW)", category: "HardCost", basis: "PER_MW_WIND", value: 0.30, depr_class: "Land_NoDepr", attribution: "WindOnly", phasing_id: "default" },
  { id: "wind_land_upfront", name: "Land Lease (upfront 5yr)", category: "HardCost", basis: "PER_ACRE", value: 30, depr_class: "LandLease_Amortized", attribution: "WindOnly", phasing_id: "default" },
  { id: "wind_e_and_c", name: "Erection & Commissioning", category: "HardCost", basis: "PER_MW_WIND", value: 0.40, depr_class: "Plant", attribution: "WindOnly", phasing_id: "default" },
  { id: "wind_epc_oh", name: "EPC Overhead", category: "EPCOverhead", basis: "PCT_OF_HARDCOST", value: 0.03, depr_class: "Plant", attribution: "WindOnly", phasing_id: "default" },
  { id: "wind_contingency", name: "Contingency", category: "Contingency", basis: "PCT_OF_HARDCOST", value: 0.02, depr_class: "Plant", attribution: "WindOnly", phasing_id: "default" },
];

const BESS_DEFAULT_ITEMS: CostItem[] = [
  { id: "bess_supply", name: "BESS Supply (cells + BMS + PCS)", category: "HardCost", basis: "PER_MWH_BESS", value: 3.50, depr_class: "BESS", attribution: "BESSOnly", phasing_id: "default" },
  { id: "bess_civil", name: "Civil & Integration", category: "HardCost", basis: "PER_MWH_BESS", value: 0.40, depr_class: "Building", attribution: "BESSOnly", phasing_id: "default" },
  { id: "bess_epc_oh", name: "EPC Overhead", category: "EPCOverhead", basis: "PCT_OF_HARDCOST", value: 0.03, depr_class: "BESS", attribution: "BESSOnly", phasing_id: "default" },
];

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function sec(inputs: Raw, key: string): Raw {
  return (inputs[key] as Raw) ?? {};
}

function gv<T>(inputs: Raw, section: string, field: string, fallback: T): T {
  const s = sec(inputs, section);
  const v = s[field];
  return v !== undefined && v !== null ? (v as T) : fallback;
}

function pct(raw: number, decimals = 4): number {
  return parseFloat((raw * 100).toFixed(decimals));
}

function sv(inputs: Raw, section: string, field: string, value: unknown): Raw {
  return { ...inputs, [section]: { ...sec(inputs, section), [field]: value } };
}

function deriveCodDate(project: Raw): string {
  if (project.cod_date) return project.cod_date as string;
  const year = (project.cod_year as number) ?? 2027;
  return `${year}-04-01`;
}

// Compute Cr from a cost item given current capacities (including tax)
function computeItemCr(
  item: CostItem,
  dcMwp: number,
  windMw: number,
  bessMwh: number,
  hardCostSum: number,
  landAcres: number,
): number | null {
  let baseCr: number | null;
  switch (item.basis) {
    case "PER_WP_DC":
      baseCr = item.value * dcMwp * 0.1; // ₹/Wp × MWp × 0.1 = Cr
      break;
    case "PER_MWP_DC":
      baseCr = item.value * dcMwp;
      break;
    case "PER_MW_WIND":
      baseCr = item.value * windMw;
      break;
    case "PER_MWH_BESS":
      baseCr = item.value * bessMwh;
      break;
    case "PCT_OF_HARDCOST":
      baseCr = hardCostSum > 0 ? item.value * hardCostSum : null;
      break;
    case "PER_ACRE":
      baseCr = item.value * (landAcres || 0) * 0.01; // Lakh/acre × acres × 0.01 = Cr (1 Lakh = 0.01 Cr)
      break;
    case "ABS_INR_CR":
      baseCr = item.value;
      break;
    default:
      baseCr = null;
  }
  // Add tax (GST) if applicable - default 5% for modules
  if (baseCr != null) {
    const taxPct = item.tax_pct ?? 5;
    return baseCr * (1 + taxPct / 100);
  }
  return baseCr;
}

function basisLabel(basis: CostItem["basis"]): string {
  switch (basis) {
    case "PER_WP_DC": return "₹/Wp";
    case "PER_MWP_DC": return "Cr/MWp";
    case "PER_MW_WIND": return "Cr/MW";
    case "PER_MWH_BESS": return "Cr/MWh";
    case "PCT_OF_HARDCOST": return "% of HC";
    case "PER_ACRE": return "Lakh/acre";
    case "ABS_INR_CR": return "₹Cr";
    default: return "";
  }
}

function injectDefaultItems(inputs: Raw, solarEnabled: boolean, windEnabled: boolean, bessEnabled: boolean): Raw {
  const capex = sec(inputs, "capex");
  const existing = (capex.cost_items as CostItem[]) ?? [];
  if (existing.length > 0) return inputs;
  const items: CostItem[] = [];
  if (solarEnabled) items.push(...SOLAR_DEFAULT_ITEMS);
  if (windEnabled) items.push(...WIND_DEFAULT_ITEMS);
  if (bessEnabled) items.push(...BESS_DEFAULT_ITEMS);
  return sv(inputs, "capex", "cost_items", items);
}

// ---------------------------------------------------------------------------
// Field primitives
// ---------------------------------------------------------------------------

function Label({ text, sub }: { text: string; sub?: string }) {
  return (
    <div className="flex flex-col">
      <span className="text-xs font-medium text-foreground">{text}</span>
      {sub && <span className="text-[10px] text-muted-foreground">{sub}</span>}
    </div>
  );
}

function NumField({
  label,
  sub,
  value,
  onChange,
  step = 0.01,
  min,
  max,
  suffix,
  readOnly,
}: {
  label: string;
  sub?: string;
  value: number;
  onChange: (v: number) => void;
  step?: number;
  min?: number;
  max?: number;
  suffix?: string;
  readOnly?: boolean;
}) {
  return (
    <div className="flex flex-col gap-1">
      <Label text={label} sub={sub} />
      <div className="flex items-center gap-1.5">
        <input
          type="number"
          step={step}
          min={min}
          max={max}
          value={value}
          readOnly={readOnly}
          onChange={(e) => !readOnly && onChange(parseFloat(e.target.value) || 0)}
          className={`w-24 rounded-md border border-input px-2.5 py-1.5 text-sm tabular-nums transition-colors focus:outline-none focus:ring-2 focus:ring-primary/30 ${
            readOnly ? "bg-muted text-muted-foreground cursor-default" : "bg-background hover:border-primary/40"
          }`}
        />
        {suffix && (
          <span className="text-xs text-muted-foreground whitespace-nowrap">{suffix}</span>
        )}
      </div>
    </div>
  );
}

function DateField({
  label,
  sub,
  value,
  onChange,
  badge,
}: {
  label: string;
  sub?: string;
  value: string;
  onChange: (v: string) => void;
  badge?: string;
}) {
  return (
    <div className="flex flex-col gap-1">
      <div className="flex items-center gap-2">
        <Label text={label} sub={sub} />
        {badge && (
          <span className="text-[9px] px-1.5 py-0.5 rounded-full bg-primary/10 text-primary font-medium">
            {badge}
          </span>
        )}
      </div>
      <input
        type="date"
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className="rounded border border-input bg-background px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-primary/30 hover:border-primary/40 transition-colors"
      />
    </div>
  );
}

function SelectField({
  label,
  sub,
  value,
  onChange,
  options,
}: {
  label: string;
  sub?: string;
  value: string;
  onChange: (v: string) => void;
  options: { value: string; label: string }[];
}) {
  return (
    <div className="flex flex-col gap-1">
      <Label text={label} sub={sub} />
      <select
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className="w-40 rounded-md border border-input bg-background px-3 py-1.5 text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-primary/30 hover:border-primary/40"
      >
        {options.map((o) => (
          <option key={o.value} value={o.value}>
            {o.label}
          </option>
        ))}
      </select>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Card components
// ---------------------------------------------------------------------------

function CardHeader({
  title,
  open,
  onToggle,
  rightSlot,
}: {
  title: string;
  open: boolean;
  onToggle: () => void;
  rightSlot?: React.ReactNode;
}) {
  return (
    <div
      className="flex items-center justify-between px-4 py-3 cursor-pointer select-none hover:bg-muted/30 transition-colors rounded-t-lg"
      onClick={onToggle}
    >
      <div className="flex items-center gap-2">
        <span
          className={`text-muted-foreground transition-transform duration-200 text-xs ${open ? "rotate-0" : "-rotate-90"}`}
        >
          ▾
        </span>
        <span className="font-semibold text-sm">{title}</span>
      </div>
      {rightSlot && (
        <div onClick={(e) => e.stopPropagation()}>{rightSlot}</div>
      )}
    </div>
  );
}

function CollapsibleCard({
  title,
  children,
  cols = 2,
  defaultOpen = true,
}: {
  title: string;
  children: React.ReactNode;
  cols?: number;
  defaultOpen?: boolean;
}) {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div className="border border-border rounded-lg overflow-hidden hover:border-border/80 transition-colors shadow-sm">
      <CardHeader title={title} open={open} onToggle={() => setOpen(!open)} />
      {open && (
        <div className={`px-4 pb-4 grid gap-3 border-t border-border/50 pt-4 grid-cols-${cols}`}>
          {children}
        </div>
      )}
    </div>
  );
}

function ToggleCard({
  title,
  enabled,
  onToggle,
  children,
  defaultOpen = true,
}: {
  title: string;
  enabled: boolean;
  onToggle: (v: boolean) => void;
  children: React.ReactNode;
  defaultOpen?: boolean;
}) {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div className="border border-border rounded-lg overflow-hidden hover:border-border/80 transition-colors shadow-sm">
      <CardHeader
        title={title}
        open={open}
        onToggle={() => setOpen(!open)}
        rightSlot={
          <label className="flex items-center gap-2 cursor-pointer">
            <input
              type="checkbox"
              checked={enabled}
              onChange={(e) => onToggle(e.target.checked)}
              className="w-4 h-4 accent-primary"
            />
            <span className={`text-xs font-medium ${enabled ? "text-primary" : "text-muted-foreground"}`}>
              {enabled ? "Enabled" : "Disabled"}
            </span>
          </label>
        }
      />
      {enabled && open && (
        <div className="px-4 pb-4 grid grid-cols-2 gap-3 border-t border-border/50 pt-4">
          {children}
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// Cost Items Table
// ---------------------------------------------------------------------------

function CostItemsTable({
  items,
  onChange,
  dcMwp,
  windMw,
  bessMwh,
  landAcres,
  attribution,
}: {
  items: CostItem[];
  onChange: (items: CostItem[]) => void;
  dcMwp: number;
  windMw: number;
  bessMwh: number;
  landAcres: number;
  attribution: "SolarOnly" | "WindOnly" | "BESSOnly";
}) {
  const filtered = items.filter((it) => it.attribution === attribution);

  // Compute hard cost sum for PCT items
  const hardCostSum = filtered
    .filter((it) => it.category === "HardCost" || it.category === "SoftCost")
    .reduce((acc, it) => {
      const cr = computeItemCr(it, dcMwp, windMw, bessMwh, 0, landAcres);
      return acc + (cr ?? 0);
    }, 0);

  function updateItem(id: string, field: keyof CostItem, value: unknown) {
    onChange(
      items.map((it) =>
        it.id === id ? { ...it, [field]: value } : it,
      ),
    );
  }

  function removeItem(id: string) {
    onChange(items.filter((it) => it.id !== id));
  }

  function addItem() {
    const newId = `custom_${attribution.toLowerCase()}_${Date.now()}`;
    const defaults: Record<string, CostItem["basis"]> = {
      SolarOnly: "PER_WP_DC",
      WindOnly: "PER_MW_WIND",
      BESSOnly: "PER_MWH_BESS",
    };
    const newItem: CostItem = {
      id: newId,
      name: "Custom Item",
      category: "HardCost",
      basis: defaults[attribution],
      value: 0,
      depr_class: attribution === "BESSOnly" ? "BESS" : "Plant",
      attribution,
      phasing_id: "default",
    };
    onChange([...items, newItem]);
  }

  const totalCr = filtered.reduce((acc, it) => {
    const cr = computeItemCr(it, dcMwp, windMw, bessMwh, hardCostSum, landAcres);
    return acc + (cr ?? 0);
  }, 0);

  return (
    <div className="col-span-2">
      <div className="overflow-x-auto rounded-lg border border-border">
        <table className="w-full text-xs">
          <thead>
            <tr className="bg-muted/50">
              <th className="px-3 py-2 text-left font-semibold text-muted-foreground min-w-[200px]">
                Line Item
              </th>
              <th className="px-3 py-2 text-left font-semibold text-muted-foreground w-20">
                Basis
              </th>
              <th className="px-2 py-2 text-right font-semibold text-muted-foreground w-20">
                Rate
              </th>
              <th className="px-2 py-2 text-right font-semibold text-muted-foreground w-14">
                Tax%
              </th>
              <th className="px-3 py-2 text-right font-semibold text-muted-foreground w-20">
                ₹Cr
              </th>
              <th className="w-6" />
            </tr>
          </thead>
          <tbody>
            {filtered.map((item) => {
              const cr = computeItemCr(item, dcMwp, windMw, bessMwh, hardCostSum, landAcres);
              return (
                <tr
                  key={item.id}
                  className="border-t border-border/50 hover:bg-accent/30 transition-colors"
                >
                  <td className="px-3 py-1.5">
                    <input
                      type="text"
                      value={item.name}
                      onChange={(e) => updateItem(item.id, "name", e.target.value)}
                      className="w-full bg-transparent focus:outline-none focus:bg-background focus:ring-1 focus:ring-primary/30 rounded px-1"
                    />
                  </td>
                  <td className="px-3 py-1.5 text-muted-foreground text-[10px]">
                    {basisLabel(item.basis)}
                  </td>
                  <td className="px-3 py-1.5">
                    <input
                      type="number"
                      step={item.basis === "PCT_OF_HARDCOST" ? 0.005 : 0.1}
                      value={item.basis === "PCT_OF_HARDCOST" ? parseFloat((item.value * 100).toFixed(2)) : item.value}
                      onChange={(e) => {
                        const raw = parseFloat(e.target.value) || 0;
                        updateItem(item.id, "value", item.basis === "PCT_OF_HARDCOST" ? raw / 100 : raw);
                      }}
                      className="w-full text-right bg-transparent focus:outline-none focus:bg-background focus:ring-1 focus:ring-primary/30 rounded px-1 tabular-nums"
                    />
                  </td>
                  <td className="px-2 py-1.5">
                    <input
                      type="text"
                      value={(item.tax_pct ?? 5) + "%"}
                      onChange={(e) => {
                        const num = e.target.value.replace("%", "").replace(/[^0-9.]/g, "");
                        updateItem(item.id, "tax_pct", parseFloat(num) || 0);
                      }}
                      className="w-full text-right bg-transparent focus:outline-none focus:bg-background focus:ring-1 focus:ring-primary/30 rounded px-1 tabular-nums"
                    />
                  </td>
                  <td className="px-3 py-1.5 text-right tabular-nums font-medium">
                    {item.basis === "PCT_OF_HARDCOST" && cr == null ? (
                      <span className="text-muted-foreground italic text-xs">calc...</span>
                    ) : cr != null ? (
                      <span title={item.basis === "PCT_OF_HARDCOST" ? `${(item.value * 100).toFixed(2)}% of ₹${hardCostSum?.toFixed(1) || 0}Cr` : undefined}>
                        {cr.toFixed(1)}
                      </span>
                    ) : (
                      <span className="text-muted-foreground italic text-xs">—</span>
                    )}
                  </td>
                  <td className="px-2 py-1.5">
                    <button
                      onClick={() => removeItem(item.id)}
                      className="text-muted-foreground/40 hover:text-destructive transition-colors text-xs"
                    >
                      ✕
                    </button>
                  </td>
                </tr>
              );
            })}
          </tbody>
          <tfoot>
            <tr className="border-t-2 border-border bg-muted/30">
              <td colSpan={4} className="px-3 py-2 font-semibold text-xs">
                Total ({attribution.replace("Only", "")})
              </td>
              <td className="px-3 py-2 text-right font-semibold tabular-nums">
                {totalCr.toFixed(1)}
              </td>
              <td />
            </tr>
          </tfoot>
        </table>
      </div>
      <button
        onClick={addItem}
        className="mt-2 text-xs text-primary hover:text-primary/80 hover:underline transition-colors"
      >
        + Add custom item
      </button>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Main component
// ---------------------------------------------------------------------------

interface Props {
  scenarioId: string;
  inputsJson: string | null;
  onSaved: () => void;
}

export function InputsTab({ scenarioId, inputsJson, onSaved }: Props) {
  const [inputs, setInputs] = useState<Raw>(() => {
    try {
      const parsed = JSON.parse(inputsJson ?? "{}") as Raw;
      // Always inject default cost items if missing (for old scenarios)
      const capex = parsed.capex as { cost_items?: CostItem[] } | undefined;
      const existingItems = capex?.cost_items ?? [];
      const items: CostItem[] = [...existingItems];
      if (existingItems.length === 0) {
        items.push(...SOLAR_DEFAULT_ITEMS, ...WIND_DEFAULT_ITEMS, ...BESS_DEFAULT_ITEMS);
      }
      return sv({ ...parsed }, "capex", "cost_items", items);
    } catch {
      return {};
    }
  });
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  function upd(section: string, field: string, value: unknown) {
    setInputs((prev) => sv(prev, section, field, value));
  }

  function setSection(key: string, value: unknown) {
    setInputs((prev) => ({ ...prev, [key]: value }));
  }

  function updCostItems(newItems: CostItem[]) {
    setInputs((prev) => sv(prev, "capex", "cost_items", newItems));
  }

  async function handleSave() {
    setSaving(true);
    setError(null);
    try {
      await updateScenarioInputs(scenarioId, inputs as ScenarioInputPayload);
      onSaved();
    } catch (e) {
      setError(e instanceof Error ? e.message : "Save failed");
    } finally {
      setSaving(false);
    }
  }

  const project = sec(inputs, "project");
  const solar = inputs.solar as Raw | null | undefined;
  const wind = inputs.wind as Raw | null | undefined;
  const bess = inputs.bess as Raw | null | undefined;
  const rtc = inputs.rtc as Raw | null | undefined;

  const solarEnabled = solar !== null && solar !== undefined;
  const windEnabled = wind !== null && wind !== undefined;
  const bessEnabled = bess !== null && bess !== undefined;
  const rtcEnabled = rtc !== null && rtc !== undefined;

  const plantCod = deriveCodDate(project);

  // Solar capacity helpers
  const solarAcMw = gv(inputs, "solar", "capacity_ac_mw", 100);
  const solarDcAcRatio = gv(inputs, "solar", "dc_ac_ratio", 1.4);
  const solarDcMwp = parseFloat((solarAcMw * solarDcAcRatio).toFixed(3));
  const moduleType = gv(inputs, "solar", "module_type", "fixed");

  const windMw = gv(inputs, "wind", "capacity_mw", 50);
  const bessMwh = gv(inputs, "bess", "capacity_mwh", 200);

  // Land calculation: 2.5ac/MWp (fixed) or 3.5ac/MWp (tracker) + 0.5ac/MW (wind)
  const solarLandFactor = (moduleType as string) === "tracker" ? 3.5 : 2.5;
  const windLandFactor = 0.5;
  const calculatedLandAcres = solarEnabled ? (solarDcMwp * solarLandFactor) + (windEnabled ? windMw * windLandFactor : 0) : windEnabled ? windMw * windLandFactor : 0;
  // Use explicit value if set, otherwise auto-calculate
  const explicitLandAcres = gv(inputs, "project", "land_acres", 0);
  const effectiveLandAcres = explicitLandAcres > 0 ? explicitLandAcres : Math.max(calculatedLandAcres, 1);

  const costItems = (gv(inputs, "capex", "cost_items", []) as CostItem[]);

  // Compute cost summary with tax breakdown
  function computeCostWithTax(items: CostItem[], attribution: string) {
    const filtered = items.filter((it) => it.attribution === attribution);
    const sum = filtered.reduce((acc, it) => {
      const cr = computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres);
      return acc + (cr ?? 0);
    }, 0);
    return sum;
  }
  const solarTotalCr = computeCostWithTax(costItems, "SolarOnly");
  const windTotalCr = computeCostWithTax(costItems, "WindOnly");
  const bessTotalCr = computeCostWithTax(costItems, "BESSOnly");
  
  // Calculate upfront lease cost based on user inputs (acres * rate * years)
  const leaseRate = gv(inputs, "project", "land_lease_rate", 0.4);
  const leaseYears = gv(inputs, "project", "land_lease_years", 5);
  const upfrontLeaseCostCr = effectiveLandAcres * leaseRate * leaseYears;
  
  const totalCostCr = solarTotalCr + windTotalCr + bessTotalCr + upfrontLeaseCostCr;

  // COD sync helper
  function handlePlantCodChange(v: string) {
    setInputs((prev) => {
      let next = sv(prev, "project", "cod_date", v);
      const p = sec(next, "project");
      // Auto-sync tech CODs if they matched old plant COD or were empty
      if (!p.solar_cod_date || p.solar_cod_date === plantCod) {
        next = sv(next, "project", "solar_cod_date", v);
      }
      if (!p.wind_cod_date || p.wind_cod_date === plantCod) {
        next = sv(next, "project", "wind_cod_date", v);
      }
      if (!p.bess_cod_date || p.bess_cod_date === plantCod) {
        next = sv(next, "project", "bess_cod_date", v);
      }
      return next;
    });
  }

  // Sync DC capacity whenever AC or ratio changes
  function handleSolarAcChange(v: number) {
    const newDc = parseFloat((v * solarDcAcRatio).toFixed(3));
    setInputs((prev) => {
      let next = sv(prev, "solar", "capacity_ac_mw", v);
      next = sv(next, "solar", "capacity_dc_mwp", newDc);
      next = sv(next, "project", "capacity_solar_mwp", newDc);
      return next;
    });
  }

  function handleDcAcRatioChange(v: number) {
    const newDc = parseFloat((solarAcMw * v).toFixed(3));
    setInputs((prev) => {
      let next = sv(prev, "solar", "dc_ac_ratio", v);
      next = sv(next, "solar", "capacity_dc_mwp", newDc);
      next = sv(next, "project", "capacity_solar_mwp", newDc);
      return next;
    });
  }

  return (
    <div className="space-y-3">
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-3">
        {/* ── Project Info ─────────────────────────────────────── */}
        <CollapsibleCard title="Project Info" cols={2}>
        <SelectField
          label="State"
          sub="Used for default CUF profile"
          value={(project.state as string) ?? "RJ"}
          onChange={(v) => {
            upd("project", "state", v);
            // Auto-set location_id for solar/wind
            if (solarEnabled) upd("solar", "location_id", v);
            if (windEnabled) upd("wind", "location_id", v);
          }}
          options={INDIAN_STATES}
        />
        <DateField
          label="Plant COD"
          sub="Commercial Operation Date"
          value={plantCod}
          onChange={handlePlantCodChange}
        />
        <DateField
          label="Solar COD"
          sub="Defaults to Plant COD"
          value={(project.solar_cod_date as string) || plantCod}
          onChange={(v) => upd("project", "solar_cod_date", v === plantCod ? null : v)}
          badge={(project.solar_cod_date as string) && (project.solar_cod_date as string) !== plantCod ? "custom" : "synced"}
        />
        {windEnabled && (
          <DateField
            label="Wind COD"
            sub="Defaults to Plant COD"
            value={(project.wind_cod_date as string) || plantCod}
            onChange={(v) => upd("project", "wind_cod_date", v === plantCod ? null : v)}
            badge={(project.wind_cod_date as string) && (project.wind_cod_date as string) !== plantCod ? "custom" : "synced"}
          />
        )}
        {bessEnabled && (
          <DateField
            label="BESS COD"
            sub="Defaults to Plant COD"
            value={(project.bess_cod_date as string) || plantCod}
            onChange={(v) => upd("project", "bess_cod_date", v === plantCod ? null : v)}
            badge={(project.bess_cod_date as string) && (project.bess_cod_date as string) !== plantCod ? "custom" : "synced"}
          />
        )}
      </CollapsibleCard>

      {/* ── Cost Summary ────────────────────────────────────── */}
      {(() => {
        // Compute grouped from ALL cost items - don't check enablement
        const solarItems = costItems.filter(it => it.attribution === "SolarOnly");
        const windItems = costItems.filter(it => it.attribution === "WindOnly");
        const bessItems = costItems.filter(it => it.attribution === "BESSOnly");

        const solarBOS = solarItems.filter(it => ["solar_inverter", "solar_dc_bos", "solar_ac_bos", "solar_hr"].includes(it.id)).reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        const solarModule = solarItems.filter(it => it.id === "solar_module").reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        const windWTG = windItems.filter(it => ["wind_wtg", "wind_tower", "wind_bop", "wind_e_and_c"].includes(it.id)).reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        // Solar land: only include items with id containing "land" AND attribution "SolarOnly"
        const solarLandCost = solarItems.filter(it => it.id.includes("land") && it.attribution === "SolarOnly").reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        // Wind land: only include items with id containing "land" AND attribution "WindOnly"
        const windLandCost = windItems.filter(it => it.id.includes("land") && it.attribution === "WindOnly").reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        const bessAll = bessItems.reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        const solarEPC = solarItems.filter(it => it.category === "EPCOverhead").reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        const windEPC = windItems.filter(it => it.category === "EPCOverhead").reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        const solarCont = solarItems.filter(it => it.category === "Contingency" && it.attribution === "SolarOnly").reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        const windCont = windItems.filter(it => it.category === "Contingency" && it.attribution === "WindOnly").reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        // EPC Margins
        const epcMarginWTG = [...windItems, ...bessItems].filter(it => it.category === "EPCMargin" && it.attribution === "WindOnly").reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        const epcMarginSolarBOS = solarItems.filter(it => it.category === "EPCMargin" && it.attribution === "SolarOnly").reduce((acc, it) => acc + (computeItemCr(it, solarDcMwp, windMw, bessMwh, 0, effectiveLandAcres) ?? 0), 0);
        // Financing
        const idcRate = gv(inputs, "capex", "interest_rate_annual", 0.09);
        const constrMonths = gv(inputs, "capex", "construction_months", 24);
        const debtFrac = gv(inputs, "capex", "debt_fraction", 0.75);
        const upfrontPct = gv(inputs, "capex", "upfront_fee_pct", 0.01);
        const bankGuaranteePct = gv(inputs, "capex", "bank_guarantee_pct", 0.001);
        // DSRA (Debt Service Reserve Account) - typically 1-2 months of debt service
        const dsraMonths = gv(inputs, "capex", "dsra_months", 2);

        // First compute base hard cost without financing items
        const baseHardCost = solarModule + solarBOS + windWTG + solarLandCost + windLandCost + bessAll + solarEPC + windEPC + epcMarginWTG + epcMarginSolarBOS + solarCont + windCont;

        // Financing costs are based on base hard cost
        const idcCost = baseHardCost * debtFrac * idcRate * constrMonths / 12;
        const upfrontCost = baseHardCost * debtFrac * upfrontPct;
        const bankGuaranteeCost = baseHardCost * bankGuaranteePct;
        // DSRA: 2 months of debt service reserve (based on base hard cost)
        const annualDebtService = baseHardCost * debtFrac * 0.12; // approximate annual debt service at 12% rate
        const dsraCost = annualDebtService * dsraMonths / 12;

        // Compute Total Hard Cost (sum of all component costs before financing)
        const totalHardCost = baseHardCost;

        return (
          <div className="border border-border rounded-lg overflow-hidden">
            <div className="bg-muted/50 px-4 py-2 border-b border-border">
              <h3 className="font-semibold text-sm">Project Cost Breakdown</h3>
            </div>
            <table className="w-full text-xs">
              <tbody>
                {solarModule > 0 && <tr><td className="px-3 py-1.5">Solar Module</td><td className="px-3 py-1.5 text-right tabular-nums">{solarModule.toFixed(2)}</td></tr>}
                {solarBOS > 0 && <tr><td className="px-3 py-1.5">Solar BoS</td><td className="px-3 py-1.5 text-right tabular-nums">{solarBOS.toFixed(2)}</td></tr>}
                {windEnabled && windWTG > 0 && <tr><td className="px-3 py-1.5">Wind WTG</td><td className="px-3 py-1.5 text-right tabular-nums">{windWTG.toFixed(2)}</td></tr>}
                {solarLandCost > 0 && <tr><td className="px-3 py-1.5">Solar Land Cost</td><td className="px-3 py-1.5 text-right tabular-nums">{solarLandCost.toFixed(2)}</td></tr>}
                {windEnabled && windLandCost > 0 && <tr><td className="px-3 py-1.5">Wind Land Cost</td><td className="px-3 py-1.5 text-right tabular-nums">{windLandCost.toFixed(2)}</td></tr>}
                {bessEnabled && bessAll > 0 && <tr><td className="px-3 py-1.5">Storage</td><td className="px-3 py-1.5 text-right tabular-nums">{bessAll.toFixed(2)}</td></tr>}
                {dsraCost > 0 && <tr><td className="px-3 py-1.5">DSRA</td><td className="px-3 py-1.5 text-right tabular-nums">{dsraCost.toFixed(2)}</td></tr>}
                {solarEPC > 0 && <tr><td className="px-3 py-1.5">Solar EPC Overheads</td><td className="px-3 py-1.5 text-right tabular-nums">{solarEPC.toFixed(2)}</td></tr>}
                {windEnabled && windEPC > 0 && <tr><td className="px-3 py-1.5">Wind EPC Overheads</td><td className="px-3 py-1.5 text-right tabular-nums">{windEPC.toFixed(2)}</td></tr>}
                {epcMarginWTG > 0 && <tr><td className="px-3 py-1.5">EPC Margin - WTG Tower+BOP</td><td className="px-3 py-1.5 text-right tabular-nums">{epcMarginWTG.toFixed(2)}</td></tr>}
                {epcMarginSolarBOS > 0 && <tr><td className="px-3 py-1.5">EPC Margin - Solar BOS</td><td className="px-3 py-1.5 text-right tabular-nums">{epcMarginSolarBOS.toFixed(2)}</td></tr>}
                {solarCont > 0 && <tr><td className="px-3 py-1.5">Contingency - Solar</td><td className="px-3 py-1.5 text-right tabular-nums">{solarCont.toFixed(2)}</td></tr>}
                {windEnabled && windCont > 0 && <tr><td className="px-3 py-1.5">Contingency - Wind (in WTG cost)</td><td className="px-3 py-1.5 text-right tabular-nums">{windCont.toFixed(2)}</td></tr>}
                <tr className="border-t-2 border-border bg-muted/30">
                  <td className="px-3 py-2 font-semibold">Total Hard Cost</td>
                  <td className="px-3 py-2 text-right tabular-nums font-semibold">{totalHardCost.toFixed(2)}</td>
                </tr>
                <tr className="border-t border-dashed border-border/50">
                  <td className="px-3 py-1.5 text-muted-foreground">Upfront Financing Fee</td><td className="px-3 py-1.5 text-right tabular-nums text-muted-foreground">{upfrontCost.toFixed(2)}</td>
                </tr>
                <tr>
                  <td className="px-3 py-1.5 text-muted-foreground">Interest During Construction</td><td className="px-3 py-1.5 text-right tabular-nums text-muted-foreground">{idcCost.toFixed(2)}</td>
                </tr>
                <tr>
                  <td className="px-3 py-1.5 text-muted-foreground">Bank Guarantee Cost</td><td className="px-3 py-1.5 text-right tabular-nums text-muted-foreground">{bankGuaranteeCost.toFixed(2)}</td>
                </tr>
                <tr className="border-t-2 border-border bg-muted/30">
                  <td className="px-3 py-2 font-semibold">Total Project Cost</td>
                  <td className="px-3 py-2 text-right tabular-nums font-bold text-primary">{(totalHardCost + upfrontCost + idcCost + bankGuaranteeCost).toFixed(2)}</td>
                </tr>
              </tbody>
            </table>
          </div>
        );
      })()}
      </div>

      {/* ── Solar Generation ─────────────────────────────────── */}
      <ToggleCard
        title="Solar Generation"
        enabled={solarEnabled}
        onToggle={(on) =>
          setSection(
            "solar",
            on
              ? {
                  location_id: (project.state as string) ?? "RJ",
                  capacity_ac_mw: 100,
                  dc_ac_ratio: 1.4,
                  capacity_dc_mwp: 140,
                  availability_fraction: 0.995,
                  degradation_y1: 0.007,
                  degradation_annual: 0.005,
                  stabilization_days: 60,
                  stabilization_energy_loss_frac: 0.20,
                  stabilization_dsm_addon_pct: 0.005,
                }
              : null,
          )
        }
      >
        <div className="flex flex-col gap-1">
          <Label text="Location / Profile" sub="Irradiance data" />
          <div className="flex items-center gap-2">
            <select
              value={gv(inputs, "solar", "location_id", "RJ")}
              onChange={(e) => {
                const v = e.target.value;
                upd("solar", "location_id", v);
                if (v === "custom") {
                  // TODO: Open custom profile upload modal
                  alert("Custom profile upload - coming soon!");
                }
              }}
              className="w-40 rounded-md border border-input bg-background px-3 py-1.5 text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-primary/30 hover:border-primary/40"
            >
              {LOCATIONS.map((o) => (
                <option key={o.value} value={o.value}>
                  {o.label}
                </option>
              ))}
            </select>
            <span className="text-[10px] px-1.5 py-0.5 rounded-full bg-green-100 text-green-700 font-medium">
                ~27% CUF
              </span>
          </div>
        </div>
        <SelectField
          label="Module Type"
          sub="Fixed vs tracker"
          value={gv(inputs, "solar", "module_type", "fixed")}
          onChange={(v) => upd("solar", "module_type", v)}
          options={[
            { value: "fixed", label: "Fixed" },
            { value: "tracker", label: "Tracker" },
          ]}
        />
        <NumField
          label="AC Capacity"
          sub="inverter rating"
          value={solarAcMw}
          onChange={handleSolarAcChange}
          step={5}
          min={1}
          suffix="MW"
        />
        <NumField
          label="DC:AC Ratio"
          sub="overloading"
          value={solarDcAcRatio}
          onChange={handleDcAcRatioChange}
          step={0.05}
          min={1.0}
          max={1.8}
        />
        <NumField
          label="DC Capacity"
          sub="auto-calc"
          value={solarDcMwp}
          onChange={() => {}}
          readOnly
          suffix="MWp"
        />
        <NumField
          label="Availability"
          sub="default 99.5%"
          value={pct(gv(inputs, "solar", "availability_fraction", 0.995))}
          onChange={(v) => upd("solar", "availability_fraction", v / 100)}
          step={0.1}
          suffix="%"
        />
        <NumField
          label="Y1 Degradation"
          sub="LID + initial"
          value={pct(gv(inputs, "solar", "degradation_y1", 0.007))}
          onChange={(v) => upd("solar", "degradation_y1", v / 100)}
          step={0.1}
          suffix="%"
        />
        <NumField
          label="Annual Degradation"
          sub="Y2-Y25"
          value={pct(gv(inputs, "solar", "degradation_annual", 0.005))}
          onChange={(v) => upd("solar", "degradation_annual", v / 100)}
          step={0.05}
          suffix="%/yr"
        />
        <div className="col-span-3 border-t border-dashed border-border/60 pt-3 mt-1">
          <p className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground mb-2">
            Stabilisation Period
          </p>
          <div className="grid grid-cols-3 gap-3">
            <NumField
              label="Days from COD"
              sub="default 60"
              value={gv(inputs, "solar", "stabilization_days", 60)}
              onChange={(v) => upd("solar", "stabilization_days", Math.round(v))}
              step={1}
              min={0}
              suffix="days"
            />
            <NumField
              label="Energy Loss"
              sub="default 20%"
              value={pct(gv(inputs, "solar", "stabilization_energy_loss_frac", 0.20))}
              onChange={(v) => upd("solar", "stabilization_energy_loss_frac", v / 100)}
              step={1}
              suffix="%"
            />
            <NumField
              label="DSM Add-on"
              sub="default 0.5%"
              value={pct(gv(inputs, "solar", "stabilization_dsm_addon_pct", 0.005))}
              onChange={(v) => upd("solar", "stabilization_dsm_addon_pct", v / 100)}
              step={0.1}
              suffix="%"
            />
          </div>
        </div>
      </ToggleCard>

        {/* ── Land & Common ────────────────────────────────────── */}
      <CollapsibleCard title="Land & Common Costs" cols={3}>
        <NumField
          label="Total Land Area"
          sub="acres needed"
          value={effectiveLandAcres}
          onChange={(v) => upd("project", "land_acres", v)}
          step={10}
          min={0}
          suffix="acres"
        />
        <NumField
          label="Lease Rate"
          sub="Lakh/acre/year"
          value={leaseRate}
          onChange={(v) => upd("project", "land_lease_rate", v)}
          step={0.05}
          min={0}
          suffix="L/acre"
        />
        <NumField
          label="Lease Years"
          sub="3, 5, 10 or custom"
          value={leaseYears}
          onChange={(v) => upd("project", "land_lease_years", v)}
          step={1}
          min={1}
          max={30}
          suffix="yr"
        />
        <div className="col-span-3 text-[10px] text-muted-foreground py-1">
           Upfront Lease Cost (included in Total Project Cost): <span className="font-medium text-foreground">{upfrontLeaseCostCr.toFixed(2)} Cr</span>
        </div>
      </CollapsibleCard>

      {/* ── Solar Capex ──────────────────────────────────────── */}
      {solarEnabled && (
        <CollapsibleCard title={`Solar Capex  —  DC Capacity: ${solarDcMwp} MWp`} cols={2}>
          <CostItemsTable
            items={costItems}
            onChange={updCostItems}
            dcMwp={solarDcMwp}
            windMw={windMw}
            bessMwh={bessMwh}
            landAcres={gv(inputs, "project", "land_acres", 0)}
            attribution="SolarOnly"
          />
        </CollapsibleCard>
      )}

      {/* ── Wind Generation ──────────────────────────────────── */}
      <ToggleCard
        title="Wind Generation"
        enabled={windEnabled}
        onToggle={(on) =>
          setSection(
            "wind",
            on
              ? {
                  location_id: (project.state as string) ?? "RJ",
                  capacity_mw: 50,
                  hub_height_m: 140,
                  availability_fraction: 0.97,
                  wake_loss_fraction: 0.05,
                  stabilization_days: 60,
                  stabilization_energy_loss_frac: 0.15,
                  stabilization_dsm_addon_pct: 0.005,
                }
              : null,
          )
        }
      >
        {/* Row 1: Location + Capacity */}
        <SelectField
          label="Location / Profile"
          sub="Wind speed data"
          value={gv(inputs, "wind", "location_id", "RJ")}
          onChange={(v) => upd("wind", "location_id", v)}
          options={LOCATIONS}
        />
        <NumField
          label="Capacity"
          sub="nameplate"
          value={gv(inputs, "wind", "capacity_mw", 50)}
          onChange={(v) => {
            upd("wind", "capacity_mw", v);
            setInputs((prev) => sv(prev, "project", "capacity_wind_mw", v));
          }}
          step={5}
          min={1}
          suffix="MW"
        />
        <NumField
          label="Hub Height"
          sub="tower height"
          value={gv(inputs, "wind", "hub_height_m", 140)}
          onChange={(v) => upd("wind", "hub_height_m", v)}
          step={10}
          min={80}
          suffix="m"
        />

        {/* Row 2: Performance */}
        <NumField
          label="Availability"
          sub="default 97%"
          value={pct(gv(inputs, "wind", "availability_fraction", 0.97))}
          onChange={(v) => upd("wind", "availability_fraction", v / 100)}
          step={0.1}
          suffix="%"
        />
        <NumField
          label="Wake Loss"
          sub="default 5%"
          value={pct(gv(inputs, "wind", "wake_loss_fraction", 0.05))}
          onChange={(v) => upd("wind", "wake_loss_fraction", v / 100)}
          step={0.5}
          suffix="%"
        />
        <div className="border-t border-dashed border-border/60 pt-3 mt-1" />

        {/* Row 3: Stabilization */}
        <div className="col-span-3 border-t border-dashed border-border/60 pt-3 mt-1">
          <p className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground mb-2">
            Stabilisation Period
          </p>
          <div className="grid grid-cols-3 gap-3">
            <NumField
              label="Days from COD"
              sub="default 60"
              value={gv(inputs, "wind", "stabilization_days", 60)}
              onChange={(v) => upd("wind", "stabilization_days", Math.round(v))}
              step={1}
              min={0}
              suffix="days"
            />
            <NumField
              label="Energy Loss"
              sub="default 15%"
              value={pct(gv(inputs, "wind", "stabilization_energy_loss_frac", 0.15))}
              onChange={(v) => upd("wind", "stabilization_energy_loss_frac", v / 100)}
              step={1}
              suffix="%"
            />
            <NumField
              label="DSM Add-on"
              sub="default 0.5%"
              value={pct(gv(inputs, "wind", "stabilization_dsm_addon_pct", 0.005))}
              onChange={(v) => upd("wind", "stabilization_dsm_addon_pct", v / 100)}
              step={0.1}
              suffix="%"
            />
          </div>
        </div>
      </ToggleCard>

      {/* ── Wind Capex ───────────────────────────────────────── */}
      {windEnabled && (
        <CollapsibleCard title={`Wind Capex  —  Capacity: ${windMw} MW`} cols={2}>
          <CostItemsTable
            items={costItems}
            onChange={updCostItems}
            dcMwp={solarDcMwp}
            windMw={windMw}
            bessMwh={bessMwh}
            landAcres={gv(inputs, "project", "land_acres", 0)}
            attribution="WindOnly"
          />
        </CollapsibleCard>
      )}

      {/* ── BESS ─────────────────────────────────────────────── */}
      <ToggleCard
        title="BESS (Battery Storage)"
        enabled={bessEnabled}
        onToggle={(on) =>
          setSection(
            "bess",
            on
              ? {
                  capacity_mwh: gv(inputs, "project", "capacity_bess_mwh", 200),
                  power_mw: gv(inputs, "project", "capacity_bess_mw", 50),
                  rte: 0.85,
                  dod: 0.85,
                }
              : null,
          )
        }
      >
        {/* Row 1: Capacity trio */}
        <NumField
          label="Energy Capacity"
          sub="nameplate"
          value={gv(inputs, "bess", "capacity_mwh", 200)}
          onChange={(v) => {
            upd("bess", "capacity_mwh", v);
            setInputs((prev) => sv(prev, "project", "capacity_bess_mwh", v));
          }}
          step={10}
          min={10}
          suffix="MWh"
        />
        <NumField
          label="Power Capacity"
          sub="max charge/discharge"
          value={gv(inputs, "bess", "power_mw", 50)}
          onChange={(v) => {
            upd("bess", "power_mw", v);
            setInputs((prev) => sv(prev, "project", "capacity_bess_mw", v));
          }}
          step={5}
          min={5}
          suffix="MW"
        />
        <div className="border-t border-dashed border-border/60 pt-3 mt-1" />

        {/* Row 2: Performance */}
        <NumField
          label="RTE"
          sub="round-trip"
          value={pct(gv(inputs, "bess", "rte", 0.85))}
          onChange={(v) => upd("bess", "rte", v / 100)}
          step={1}
          suffix="%"
        />
        <NumField
          label="DOD"
          sub="depth of discharge"
          value={pct(gv(inputs, "bess", "dod", 0.85))}
          onChange={(v) => upd("bess", "dod", v / 100)}
          step={1}
          suffix="%"
        />
      </ToggleCard>

      {/* ── BESS Capex ───────────────────────────────────────── */}
      {bessEnabled && (
        <CollapsibleCard title={`BESS Capex  —  Capacity: ${bessMwh} MWh`} cols={2}>
          <CostItemsTable
            items={costItems}
            onChange={updCostItems}
            dcMwp={solarDcMwp}
            windMw={windMw}
            bessMwh={bessMwh}
            landAcres={0}
            attribution="BESSOnly"
          />
        </CollapsibleCard>
      )}

      {/* ── RTC Dispatch ─────────────────────────────────────── */}
      <ToggleCard
        title="RTC Dispatch"
        enabled={rtcEnabled}
        onToggle={(on) =>
          setSection("rtc", on ? { rtc_mw: 50, mcp_enabled: false, initial_soc_frac: 0.5 } : null)
        }
      >
        <NumField
          label="RTC Contracted Capacity"
          sub="MW"
          value={gv(inputs, "rtc", "rtc_mw", 50)}
          onChange={(v) => upd("rtc", "rtc_mw", v)}
          step={5}
          min={0}
          suffix="MW"
        />
        <div className="flex flex-col gap-1">
          <Label text="Sell Surplus at MCP" sub="Market Clearing Price" />
          <label className="flex items-center gap-2 cursor-pointer mt-1">
            <input
              type="checkbox"
              checked={gv(inputs, "rtc", "mcp_enabled", false) as boolean}
              onChange={(e) => upd("rtc", "mcp_enabled", e.target.checked)}
              className="w-4 h-4 accent-primary"
            />
            <span className="text-sm">Enable MCP revenue</span>
          </label>
        </div>
      </ToggleCard>

      {/* ── Commercial ───────────────────────────────────────── */}
      <CollapsibleCard title="Commercial / PPA" cols={3}>
        {/* Row 1: Tariff */}
        <NumField
          label="PPA Tariff"
          sub="₹/kWh"
          value={gv(inputs, "commercial", "tariff_inr_per_kwh", 3.5)}
          onChange={(v) => upd("commercial", "tariff_inr_per_kwh", v)}
          step={0.05}
          min={1}
          suffix="₹/kWh"
        />
        <div className="border-t border-dashed border-border/60 pt-3 mt-1" />
        <div className="border-t border-dashed border-border/60 pt-3 mt-1" />

        {/* Row 2: Losses */}
        <NumField
          label="Aux"
          sub="default 0.5%"
          value={pct(gv(inputs, "commercial", "aux_consumption_pct", 0.005))}
          onChange={(v) => upd("commercial", "aux_consumption_pct", v / 100)}
          step={0.1}
          suffix="%"
        />
        <NumField
          label="Tx Loss"
          sub="default 1%"
          value={pct(gv(inputs, "commercial", "transmission_loss_pct", 0.01))}
          onChange={(v) => upd("commercial", "transmission_loss_pct", v / 100)}
          step={0.1}
          suffix="%"
        />
        <NumField
          label="DSM/RTC"
          sub="default 2%"
          value={pct(gv(inputs, "commercial", "dsm_loss_pct", 0.02))}
          onChange={(v) => upd("commercial", "dsm_loss_pct", v / 100)}
          step={0.1}
          suffix="%"
        />

        {/* Row 3: Working Capital */}
        <NumField
          label="Bad Debt"
          sub="default 0%"
          value={pct(gv(inputs, "commercial", "bad_debt_pct", 0.0))}
          onChange={(v) => upd("commercial", "bad_debt_pct", v / 100)}
          step={0.1}
          suffix="%"
        />
        <NumField
          label="Receivable"
          sub="default 45 days"
          value={gv(inputs, "commercial", "receivable_days", 45)}
          onChange={(v) => upd("commercial", "receivable_days", v)}
          step={1}
          suffix="days"
        />
        <div className="border-t border-dashed border-border/60 pt-3 mt-1" />
      </CollapsibleCard>

      {/* ── Operating Expenditure ────────────────────────────── */}
      <CollapsibleCard title="Operating Expenditure" cols={3}>
        {/* Solar O&M */}
        {solarEnabled && (
          <>
            <div className="col-span-3 mt-1">
              <p className="text-[10px] font-semibold uppercase tracking-wider text-primary/70 mb-2">
                Solar O&M
              </p>
            </div>
            <NumField
              label="Rate"
              sub="₹L/MWp/yr"
              value={parseFloat(((gv(inputs, "opex", "om_solar_cr_per_mw", 0.025) as number) * 100).toFixed(4))}
              onChange={(v) => upd("opex", "om_solar_cr_per_mw", v / 100)}
              step={0.1}
              suffix="L/MWp"
            />
            <NumField
              label="Escalation"
              sub="default 5%/yr"
              value={pct(gv(inputs, "opex", "om_solar_escalation_pct", 0.05))}
              onChange={(v) => upd("opex", "om_solar_escalation_pct", v / 100)}
              step={0.5}
              suffix="%"
            />
            <NumField
              label="Start Yr"
              sub="default Year 4"
              value={gv(inputs, "opex", "om_solar_escalation_after_year", 4)}
              onChange={(v) => upd("opex", "om_solar_escalation_after_year", Math.round(v))}
              step={1}
              min={1}
              max={25}
            />
          </>
        )}

        {/* Wind O&M */}
        {windEnabled && (
          <>
            <div className="col-span-3 border-t border-dashed border-border/60 pt-3 mt-1">
              <p className="text-[10px] font-semibold uppercase tracking-wider text-primary/70 mb-2">
                Wind O&M
              </p>
            </div>
            <NumField
              label="Rate"
              sub="₹L/MW/yr"
              value={parseFloat(((gv(inputs, "opex", "om_wind_cr_per_mw", 0.08) as number) * 100).toFixed(4))}
              onChange={(v) => upd("opex", "om_wind_cr_per_mw", v / 100)}
              step={0.5}
              suffix="L/MW"
            />
            <NumField
              label="Escalation"
              sub="default 5%/yr"
              value={pct(gv(inputs, "opex", "om_wind_escalation_pct", 0.05))}
              onChange={(v) => upd("opex", "om_wind_escalation_pct", v / 100)}
              step={0.5}
              suffix="%"
            />
            <NumField
              label="Start Yr"
              sub="default Year 5"
              value={gv(inputs, "opex", "om_wind_escalation_after_year", 5)}
              onChange={(v) => upd("opex", "om_wind_escalation_after_year", Math.round(v))}
              step={1}
              min={1}
              max={25}
            />
          </>
        )}

        {/* BESS O&M */}
        {bessEnabled && (
          <>
            <div className="col-span-3 border-t border-dashed border-border/60 pt-3 mt-1">
              <p className="text-[10px] font-semibold uppercase tracking-wider text-primary/70 mb-2">
                BESS O&M
              </p>
            </div>
            <NumField
              label="O&M"
              sub="% of capex/yr"
              value={pct(gv(inputs, "opex", "om_bess_pct_of_capex", 0.03) as number)}
              onChange={(v) => upd("opex", "om_bess_pct_of_capex", v / 100)}
              step={0.1}
              suffix="%"
            />
            <div className="border-t border-dashed border-border/60 pt-3 mt-1" />
            <div className="border-t border-dashed border-border/60 pt-3 mt-1" />
          </>
        )}

        {/* Common */}
        <div className="col-span-3 border-t border-dashed border-border/60 pt-3 mt-1">
          <p className="text-[10px] font-semibold uppercase tracking-wider text-primary/70 mb-2">
            Common
          </p>
        </div>
        <NumField
          label="Insurance"
          sub="default 0.5%"
          value={pct(gv(inputs, "opex", "insurance_pct_of_capex", 0.005))}
          onChange={(v) => upd("opex", "insurance_pct_of_capex", v / 100)}
          step={0.05}
          suffix="%"
        />
        <NumField
          label="AM Fee"
          sub="default 1%"
          value={pct(gv(inputs, "opex", "am_fee_pct_of_revenue", 0.01))}
          onChange={(v) => upd("opex", "am_fee_pct_of_revenue", v / 100)}
          step={0.1}
          suffix="%"
        />
        <NumField
          label="Misc"
          sub="₹Cr/yr"
          value={gv(inputs, "opex", "misc_cr", 0.5)}
          onChange={(v) => upd("opex", "misc_cr", v)}
          step={0.1}
          suffix="Cr"
        />
      </CollapsibleCard>

      {/* ── Construction & Financing ─────────────────────────── */}
      <CollapsibleCard title="Construction & Financing" cols={3}>
        {/* Row 1 */}
        <NumField
          label="Period"
          sub="months"
          value={gv(inputs, "capex", "construction_months", 24)}
          onChange={(v) => upd("capex", "construction_months", Math.round(v))}
          step={1}
          min={6}
          max={60}
          suffix="months"
        />
        <NumField
          label="IDC Rate"
          sub="% pa"
          value={pct(gv(inputs, "capex", "interest_rate_annual", 0.09))}
          onChange={(v) => upd("capex", "interest_rate_annual", v / 100)}
          step={0.1}
          suffix="%"
        />
        <div className="border-t border-dashed border-border/60 pt-3 mt-1" />

        {/* Row 2 */}
        <NumField
          label="Debt Fraction"
          sub="% of TPC"
          value={pct(gv(inputs, "capex", "debt_fraction", 0.75))}
          onChange={(v) => upd("capex", "debt_fraction", v / 100)}
          step={1}
          suffix="%"
        />
        <NumField
          label="Upfront Fee"
          sub="% of debt"
          value={pct(gv(inputs, "capex", "upfront_fee_pct", 0.0075 * 1.18))}
          onChange={(v) => upd("capex", "upfront_fee_pct", v / 100)}
          step={0.1}
          suffix="%"
        />
      </CollapsibleCard>

      {/* ── Debt Financing ───────────────────────────────────── */}
      <CollapsibleCard title="Debt Financing" cols={3}>
        {/* Row 1 */}
        <NumField
          label="Interest"
          sub="coupon pa"
          value={pct(gv(inputs, "debt", "interest_rate_annual", 0.09))}
          onChange={(v) => upd("debt", "interest_rate_annual", v / 100)}
          step={0.25}
          suffix="%"
        />
        <NumField
          label="Tenor"
          sub="years"
          value={gv(inputs, "debt", "tenor_years", 18)}
          onChange={(v) => upd("debt", "tenor_years", Math.round(v))}
          step={1}
          min={5}
          max={25}
          suffix="years"
        />
        <NumField
          label="Moratorium"
          sub="interest-only"
          value={gv(inputs, "debt", "moratorium_years", 1)}
          onChange={(v) => upd("debt", "moratorium_years", Math.round(v))}
          step={1}
          min={0}
          suffix="years"
        />

        {/* Row 2 */}
        <NumField
          label="D:E Ratio"
          sub="max leverage"
          value={gv(inputs, "debt", "de_ratio", 3.0)}
          onChange={(v) => upd("debt", "de_ratio", v)}
          step={0.25}
          min={0.5}
        />
        <NumField
          label="Min DSCR"
          sub="covenant"
          value={gv(inputs, "debt", "min_dscr", 1.2)}
          onChange={(v) => upd("debt", "min_dscr", v)}
          step={0.05}
          min={1.0}
        />
        <NumField
          label="Avg DSCR"
          sub="for sculpting"
          value={gv(inputs, "debt", "avg_dscr", 1.35)}
          onChange={(v) => upd("debt", "avg_dscr", v)}
          step={0.05}
          min={1.0}
        />
        <div className="col-span-3">
          <SelectField
            label="Repayment Shape"
            value={gv(inputs, "debt", "schedule_shape", "equal_principal") as string}
            onChange={(v) => upd("debt", "schedule_shape", v)}
            options={DEBT_SHAPES}
          />
        </div>
      </CollapsibleCard>

      {/* ── Tax ──────────────────────────────────────────────── */}
      <CollapsibleCard title="Tax (Section 115BAA)" defaultOpen={false}>
        <NumField
          label="Effective Tax Rate"
          sub="incl. surcharge & cess"
          value={pct(gv(inputs, "tax", "rate", 0.2517))}
          onChange={(v) => upd("tax", "rate", v / 100)}
          step={0.1}
          suffix="%"
        />
        <NumField
          label="WDV Plant Rate"
          sub="40% for Solar/Wind"
          value={pct(gv(inputs, "tax", "wdv_plant_rate", 0.4))}
          onChange={(v) => upd("tax", "wdv_plant_rate", v / 100)}
          step={1}
          suffix="%"
        />
        <NumField
          label="WDV BESS Rate"
          value={pct(gv(inputs, "tax", "wdv_bess_rate", 0.4))}
          onChange={(v) => upd("tax", "wdv_bess_rate", v / 100)}
          step={1}
          suffix="%"
        />
        <NumField
          label="WDV Building Rate"
          value={pct(gv(inputs, "tax", "wdv_building_rate", 0.1))}
          onChange={(v) => upd("tax", "wdv_building_rate", v / 100)}
          step={1}
          suffix="%"
        />
      </CollapsibleCard>

      {/* ── Solver ───────────────────────────────────────────── */}
      <CollapsibleCard title="Solver">
        <div className="col-span-2">
          <SelectField
            label="Mode"
            value={gv(inputs, "solver", "mode", "solve_tariff") as string}
            onChange={(v) => upd("solver", "mode", v)}
            options={[
              { value: "solve_tariff", label: "Solve tariff for target Equity IRR" },
              { value: "fixed_tariff", label: "Fixed tariff (compute IRR)" },
            ]}
          />
        </div>
        {gv(inputs, "solver", "mode", "solve_tariff") === "solve_tariff" ? (
          <NumField
            label="Target Equity IRR"
            value={pct(gv(inputs, "solver", "target_equity_irr", 0.18))}
            onChange={(v) => upd("solver", "target_equity_irr", v / 100)}
            step={0.5}
            min={5}
            max={40}
            suffix="%"
          />
        ) : (
          <NumField
            label="Fixed Tariff"
            value={gv(inputs, "solver", "fixed_tariff", 3.5) as number}
            onChange={(v) => upd("solver", "fixed_tariff", v)}
            step={0.05}
            min={1}
            suffix="₹/kWh"
          />
        )}
      </CollapsibleCard>

      {error && (
        <p className="text-sm text-destructive bg-destructive/10 rounded-lg px-3 py-2 border border-destructive/20">
          {error}
        </p>
      )}
      <div className="flex justify-end pt-2 pb-4">
        <Button onClick={handleSave} disabled={saving} className="px-6">
          {saving ? "Saving…" : "Save & Re-run"}
        </Button>
      </div>
    </div>
  );
}
