/* ============================================================
   store.jsx — ข้อมูล + state กลางของระบบ (เชื่อม API จริงบน Cloudflare D1)
   • แค็ตตาล็อก (หมวด/สินค้า/โซน/ช่อง) เป็นข้อมูลคงที่ในฝั่ง client
   • ข้อมูลที่เปลี่ยนแปลง (สต๊อก/การเคลื่อนไหว/ใบเสนอราคา/รูป/บริษัท) โหลดจาก D1
   ============================================================ */
const { createContext, useContext, useState, useCallback, useMemo, useEffect } = React;

/* ---------- หมวดวัสดุ ---------- */
const CATEGORIES = [
  { id: "steel",  name: "เหล็ก / โครงสร้าง", color: "#475569", soft: "#eef1f6" },
  { id: "cement", name: "ปูน / หิน / ทราย",  color: "#9a7b4f", soft: "#f5efe6" },
  { id: "paint",  name: "สี / เคมีภัณฑ์",    color: "#2563eb", soft: "#eaf1ff" },
  { id: "pipe",   name: "ท่อ / ประปา",       color: "#0f9d58", soft: "#e6f6ee" },
  { id: "elec",   name: "ไฟฟ้า",             color: "#d98a04", soft: "#fdf3e2" },
  { id: "hw",     name: "เครื่องมือ / ฮาร์ดแวร์", color: "#7c3aed", soft: "#f1ebfe" },
];

/* ---------- สินค้า (แค็ตตาล็อกคงที่ — ตรงกับ seed ใน D1) ---------- */
const ITEMS = [
  { sku: "ST-RB6",   name: "เหล็กเส้นกลม RB6 SR24",        cat: "steel",  unit: "เส้น",  price: 78,    reorder: 200 },
  { sku: "ST-DB12",  name: "เหล็กข้ออ้อย DB12 SD40",        cat: "steel",  unit: "เส้น",  price: 245,   reorder: 150 },
  { sku: "ST-DB16",  name: "เหล็กข้ออ้อย DB16 SD40",        cat: "steel",  unit: "เส้น",  price: 432,   reorder: 120 },
  { sku: "ST-HB150", name: "เหล็ก H-Beam 150×150×6 ม.",     cat: "steel",  unit: "เส้น",  price: 3850,  reorder: 20  },
  { sku: "ST-WM4",   name: "ตะแกรงไวร์เมช 4 มม. (2×2 ม.)",  cat: "steel",  unit: "แผ่น",  price: 168,   reorder: 80  },
  { sku: "CM-PC50",  name: "ปูนซีเมนต์ปอร์ตแลนด์ 50 กก.",   cat: "cement", unit: "ถุง",   price: 175,   reorder: 300 },
  { sku: "CM-MT40",  name: "ปูนก่อสำเร็จ 40 กก.",          cat: "cement", unit: "ถุง",   price: 92,    reorder: 200 },
  { sku: "CM-RK",    name: "หินคลุก",                       cat: "cement", unit: "ลบ.ม.", price: 480,   reorder: 30  },
  { sku: "CM-SD",    name: "ทรายหยาบ",                      cat: "cement", unit: "ลบ.ม.", price: 420,   reorder: 30  },
  { sku: "CM-BR",    name: "อิฐมอญ มือ 1",                  cat: "cement", unit: "ก้อน",  price: 2.8,   reorder: 5000 },
  { sku: "PT-AC18",  name: "สีน้ำอะครีลิคภายนอก 18.925 ล.", cat: "paint",  unit: "ถัง",   price: 2350,  reorder: 25  },
  { sku: "PT-PR3.5", name: "สีรองพื้นปูนเก่า 3.5 ล.",       cat: "paint",  unit: "แกลลอน", price: 540,  reorder: 40  },
  { sku: "PT-TN",    name: "ทินเนอร์ AAA 3.785 ล.",         cat: "paint",  unit: "แกลลอน", price: 215,  reorder: 50  },
  { sku: "PP-PVC4",  name: 'ท่อ PVC 4" ชั้น 8.5',           cat: "pipe",   unit: "เส้น",  price: 285,   reorder: 60  },
  { sku: "PP-EL4",   name: 'ข้องอ PVC 4" 90°',             cat: "pipe",   unit: "ตัว",   price: 38,    reorder: 100 },
  { sku: "PP-PPR",   name: 'ท่อ PPR 1/2" PN20',            cat: "pipe",   unit: "เส้น",  price: 95,    reorder: 80  },
  { sku: "EL-THW25", name: "สายไฟ THW 2.5 sq.mm. (100 ม.)", cat: "elec",  unit: "ม้วน",  price: 1180,  reorder: 30  },
  { sku: "EL-CD20",  name: "ท่อร้อยสายไฟ PVC 20 มม.",      cat: "elec",   unit: "เส้น",  price: 42,    reorder: 100 },
  { sku: "HW-SCR",   name: "สกรูเกลียวปล่อย 1 นิ้ว (กล่อง)", cat: "hw",    unit: "กล่อง", price: 65,    reorder: 60  },
  { sku: "HW-SIL",   name: "ซิลิโคนยาแนวใส",                cat: "hw",     unit: "หลอด",  price: 78,    reorder: 120 },
];

