"use client";

import { AlertTriangle, Factory, Gauge, Plus, Recycle, Sparkles, Trash2, Zap } from "lucide-react";
import { useEffect, useMemo, useState } from "react";

import { Button } from "@/components/ui/button";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { MACHINE_BY_ID, catalogPlacement, downstreamProducts, iconForGroup } from "@/app/lib/factorio-data";
import { groupLabel, localizedName, tr } from "@/app/lib/i18n";
import {
  QUALITY_RECYCLING_PRODUCTS, RECYCLING_PRODUCTS, RECYCLING_ROUTE_BY_ID, calculateRecycling,
} from "@/app/lib/recycling";
import type {
  EnergySourceSelection, ItemGroupId, Locale, MaterialFlow, QualityId, RateUnit, RecyclingInput, RecyclingRoute,
} from "@/app/lib/types";
import { FactorioIcon } from "./factorio-icon";
import { SearchPicker } from "./search-picker";
import {
  BeaconCountSelect, FieldLabel, GeometryDesign, MaterialRow, MaterialRowContent, MetricCard, ModuleConfigurator,
  type ModuleConfig, QualitySelect, SectionTitle, SmartNumberInput, UnitSelect, formatNumber, formatPower, resolvedModules,
} from "./calculator-widgets";

type Target = {
  id: string; productId: string; routeId: string; amount: number; unit: RateUnit;
  targetOutputId: string;
  inputQuality: QualityId; outputQuality: QualityId | "total"; maxQuality: QualityId; recyclerQuality: QualityId;
  machineConfig: ModuleConfig; beaconConfig: ModuleConfig; beaconEnabled: boolean; beaconCount: number;
  beaconQuality: QualityId; includeEnergy: boolean;
};
const recycler = MACHINE_BY_ID.get("recycler")!;
const recycleRecipe = {
  id: "recycling", name: "Recycling", categories: ["recycling"], energy: .5,
  ingredients: [], products: [], allowProductivity: false, allowQuality: true, icon: recycler.icon,
};
function makeTarget(id: string, qualityMode: boolean, productId?: string): Target {
  const products = qualityMode ? QUALITY_RECYCLING_PRODUCTS : RECYCLING_PRODUCTS;
  const preferred = products.find((p) => p.id === productId) ?? products[0];
  const preferredRoute = RECYCLING_ROUTE_BY_ID.get(preferred.routeIds[0])!;
  return {
    id, productId: preferred.id, routeId: preferred.routeIds[0], amount: 60, unit: "s",
    targetOutputId: preferredRoute.outputs[0]?.id ?? "",
    inputQuality: "normal", outputQuality: "total", maxQuality: "legendary", recyclerQuality: "normal",
    machineConfig: { mode: "auto", families: [qualityMode ? "quality" : "speed"], tier: 3, quality: "normal", manual: [] },
    beaconConfig: { mode: "auto", families: ["speed"], tier: 3, quality: "normal", manual: [] },
    beaconEnabled: qualityMode, beaconCount: qualityMode ? 1 : 0, beaconQuality: "normal", includeEnergy: false,
  };
}

function recyclingRouteLabel(route: RecyclingRoute, locale: Locale) {
  return route.sourceRecipeId
    ? localizedName(route.sourceRecipeId, locale, "recipe")
    : `${localizedName(route.productId, locale, "item")} · ${tr(locale, "recycling")}`;
}

function selectedQualityFlow(flow: MaterialFlow, target: Target, qualityMode: boolean): MaterialFlow {
  if (!qualityMode || target.outputQuality === "total") return flow;
  const amounts = flow.amounts.filter((entry) => entry.quality === target.outputQuality);
  return { ...flow, amounts, total: amounts.reduce((sum, entry) => sum + entry.amount, 0) };
}

