"use client";

import { useEffect, useMemo, useState } from "react";

import { useLocale } from "@/components/providers/locale-provider";
import { EmptyState, StatCard } from "@/components/shared/ops-primitives";
import type { Buyer } from "@/features/buyers/types/buyer";
import { formatCurrencyAmount, formatDecimal, formatQuantity } from "@/lib/formatters";
import type { ApiErrorResponse } from "@/types/api";
import type { LotListItem } from "@/types/lot";

type AllocationRow = {
  lot_id: string;
  lot_code: string;
  warehouse: string;
  grade: string;
  available_qty: number;
  allocated_qty: number;
  unit_code: string;
  unit_cost: number;
  line_cost: number;
  aging_days: number;
};

type SalesAllocationClientProps = {
  currencyCode: string;
};

export function SalesAllocationClient({ currencyCode }: SalesAllocationClientProps) {
  const { locale } = useLocale();
  const [lots, setLots] = useState<LotListItem[]>([]);
  const [buyers, setBuyers] = useState<Buyer[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [buyerId, setBuyerId] = useState("");
  const [gradeFilter, setGradeFilter] = useState("ALL");
  const [requestedQty, setRequestedQty] = useState("0");
  const [sellingPrice, setSellingPrice] = useState("0");

  async function loadData() {
    setLoading(true);
    setError(null);
    try {
      const [lotsResponse, buyersResponse] = await Promise.all([
        fetch("/api/v1/lots", { cache: "no-store" }),
        fetch("/api/v1/buyers", { cache: "no-store" })
      ]);

      const lotsPayload = (await lotsResponse.json()) as { data: LotListItem[] } | ApiErrorResponse;
      const buyersPayload = (await buyersResponse.json()) as { data: Buyer[] } | ApiErrorResponse;

      if (!lotsResponse.ok || !("data" in lotsPayload)) {
        throw new Error("message" in lotsPayload ? lotsPayload.message : locale === "id" ? "Gagal memuat data lot." : "Failed to load lot data.");
      }
      if (!buyersResponse.ok || !("data" in buyersPayload)) {
        throw new Error("message" in buyersPayload ? buyersPayload.message : locale === "id" ? "Failed to load buyer data." : "Failed to load buyer data.");
      }

      setLots(lotsPayload.data);
      setBuyers(buyersPayload.data.filter((buyer) => buyer.status === "ACTIVE"));
    } catch (err) {
      setError(err instanceof Error ? err.message : locale === "id" ? "Gagal memuat data penjualan." : "Failed to load sales data.");
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void loadData();
  }, []);

  const gradeOptions = useMemo(
    () =>
      [
        "ALL",
        ...new Set(lots.filter((lot) => lot.status === "ACTIVE").map((lot) => lot.grade))
      ],
    [lots]
  );

  const demandQty = Number(requestedQty) || 0;
  const sellingPriceValue = Number(sellingPrice) || 0;

  const candidateLots = useMemo(() => {
    return lots
      .filter((lot) => {
        if (lot.status !== "ACTIVE") return false;
        if (lot.available_qty <= 0) return false;
        if (gradeFilter !== "ALL" && lot.grade !== gradeFilter) return false;
        return true;
      })
      .sort((a, b) => b.aging_days - a.aging_days);
  }, [gradeFilter, lots]);

  const allocation = useMemo(() => {
    let remaining = demandQty;
    const rows: AllocationRow[] = [];

    candidateLots.forEach((lot) => {
      if (remaining <= 0) return;
      const allocatedQty = Math.min(lot.available_qty, remaining);
      if (allocatedQty <= 0) return;

      rows.push({
        lot_id: lot.id,
        lot_code: lot.lot_code,
        warehouse: lot.warehouse,
        grade: lot.grade,
        available_qty: lot.available_qty,
        allocated_qty: allocatedQty,
        unit_code: lot.unit_code,
        unit_cost: lot.unit_cost,
        line_cost: allocatedQty * lot.unit_cost,
        aging_days: lot.aging_days
      });

      remaining -= allocatedQty;
    });

    const allocatedQty = rows.reduce((sum, row) => sum + row.allocated_qty, 0);
    const estimatedCogs = rows.reduce((sum, row) => sum + row.line_cost, 0);
    const estimatedRevenue = allocatedQty * sellingPriceValue;

    return {
      rows,
      allocated_qty: allocatedQty,
      shortfall_qty: Math.max(0, demandQty - allocatedQty),
      estimated_cogs: estimatedCogs,
      estimated_revenue: estimatedRevenue,
      gross_margin: estimatedRevenue - estimatedCogs
    };
  }, [candidateLots, demandQty, sellingPriceValue]);

  const selectedBuyer = buyers.find((buyer) => buyer.id === buyerId) ?? null;
  const allocationUnitCode = useMemo(() => {
    const unitCodes = Array.from(new Set(candidateLots.map((lot) => lot.unit_code).filter(Boolean)));
    return unitCodes.length === 1 ? unitCodes[0] : null;
  }, [candidateLots]);

  return (
    <section className="space-y-6">
      <div className="grid gap-6 xl:grid-cols-[1.15fr_0.85fr]">
        <div className="ops-card p-6">
          <p className="ops-overline">Commercial planning</p>
          <h2 className="mt-2 text-[32px] font-semibold tracking-tight text-ink">Sales allocation workspace</h2>
          <p className="mt-3 max-w-3xl text-[14px] leading-7 text-slate-600">
            Halaman ini menggantikan placeholder dengan allocation preview yang sudah memakai stok lot nyata.
            Hasilnya belum disimpan sebagai transaksi sales, tetapi sudah cukup untuk validasi demand,
            kesiapan stok, dan estimasi margin.
          </p>

          <div className="mt-6 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            <label>
              <span className="ops-label">Buyer</span>
              <select value={buyerId} onChange={(event) => setBuyerId(event.target.value)} className="ops-select">
                <option value="">{locale === "id" ? "Pilih pembeli aktif" : "Choose active buyer"}</option>
                {buyers.map((buyer) => (
                  <option key={buyer.id} value={buyer.id}>
                    {buyer.code} - {buyer.name}
                  </option>
                ))}
              </select>
            </label>
            <label>
              <span className="ops-label">Grade</span>
              <select value={gradeFilter} onChange={(event) => setGradeFilter(event.target.value)} className="ops-select">
                {gradeOptions.map((option) => (
                  <option key={option} value={option}>
                    {option === "ALL" ? (locale === "id" ? "Semua grade" : "All grades") : option}
                  </option>
                ))}
              </select>
            </label>
            <button type="button" onClick={() => void loadData()} className="ops-btn-secondary self-end" disabled={loading}>
              Refresh stok
            </button>
          </div>

          <div className="mt-4 grid gap-4 md:grid-cols-2">
            <label>
              <span className="ops-label">Requested qty</span>
              <input
                value={requestedQty}
                onChange={(event) => setRequestedQty(event.target.value)}
                inputMode="decimal"
                className="ops-input"
                placeholder="0"
              />
            </label>
            <label>
              <span className="ops-label">Selling price / unit</span>
              <input
                value={sellingPrice}
                onChange={(event) => setSellingPrice(event.target.value)}
                inputMode="decimal"
                className="ops-input"
                placeholder="0"
              />
            </label>
          </div>

          {error ? (
            <div className="mt-5 rounded border border-ember/30 bg-ember/10 px-4 py-3 text-sm text-ember">{error}</div>
          ) : null}
        </div>

        <div className="ops-card-dark p-6">
          <p className="text-[11px] font-bold uppercase tracking-[0.05em] text-white/70">Allocation rule</p>
          <div className="mt-4 space-y-3 text-[13px] leading-6 text-white/85">
            <div className="rounded border border-white/15 bg-white/5 px-4 py-3">
              Kandidat diambil dari lot `ACTIVE` dengan `available_qty` di atas nol.
            </div>
            <div className="rounded border border-white/15 bg-white/5 px-4 py-3">
              Urutan alokasi memakai lot dengan aging tertinggi lebih dulu sebagai pendekatan FIFO operasional.
            </div>
            <div className="rounded border border-white/15 bg-white/5 px-4 py-3">
              Preview ini belum membuat `sales order`, jadi aman dipakai untuk simulasi demand.
            </div>
          </div>
        </div>
      </div>

      <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-5">
        <StatCard
          label={locale === "id" ? "Pembeli" : "Buyer"}
          value={selectedBuyer?.code ?? "-"}
          hint={selectedBuyer?.name ?? (locale === "id" ? "Pilih pembeli untuk simulasi" : "Choose a buyer for simulation")}
        />
        <StatCard label={locale === "id" ? "Lot kandidat" : "Candidate lots"} value={String(candidateLots.length)} hint={locale === "id" ? "Lot yang lolos filter" : "Lots that passed the filter"} />
        <StatCard label={locale === "id" ? "Qty teralokasi" : "Allocated qty"} value={formatQuantity(allocation.allocated_qty, locale, allocationUnitCode)} hint={allocationUnitCode ? (locale === "id" ? "Qty yang berhasil dipenuhi" : "Fulfilled qty") : (locale === "id" ? "Qty yang berhasil dipenuhi · mixed units" : "Fulfilled qty · mixed units")} tone="teal" />
        <StatCard label={locale === "id" ? "Kekurangan" : "Shortfall"} value={formatQuantity(allocation.shortfall_qty, locale, allocationUnitCode)} hint={allocationUnitCode ? (locale === "id" ? "Qty yang masih kurang" : "Remaining shortfall") : (locale === "id" ? "Qty yang masih kurang · mixed units" : "Remaining shortfall · mixed units")} tone={allocation.shortfall_qty > 0 ? "danger" : "default"} />
        <StatCard label={locale === "id" ? "Margin kotor" : "Gross margin"} value={formatCurrencyAmount(allocation.gross_margin, locale, currencyCode, 0)} hint={locale === "id" ? "Pendapatan dikurangi estimasi HPP" : "Revenue minus estimated COGS"} />
      </div>

      <div className="grid gap-6 lg:grid-cols-[1.05fr_0.95fr]">
        <div className="ops-table-shell">
          <div className="ops-section-head">
            <div>
              <p className="ops-title">{locale === "id" ? "Saran alokasi" : "Suggested allocation"}</p>
              <p className="ops-copy">{locale === "id" ? "Preview alokasi lot untuk memenuhi qty permintaan saat ini." : "Preview lot allocation to fulfill the current requested qty."}</p>
            </div>
            <div className="ops-chip-muted">{allocation.rows.length} {locale === "id" ? "lot terpakai" : "lots used"}</div>
          </div>

          {loading ? (
            <div className="px-6 py-8 text-sm text-slate-500">{locale === "id" ? "Memuat data perencanaan penjualan..." : "Loading sales planning data..."}</div>
          ) : demandQty <= 0 ? (
            <EmptyState
              title={locale === "id" ? "Masukkan qty permintaan" : "Enter requested qty"}
              copy={locale === "id" ? "Setelah qty diisi, sistem akan menghitung saran alokasi dari lot aktif." : "After qty is filled in, the system will calculate suggested allocations from active lots."}
            />
          ) : allocation.rows.length === 0 ? (
            <EmptyState
              title="Tidak ada lot yang cocok"
              copy="Periksa filter grade atau pastikan stok aktif masih tersedia."
            />
          ) : (
            <div className="overflow-x-auto">
              <table className="ops-table">
                <thead>
                  <tr>
                    <th>Lot Code</th>
                    <th>Warehouse</th>
                    <th>Grade</th>
                    <th>Available Qty</th>
                    <th>Allocated Qty</th>
                    <th>Unit Cost</th>
                    <th>Line Cost</th>
                    <th>Aging</th>
                  </tr>
                </thead>
                <tbody>
                  {allocation.rows.map((row) => (
                    <tr key={row.lot_id}>
                      <td className="font-medium text-ink">{row.lot_code}</td>
                      <td>{row.warehouse}</td>
                      <td>{row.grade}</td>
                      <td>{formatQuantity(row.available_qty, "id", row.unit_code)}</td>
                      <td>{formatQuantity(row.allocated_qty, "id", row.unit_code)}</td>
                      <td>{formatCurrencyAmount(row.unit_cost, "id", currencyCode, 0)}</td>
                      <td>{formatCurrencyAmount(row.line_cost, "id", currencyCode, 0)}</td>
                      <td>{row.aging_days} hari</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>

        <div className="space-y-6">
          <div className="ops-card p-6">
            <p className="ops-title">Commercial snapshot</p>
            <div className="mt-4 space-y-3 text-[13px] text-slate-600">
              <div className="flex items-center justify-between gap-4 rounded border border-line/70 bg-slate-50/70 px-4 py-3">
                <span>Requested qty</span>
                <strong className="text-ink">{formatQuantity(demandQty, "id", allocationUnitCode)}</strong>
              </div>
              <div className="flex items-center justify-between gap-4 rounded border border-line/70 bg-slate-50/70 px-4 py-3">
                <span>Estimated revenue</span>
                <strong className="text-ink">{formatCurrencyAmount(allocation.estimated_revenue, "id", currencyCode, 0)}</strong>
              </div>
              <div className="flex items-center justify-between gap-4 rounded border border-line/70 bg-slate-50/70 px-4 py-3">
                <span>Estimated COGS</span>
                <strong className="text-ink">{formatCurrencyAmount(allocation.estimated_cogs, "id", currencyCode, 0)}</strong>
              </div>
              <div className="flex items-center justify-between gap-4 rounded border border-line/70 bg-slate-50/70 px-4 py-3">
                <span>Margin / unit allocated</span>
                <strong className="text-ink">
                  {allocation.allocated_qty > 0
                    ? formatCurrencyAmount(allocation.gross_margin / allocation.allocated_qty, "id", currencyCode, 0)
                    : formatCurrencyAmount(0, "id", currencyCode, 0)}
                </strong>
              </div>
            </div>
          </div>

          <div className="ops-note">
            Modul ini sengaja diposisikan sebagai tahap sebelum backend `sales order` dibuat.
            Dengan begitu, tim sudah bisa memvalidasi logika stok, kesiapan supply, dan ekspektasi margin dari data riil.
          </div>
        </div>
      </div>
    </section>
  );
}