/* ---------- โลเคชั่น (โซน × ช่อง) ---------- */
const ZONES = [
  { id: "A", name: "โซน A — เหล็ก/โครงสร้าง", cols: 4, rows: 2 },
  { id: "B", name: "โซน B — ปูน/หิน/ทราย",    cols: 4, rows: 2 },
  { id: "C", name: "โซน C — สี/เคมี/ฮาร์ดแวร์", cols: 4, rows: 2 },
  { id: "D", name: "โซน D — ท่อ/ไฟฟ้า",       cols: 4, rows: 2 },
];
const BIN_CAP = 1200;

function buildLocations() {
  const locs = [];
  ZONES.forEach(z => {
    for (let i = 1; i <= z.cols * z.rows; i++) {
      locs.push({ code: `${z.id}-${String(i).padStart(2, "0")}`, zone: z.id });
    }
  });
  return locs;
}

/* ---------- ผู้ติดต่อ ---------- */
const SUPPLIERS = ["บ.สยามสตีล จำกัด", "ทีพีไอ โพลีน", "บ.ทีโอเอ เพ้นท์", "บ.ท่อน้ำไทย", "ยูไนเต็ด ฮาร์ดแวร์"];
const CUSTOMERS = ["ไซต์: คอนโดริเวอร์เฮาส์", "ไซต์: บ้านคุณสมชาย", "หจก.รุ่งเรืองก่อสร้าง", "ไซต์: อาคารพาณิชย์ ซ.5", "ช่างประจำร้าน"];
const USERS = ["สมหญิง (สโตร์)", "ธนา (สโตร์)", "วิภา (จัดซื้อ)"];

/* ปริมาณเคลื่อนไหว 7 วัน (กราฟ dashboard — ข้อมูลประกอบ) */
const FLOW_7D = [
  { d: "28 พ.ค.", in: 1240, out: 980 },
  { d: "29 พ.ค.", in: 0,    out: 1340 },
  { d: "30 พ.ค.", in: 940,  out: 1620 },
  { d: "31 พ.ค.", in: 520,  out: 1200 },
  { d: "1 มิ.ย.", in: 660,  out: 410 },
  { d: "2 มิ.ย.", in: 1300, out: 880 },
  { d: "3 มิ.ย.", in: 920,  out: 760 },
];

/* ===================== helpers ===================== */
const fmt = (n) => new Intl.NumberFormat("th-TH").format(Math.round(n));
const fmtMoney = (n) => new Intl.NumberFormat("th-TH", { maximumFractionDigits: 0 }).format(Math.round(n));
const fmtMoneyK = (n) => {
  if (n >= 1e6) return (n / 1e6).toFixed(2) + " ล้าน";
  if (n >= 1e3) return fmt(n);
  return fmt(n);
};
const catOf = (sku) => CATEGORIES.find(c => c.id === (ITEMS.find(i => i.sku === sku) || {}).cat) || CATEGORIES[0];
const itemOf = (sku) => ITEMS.find(i => i.sku === sku);
const fmtDate = (iso) => {
  const dt = new Date(iso);
  const months = ["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."];
  return `${dt.getDate()} ${months[dt.getMonth()]} ${(dt.getFullYear()+543) % 100} · ${String(dt.getHours()).padStart(2,"0")}:${String(dt.getMinutes()).padStart(2,"0")}`;
};

/* ===================== Store context ===================== */
const Store = createContext(null);
const useStore = () => useContext(Store);