function RecyclingOutputPicker({
  flow,
  target,
  qualityMode,
  locale,
  products,
  navigate,
}: {
  flow: MaterialFlow;
  target: Target;
  qualityMode: boolean;
  locale: Locale;
  products: typeof RECYCLING_PRODUCTS;
  navigate: (targetId: string, productId: string) => void;
}) {
  const displayed = selectedQualityFlow(flow, target, qualityMode);
  const downstream = downstreamProducts(`item:${flow.id}`).filter((entry) =>
    products.some((candidate) => candidate.id === entry.id),
  );
  if (!downstream.length)
    return (
      <MaterialRow
        flow={displayed}
        unit={target.unit}
        locale={locale}
        onClick={
          products.some((entry) => entry.id === flow.id)
            ? () => navigate(target.id, flow.id)
            : undefined
        }
      />
    );
  const options = downstream.map((entry) => ({
    value: entry.id,
    label: localizedName(entry.id, locale, "item"),
    icon: entry.icon,
    keywords: `${entry.name} ${entry.id}`,
    group: entry.group,
    subgroup: entry.subgroup,
    subgroupLabel: entry.subgroup
      ? localizedName(entry.subgroup, locale, "subgroup")
      : undefined,
  }));
  const groups = (
    [
      "logistics",
      "production",
      "intermediate-products",
      "space",
      "combat",
      "fluids",
    ] as ItemGroupId[]
  )
    .filter((id) => options.some((option) => option.group === id))
    .map((id) => ({
      id,
      label: groupLabel(id, locale),
      icon: iconForGroup(id),
    }));
  const currentPlacement = catalogPlacement(flow.id, "item");
  return (
    <SearchPicker
      value={flow.id}
      options={options}
      groups={groups}
      triggerOption={{
        value: flow.id,
        label: localizedName(flow.id, locale, "item"),
        icon: flow.icon,
        group: currentPlacement.group,
        subgroup: currentPlacement.subgroup,
      }}
      triggerContent={
        <MaterialRowContent
          flow={displayed}
          unit={target.unit}
          locale={locale}
        />
      }
      onChange={(productId) => navigate(target.id, productId)}
      placeholder={tr(locale, "chooseNextProduct")}
      searchPlaceholder={tr(locale, "downstreamProducts")}
      emptyText={tr(locale, "noMatch")}
      triggerClassName="border-white/7 bg-[#151719] text-zinc-100 hover:border-[#f7a72d]/40 hover:bg-[#191c1e]"
    />
  );
}