/* หน้าจอโหลด/ผิดพลาด ระหว่างดึงข้อมูลจาก D1 */
function LoadScreen({ error, onRetry, onLogout }) {
  return (
    <div style={{ height: "100%", display: "grid", placeItems: "center", background: "var(--bg)" }}>
      <div style={{ textAlign: "center" }}>
        {error ? (
          <React.Fragment>
            <div style={{ width: 60, height: 60, borderRadius: 16, background: "var(--red-soft)", color: "var(--red)", display: "grid", placeItems: "center", margin: "0 auto 16px" }}><Icons.alert size={28}/></div>
            <div style={{ fontWeight: 600, fontSize: 16 }}>โหลดข้อมูลจากฐานข้อมูลไม่สำเร็จ</div>
            <div style={{ color: "var(--muted)", fontSize: 13.5, margin: "6px 0 18px" }}>ตรวจสอบการเชื่อมต่อ หรือเข้าสู่ระบบใหม่อีกครั้ง</div>
            <div style={{ display: "flex", gap: 10, justifyContent: "center" }}>
              <button className="btn btn-ghost" onClick={onLogout}>ออกจากระบบ</button>
              <button className="btn btn-primary" onClick={onRetry}><Icons.refresh size={16}/>ลองใหม่</button>
            </div>
          </React.Fragment>
        ) : (
          <React.Fragment>
            <div className="spin" style={{ width: 44, height: 44, borderRadius: "50%", border: "3px solid var(--line)", borderTopColor: "var(--primary-600)", margin: "0 auto 16px" }}></div>
            <div style={{ color: "var(--muted)", fontSize: 14 }}>กำลังโหลดข้อมูลจากคลัง…</div>
          </React.Fragment>
        )}
      </div>
    </div>
  );
}