function RecyclingSettings({
  target, qualityMode, locale, onChange, onRemove, canRemove, energySelection, onEnergyToggle,
}: { target: Target; qualityMode: boolean; locale: Locale; onChange: (patch: Partial<Target>) => void; onRemove: () => void; canRemove: boolean; energySelection?: EnergySourceSelection; onEnergyToggle: (id: string, field: "includeDirect" | "includeChain", value: boolean) => void }) {
  const products = qualityMode ? QUALITY_RECYCLING_PRODUCTS : RECYCLING_PRODUCTS;
  const product = products.find((entry) => entry.id === target.productId) ?? products[0];
  const route = RECYCLING_ROUTE_BY_ID.get(target.routeId) ?? RECYCLING_ROUTE_BY_ID.get(product.routeIds[0])!;
  const productOptions = products.map((entry) => { const placement = catalogPlacement(entry.id,"item"); return { value: entry.id, label: localizedName(entry.id, locale, "item"), icon: entry.icon, keywords: entry.name, group: placement.group, subgroup: placement.subgroup, subgroupLabel: placement.subgroup ? localizedName(placement.subgroup, locale, "subgroup") : undefined }; });
  const groups = (["logistics","production","intermediate-products","space","combat","fluids"] as ItemGroupId[]).filter((id)=>productOptions.some((option)=>option.group===id)).map((id) => ({ id, label: groupLabel(id,locale), icon: iconForGroup(id) }));
  return (
    <section className="panel-card">
      <div className="mb-4 flex items-center justify-between"><SectionTitle number="#" title={tr(locale, "recycleProduct")} icons={[recycler.icon]} /><Button type="button" size="icon-sm" variant="ghost" disabled={!canRemove} onClick={onRemove} className="text-zinc-600 hover:text-[#e65d4f]"><Trash2 /></Button></div>
      <FieldLabel>{tr(locale, "product")}</FieldLabel>
      <SearchPicker value={product.id} options={productOptions} groups={groups} onChange={(id) => {
        const next = products.find((entry) => entry.id === id)!;
        const nextRoute = RECYCLING_ROUTE_BY_ID.get(next.routeIds[0])!;
        onChange({ productId: id, routeId: next.routeIds[0], targetOutputId: nextRoute.outputs[0]?.id ?? "" });
      }} placeholder={tr(locale, "selectProduct")} searchPlaceholder={tr(locale, "searchProducts")} emptyText={tr(locale, "noMatch")} />
      {product.routeIds.length > 1 ? <div className="mt-3"><FieldLabel>{tr(locale, "recipeRoute")}</FieldLabel><Select value={route.id} onValueChange={(routeId) => { const nextRoute=RECYCLING_ROUTE_BY_ID.get(routeId)!; onChange({ routeId, targetOutputId: nextRoute.outputs[0]?.id ?? "" }); }}><SelectTrigger className="h-10 border-white/10 bg-[#17191b]"><SelectValue /></SelectTrigger><SelectContent>{product.routeIds.map((id) => { const option = RECYCLING_ROUTE_BY_ID.get(id)!; return <SelectItem key={id} value={id}>{recyclingRouteLabel(option, locale)}</SelectItem>; })}</SelectContent></Select></div> : null}
      {qualityMode ? <div className="mt-3"><FieldLabel>{tr(locale,"targetReturn")}</FieldLabel><Select value={target.targetOutputId} onValueChange={(targetOutputId)=>onChange({targetOutputId})}><SelectTrigger className="h-10 border-white/10 bg-[#17191b]"><SelectValue /></SelectTrigger><SelectContent>{route.outputs.map((output)=><SelectItem key={output.id} value={output.id}><span className="flex items-center gap-2"><FactorioIcon src={output.icon} alt="" size="sm" />{localizedName(output.id,locale,"item")}</span></SelectItem>)}</SelectContent></Select></div> : null}
      <div className="target-rate-inline mt-3 grid grid-cols-[1fr_88px] gap-2 rounded-xl p-3"><div><FieldLabel>{qualityMode ? tr(locale,"desiredQualityOutput") : tr(locale, "amount")}</FieldLabel><SmartNumberInput min={0} value={target.amount} onValueChange={(amount) => onChange({ amount })} /></div><div><FieldLabel>{tr(locale, "unit")}</FieldLabel><UnitSelect value={target.unit} onChange={(unit) => onChange({ unit })} /></div></div>
      <div className="mt-3 grid grid-cols-2 gap-2"><div><FieldLabel>{tr(locale, "recyclerQuality")}</FieldLabel><QualitySelect value={target.recyclerQuality} onChange={(v) => onChange({ recyclerQuality: v as QualityId })} locale={locale} /></div><div><FieldLabel>{tr(locale, "ingredientQuality")}</FieldLabel><QualitySelect value={target.inputQuality} onChange={(v) => { const next=v as QualityId; const order: QualityId[]=["normal","uncommon","rare","epic","legendary"]; onChange({ inputQuality: next, outputQuality: target.outputQuality!=="total"&&order.indexOf(target.outputQuality)<order.indexOf(next)?next:target.outputQuality }); }} locale={locale} /></div></div>
      {qualityMode ? <div className="mt-3 grid grid-cols-2 gap-2"><div><FieldLabel>{tr(locale, "maximumQuality")}</FieldLabel><QualitySelect value={target.maxQuality} onChange={(v) => {
        const next = v as QualityId;
        const order: QualityId[] = ["normal", "uncommon", "rare", "epic", "legendary"];
        onChange({ maxQuality: next, outputQuality: target.outputQuality === "total" || order.indexOf(target.outputQuality) <= order.indexOf(next) ? target.outputQuality : next });
      }} locale={locale} /></div><div><FieldLabel>{tr(locale, "targetQuality")}</FieldLabel><QualitySelect value={target.outputQuality} onChange={(v) => onChange({ outputQuality: v })} locale={locale} includeTotal maxQuality={target.maxQuality} /></div></div> : null}
      <div className="mt-3"><ModuleConfigurator title={tr(locale, "machineModules")} locale={locale} slots={4} machine={recycler} recipe={recycleRecipe} config={target.machineConfig} onChange={(machineConfig) => onChange({ machineConfig })} allowedFamilies={["quality","speed","efficiency"]} autoAllowedFamilies={qualityMode ? ["quality"] : ["speed","efficiency"]} /></div>
      <div className="mt-3 rounded-xl border border-white/8 p-3"><label className="mb-3 flex items-center gap-2 text-xs"><input type="checkbox" checked={target.beaconEnabled} onChange={(e) => onChange({ beaconEnabled: e.target.checked })} />{tr(locale, "beacons")}</label>{qualityMode ? <p className="mb-3 text-[10px] leading-5 text-zinc-500">{tr(locale, "qualitySafeBeacon")}</p> : <div className="mb-3"><FieldLabel detail="max 12">{tr(locale, "activePerMachine")}</FieldLabel><BeaconCountSelect value={target.beaconCount} maximum={12} disabled={!target.beaconEnabled} onChange={(beaconCount)=>onChange({beaconCount})} /></div>}<ModuleConfigurator title={tr(locale, "beaconModules")} locale={locale} slots={qualityMode ? 1 : 2} machine={recycler} recipe={recycleRecipe} beacon config={target.beaconConfig} onChange={(beaconConfig) => onChange({ beaconConfig })} allowedFamilies={["speed","efficiency"]} /></div>
      <label className="mt-3 flex items-center justify-between rounded-lg border border-white/7 bg-[#17191b] p-3 text-xs"><span>{tr(locale, "includeEnergy")}</span><input type="checkbox" checked={energySelection?.includeDirect ?? target.includeEnergy} onChange={(e) => { onChange({ includeEnergy: e.target.checked }); onEnergyToggle(target.id, "includeDirect", e.target.checked); }} /></label>
    </section>
  );
}