function StoreProvider({ children }) {
  const { user: currentUser, logout } = useAuth();
  const [stock, setStock] = useState({});
  const [movements, setMovements] = useState([]);
  const [quotes, setQuotes] = useState([]);
  const [images, setImages] = useState({});
  const [company, setCompanyState] = useState(null);
  const [toasts, setToasts] = useState([]);
  const [loaded, setLoaded] = useState(false);
  const [loadErr, setLoadErr] = useState(false);
  const locations = useMemo(buildLocations, []);

  const pushToast = useCallback((msg, kind = "ok") => {
    const id = Math.random().toString(36).slice(2);
    setToasts(t => [...t, { id, msg, kind }]);
    setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 3200);
  }, []);

  /* ---- โหลดข้อมูลทั้งหมดจาก D1 ---- */
  const loadState = useCallback(async () => {
    setLoadErr(false);
    const r = await API.get("state");
    if (r.status === 401) { logout(); return; }
    if (!r.ok) { setLoadErr(true); setLoaded(true); return; }
    setStock(r.data.stock || {});
    setMovements(r.data.movements || []);
    setQuotes(r.data.quotes || []);
    setImages(r.data.images || {});
    setCompanyState(r.data.company || {});
    setLoadErr(false);
    setLoaded(true);
  }, [logout]);

  useEffect(() => { loadState(); }, [loadState]);

  /* ---- helper: เลขเอกสารถัดไป (แสดงผล — เซิร์ฟเวอร์เป็นผู้กำหนดจริง) ---- */
  const nextDoc = useCallback((type) => {
    const prefix = type === "in" ? "RC" : "IS";
    const n = movements.filter(m => m.id.startsWith(prefix)).length + (type === "in" ? 19 : 42);
    return `${prefix}-2406-${String(n).padStart(3, "0")}`;
  }, [movements]);

  const nextQuoteNo = useCallback(() => `QT-2606-${String(quotes.length + 1).padStart(3, "0")}`, [quotes]);

  /* รายชื่อผู้บันทึก = ผู้ที่ล็อกอิน + รายชื่อตั้งต้น */
  const userList = useMemo(() => {
    const base = [...USERS];
    if (currentUser && !base.includes(currentUser.name)) base.unshift(currentUser.name);
    return base;
  }, [currentUser]);

  /* รวมคงเหลือทั้งหมดต่อ sku */
  const stockBySku = useMemo(() => {
    const m = {};
    ITEMS.forEach(i => (m[i.sku] = 0));
    Object.values(stock).forEach(bin => {
      Object.entries(bin).forEach(([sku, q]) => { m[sku] = (m[sku] || 0) + q; });
    });
    return m;
  }, [stock]);

  const locationsOf = useCallback((sku) => {
    const out = [];
    Object.entries(stock).forEach(([code, bin]) => { if (bin[sku] > 0) out.push({ code, qty: bin[sku] }); });
    return out.sort((a, b) => b.qty - a.qty);
  }, [stock]);

  const binSummary = useCallback((code) => {
    const bin = stock[code] || {};
    const entries = Object.entries(bin).filter(([, q]) => q > 0);
    const units = entries.reduce((s, [, q]) => s + q, 0);
    return { entries, units, skuCount: entries.length };
  }, [stock]);

  const totalValue = useMemo(() =>
    ITEMS.reduce((s, i) => s + (stockBySku[i.sku] || 0) * i.price, 0)
  , [stockBySku]);

  const lowStock = useMemo(() =>
    ITEMS.map(i => ({ ...i, qty: stockBySku[i.sku] || 0 }))
         .filter(i => i.qty <= i.reorder)
         .sort((a, b) => (a.qty / a.reorder) - (b.qty / b.reorder))
  , [stockBySku]);

  /* ---- mutations (เรียก API → อัปเดต state) ---- */
  const receive = useCallback(async ({ party, user, note, lines }) => {
    const r = await API.post("receive", { party, user, note, lines });
    if (!r.ok) { pushToast(r.data.error || "บันทึกไม่สำเร็จ", "warn"); return null; }
    setStock(r.data.stock || {});
    setMovements(m => [r.data.movement, ...m]);
    pushToast(`บันทึกรับเข้า ${r.data.id} สำเร็จ · ${lines.length} รายการ`);
    return r.data.id;
  }, [pushToast]);

  const issue = useCallback(async ({ party, user, note, lines }) => {
    const r = await API.post("issue", { party, user, note, lines });
    if (!r.ok) { pushToast(r.data.error || "บันทึกไม่สำเร็จ", "warn"); return null; }
    setStock(r.data.stock || {});
    setMovements(m => [r.data.movement, ...m]);
    pushToast(`บันทึกจ่ายออก ${r.data.id} สำเร็จ · ${lines.length} รายการ`);
    return r.data.id;
  }, [pushToast]);

  /* รูปสินค้า — อัปเดตทันที (optimistic) แล้วบันทึกขึ้นเซิร์ฟเวอร์ */
  const setImage = useCallback((sku, url) => {
    setImages(prev => { const n = { ...prev }; if (url) n[sku] = url; else delete n[sku]; return n; });
    API.post("item-image", { sku, image: url || null }).then(r => {
      if (!r.ok) pushToast("บันทึกรูปขึ้นเซิร์ฟเวอร์ไม่สำเร็จ", "warn");
    });
  }, [pushToast]);

  const setCompany = useCallback((patch) => {
    setCompanyState(prev => ({ ...prev, ...patch }));
    API.post("company", patch).then(r => { if (!r.ok) pushToast("บันทึกข้อมูลบริษัทไม่สำเร็จ", "warn"); });
  }, [pushToast]);

  const addQuote = useCallback(async (q) => {
    const r = await API.post("quotes", q);
    if (!r.ok) { pushToast(r.data.error || "บันทึกใบเสนอราคาไม่สำเร็จ", "warn"); return null; }
    setQuotes(prev => [r.data.quote, ...prev]);
    return r.data.quote;
  }, [pushToast]);

  const deleteQuote = useCallback((id) => {
    setQuotes(prev => prev.filter(q => q.id !== id));
    API.del("quotes/" + encodeURIComponent(id)).then(r => { if (!r.ok) pushToast("ลบใบเสนอราคาไม่สำเร็จ", "warn"); });
  }, [pushToast]);

  if (!loaded || loadErr) {
    return <LoadScreen error={loadErr} onRetry={() => { setLoaded(false); loadState(); }} onLogout={logout} />;
  }

  const value = {
    CATEGORIES, ITEMS, ZONES, BIN_CAP, SUPPLIERS, CUSTOMERS, USERS: userList, FLOW_7D,
    stock, movements, locations, toasts, images, currentUser, company, quotes,
    stockBySku, locationsOf, binSummary, totalValue, lowStock,
    receive, issue, pushToast, nextDoc, setImage, setCompany, addQuote, deleteQuote, nextQuoteNo,
    fmt, fmtMoney, fmtMoneyK, catOf, itemOf, fmtDate,
  };
  return <Store.Provider value={value}>{children}</Store.Provider>;
}

Object.assign(window, { StoreProvider, useStore, CATEGORIES, ITEMS, ZONES, fmt, fmtMoney, fmtMoneyK, catOf, itemOf, fmtDate });