function compute(target: Target, qualityMode: boolean) {
  const route = RECYCLING_ROUTE_BY_ID.get(target.routeId)!;
  const modules = resolvedModules(target.machineConfig, 4, recycler, recycleRecipe);
  let beaconModules = resolvedModules(target.beaconConfig, qualityMode ? 1 : 2, recycler, recycleRecipe, true);
  if (qualityMode) beaconModules = [beaconModules[0] ?? null, null];
  const input: RecyclingInput = {
    route, amount: target.amount, unit: target.unit, inputQuality: target.inputQuality,
    maxQuality: target.maxQuality, recyclerQuality: target.recyclerQuality, modules,
    beaconEnabled: target.beaconEnabled, beaconCount: qualityMode ? 1 : target.beaconCount,
    beaconModules, beaconQuality: target.beaconQuality, qualityMode,
    targetOutputId: target.targetOutputId,
    targetQuality: target.outputQuality,
    amountMode: qualityMode ? "target-output" : "input",
  };
  return { route, result: calculateRecycling(input) };
}

export function RecyclingWorkspace({
  locale, qualityMode, onEnergySources, energySelections, onEnergyToggle,
}: { locale: Locale; qualityMode: boolean; onEnergySources: (sources: EnergySourceSelection[]) => void; energySelections: Record<string, EnergySourceSelection>; onEnergyToggle: (id: string, field: "includeDirect" | "includeChain", value: boolean) => void }) {
  const products = qualityMode ? QUALITY_RECYCLING_PRODUCTS : RECYCLING_PRODUCTS;
  const [targets, setTargets] = useState<Target[]>([]);
  const computed = useMemo(() => targets.map((target) => ({ target, ...compute(target, qualityMode) })), [targets, qualityMode]);
  useEffect(() => {
    onEnergySources(computed.map(({ target, route, result }) => ({
      id: target.id, label: localizedName(route.productId, locale, "item"), icon: route.productIcon,
      directKw: result.electricKw, chainKw: 0, includeDirect: target.includeEnergy, includeChain: false,
      mode: qualityMode ? "quality-recycling" : "recycling",
    })));
  }, [computed, locale, onEnergySources, qualityMode]);
  const update = (id: string, patch: Partial<Target>) => setTargets((items) => items.map((item) => item.id === id ? { ...item, ...patch } : item));
  const add = (productId: string) => setTargets((items) => [...items, makeTarget(`${qualityMode ? "qr" : "r"}-${Date.now()}`, qualityMode, productId)]);
  const navigate = (targetId: string, productId: string) => {
    const product = products.find((entry) => entry.id === productId);
    if (product) {
      const route = RECYCLING_ROUTE_BY_ID.get(product.routeIds[0])!;
      update(targetId, {
        productId,
        routeId: product.routeIds[0],
        targetOutputId: route.outputs[0]?.id ?? "",
      });
    }
  };
  const options = products.map((entry) => { const placement=catalogPlacement(entry.id,"item"); return { value:entry.id, label:localizedName(entry.id,locale,"item"), icon:entry.icon, keywords:entry.name, group:placement.group, subgroup:placement.subgroup, subgroupLabel:placement.subgroup?localizedName(placement.subgroup,locale,"subgroup"):undefined }; });
  const groups = (["logistics","production","intermediate-products","space","combat","fluids"] as ItemGroupId[]).filter((id)=>options.some((option)=>option.group===id)).map((id)=>({id,label:groupLabel(id,locale),icon:iconForGroup(id)}));
  return (
    <div className="workspace-grid">
      <aside className="workspace-settings">
        <section className="panel-card"><SectionTitle number="+" title={tr(locale,"currentProducts")} icons={[recycler.icon]} /><SearchPicker value="" options={options} groups={groups} onChange={add} placeholder={tr(locale,"selectProduct")} searchPlaceholder={tr(locale,"searchProducts")} emptyText={tr(locale,"noMatch")} /></section>
        {targets.map((target) => <RecyclingSettings key={target.id} target={target} qualityMode={qualityMode} locale={locale} onChange={(patch) => update(target.id, patch)} onRemove={() => setTargets((items) => items.filter((item) => item.id !== target.id))} canRemove energySelection={energySelections[target.id]} onEnergyToggle={onEnergyToggle} />)}
      </aside>
      <section className="workspace-results">
        {!computed.length ? <div className="panel-card flex min-h-56 flex-col items-center justify-center text-center"><Plus className="mb-3 size-8 text-[#f7a72d]" /><h2 className="text-lg font-semibold">{tr(locale,"noProductSelected")}</h2></div> : null}
        {computed.map(({ target, route, result }) => {
          const downstream = downstreamProducts(`item:${route.productId}`).filter(
            (entry) => products.some((candidate) => candidate.id === entry.id),
          );
          const downstreamOptions = downstream.map((entry) => ({
            value: entry.id,
            label: localizedName(entry.id, locale, "item"),
            icon: entry.icon,
            keywords: `${entry.name} ${entry.id}`,
            group: entry.group,
            subgroup: entry.subgroup,
            subgroupLabel: entry.subgroup ? localizedName(entry.subgroup, locale, "subgroup") : undefined,
          }));
          const downstreamGroups = (["logistics","production","intermediate-products","space","combat","fluids"] as ItemGroupId[])
            .filter((id) => downstreamOptions.some((option) => option.group === id))
            .map((id) => ({ id, label: groupLabel(id, locale), icon: iconForGroup(id) }));
          return (
          <article key={target.id} className="space-y-4 rounded-2xl border border-white/9 bg-[#111315] p-5">
            <div className="result-hero"><div className="min-w-0 flex-1"><p className="eyebrow">{qualityMode ? tr(locale, "qualityRecycling") : tr(locale, "recycling")}</p><SearchPicker value={route.productId} options={downstreamOptions} groups={downstreamGroups} triggerOption={{ value: route.productId, label: localizedName(route.productId, locale, "item"), icon: route.productIcon, group: catalogPlacement(route.productId, "item").group }} onChange={(id)=>navigate(target.id,id)} placeholder={tr(locale,"chooseNextProduct")} searchPlaceholder={tr(locale,"downstreamProducts")} emptyText={tr(locale,"noMatch")} triggerClassName="mt-1 h-14 max-w-xl border-[#69c5df]/30 bg-[#69c5df]/6 text-2xl font-semibold" /><p className="mt-1 text-xs text-zinc-500">{recyclingRouteLabel(route, locale)}</p></div></div>
            <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4"><MetricCard icon={<Factory className="size-4" />} label={tr(locale, "machinesRequired")} value={String(result.recyclersToBuild)} detail={`${formatNumber(result.theoreticalRecyclers, locale)} ${tr(locale, "theoretical")}`} /><MetricCard icon={<Gauge className="size-4" />} label={tr(locale, "throughput")} value={`${formatNumber(result.throughputPerRecycler, locale)}/s`} detail={`${formatNumber(result.recyclerTimeSeconds, locale)} s / item`} /><MetricCard icon={qualityMode ? <Sparkles className="size-4" /> : <Recycle className="size-4" />} label={qualityMode ? tr(locale, "quality") : tr(locale, "utilization")} value={qualityMode ? `${formatNumber(result.qualityChance * 100, locale)}%` : `${formatNumber(result.utilization * 100, locale)}%`} /><MetricCard icon={<Zap className="size-4" />} label={tr(locale, "power")} value={formatPower(result.electricKw, locale)} /></div>
            {qualityMode ? <div className="notice-info"><span><strong>{formatNumber(result.targetOutputPerSecond*(target.unit==="s"?1:target.unit==="min"?60:3600),locale)}{target.unit==="s"?"/s":target.unit==="min"?"/min":"/h"} · {localizedName(target.targetOutputId,locale,"item")} · {target.outputQuality==="total"?tr(locale,"allQualities"):localizedName(target.outputQuality,locale,"quality")}</strong><br />{tr(locale,"recycleProduct")}: {formatNumber(result.inputPerSecond*(target.unit==="s"?1:target.unit==="min"?60:3600),locale)}{target.unit==="s"?"/s":target.unit==="min"?"/min":"/h"}</span></div> : null}
            <div className={`grid gap-3 ${result.lostFluids.length ? "lg:grid-cols-2" : ""}`}><div><h3 className="mb-2 text-sm font-semibold">{tr(locale, "expectedOutputs")}</h3><div className="space-y-2">{result.outputs.map((flow) => <RecyclingOutputPicker key={flow.id} flow={flow} target={target} qualityMode={qualityMode} locale={locale} products={products} navigate={navigate} />)}</div></div>{result.lostFluids.length ? <div><h3 className="mb-2 text-sm font-semibold text-[#e5a12b]">{tr(locale, "lostFluids")}</h3><div className="space-y-2">{result.lostFluids.map((flow) => <MaterialRow key={flow.id} flow={flow} unit={target.unit} locale={locale} />)}</div></div> : null}</div>
            {!qualityMode && !result.lostFluids.length ? <div className="notice-info">{tr(locale, "solidRecycleReturn")}</div> : null}
            {qualityMode ? <p className="quality-fluid-footnote">{tr(locale, "noQualityFluids")}</p> : null}
            {qualityMode ? <div className="notice-warning"><AlertTriangle className="size-4 shrink-0" />{tr(locale,"expectedOutputs")} · {tr(locale,"theoretical")}</div> : null}
            <GeometryDesign layout={result.beaconLayout} machine={recycler} locale={locale} />
          </article>
          );
        })}
      </section>
    </div>
  );
}
