// Shared store — single source of truth, persisted to localStorage.
// Pub/sub so any component re-renders when state changes.

const STORAGE_KEY = "yjmall_state_v3";

const fmtTHB = (n) => "฿" + Math.round(n).toLocaleString("th-TH");
const fmtNum = (n) => Math.round(n).toLocaleString("th-TH");
const fmtDate = (ts) => {
  const d = new Date(ts);
  return d.toLocaleDateString("th-TH", { day: "2-digit", month: "short", year: "2-digit" });
};
const fmtTime = (ts) => {
  const d = new Date(ts);
  return d.toLocaleTimeString("th-TH", { hour: "2-digit", minute: "2-digit" });
};
const fmtRelTime = (ts) => {
  const diff = (Date.now() - ts) / 1000;
  if (diff < 60) return Math.floor(diff) + " วินาทีที่แล้ว";
  if (diff < 3600) return Math.floor(diff / 60) + " นาทีที่แล้ว";
  if (diff < 86400) return Math.floor(diff / 3600) + " ชม.ที่แล้ว";
  return Math.floor(diff / 86400) + " วันที่แล้ว";
};
const uid = (p = "id") => p + "_" + Math.random().toString(36).slice(2, 9);
const clamp = (n, a, b) => Math.max(a, Math.min(b, n));

// === Seed data ===
function makeSeed() {
  const now = Date.now();
  const day = 86400000;

  const brands = [
    { id: "b1", name: "Glow Beauty", gp: 60, status: "active", category: "ความงาม", bankAcc: "KTB 123-4-56789", regDoc: "ภพ.20 / 2566", joined: now - 120 * day, isHouse: false },
    { id: "b2", name: "Vita Plus", gp: 50, status: "active", category: "อาหารเสริม", bankAcc: "SCB 234-5-67890", regDoc: "ภพ.20 / 2567", joined: now - 80 * day, isHouse: false },
    { id: "b3", name: "Wellness Daily", gp: 40, status: "active", category: "อาหารเสริม", bankAcc: "KBank 345-6-78901", regDoc: "ภพ.20 / 2566", joined: now - 60 * day, isHouse: false },
    { id: "b4", name: "Pure Skin Lab", gp: 60, status: "active", category: "ความงาม", bankAcc: "BAY 456-7-89012", regDoc: "ภพ.20 / 2567", joined: now - 40 * day, isHouse: false },
    { id: "b-house", name: "Nice Care (House Brand)", gp: 100, status: "active", category: "House Brand", bankAcc: "—", regDoc: "—", joined: now - 200 * day, isHouse: true },
    { id: "b5", name: "Aromatic Co.", gp: 50, status: "pending", category: "หอม-อโรม่า", bankAcc: "TTB 567-8-90123", regDoc: "อยู่ระหว่างตรวจสอบ", joined: now - 5 * day, isHouse: false },
  ];

  const products = [
    { id: "p1", brandId: "b1", name: "เซรั่มผิวกระจ่างใส VitaC 30ml", price: 890, stock: 240, sold: 1820, telesalesDiscount: 100 },
    { id: "p2", brandId: "b1", name: "ครีมบำรุงผิว Hydra Boost 50g", price: 690, stock: 180, sold: 1140, telesalesDiscount: 80 },
    { id: "p3", brandId: "b2", name: "วิตามินรวม Multi-Vita 60 เม็ด", price: 590, stock: 320, sold: 980, telesalesDiscount: 60 },
    { id: "p4", brandId: "b2", name: "คอลลาเจน Premium 200g", price: 1290, stock: 90, sold: 720, telesalesDiscount: 150 },
    { id: "p5", brandId: "b3", name: "น้ำมันปลา Omega-3 90 แคปซูล", price: 790, stock: 150, sold: 540, telesalesDiscount: 100 },
    { id: "p6", brandId: "b4", name: "แผ่นมาส์กหน้า Bio-Cell 5 ชิ้น", price: 390, stock: 420, sold: 2200, telesalesDiscount: 40 },
    { id: "p7", brandId: "b4", name: "เซรั่ม Retinol Night 20ml", price: 1190, stock: 60, sold: 380, telesalesDiscount: 200 },
    { id: "ph1", brandId: "b-house", name: "Nice Care สบู่สมุนไพร 3 ก้อน", price: 290, stock: 999, sold: 3200, telesalesDiscount: 50 },
    { id: "ph2", brandId: "b-house", name: "Nice Care ชาเขียวลดน้ำหนัก", price: 490, stock: 999, sold: 2400, telesalesDiscount: 80 },
    { id: "ph3", brandId: "b-house", name: "Nice Care คอลลาเจนเปปไทด์", price: 690, stock: 999, sold: 1800, telesalesDiscount: 100 },
  ];

  const brokers = [
    { id: "br1", name: "คุณทิพย์ สายแชร์", level: 7, exp: 4820, totalEarn: 24600, withdrawn: 18000, avatar: "ท", joined: now - 90 * day },
    { id: "br2", name: "คุณก้อย แม่ค้าออนไลน์", level: 6, exp: 3120, totalEarn: 18400, withdrawn: 12000, avatar: "ก", joined: now - 75 * day },
    { id: "br3", name: "คุณเอก รีวิวเวอร์", level: 9, exp: 6450, totalEarn: 42100, withdrawn: 30000, avatar: "อ", joined: now - 110 * day },
    { id: "br4", name: "คุณนุ่น ติ๊กต็อกเกอร์", level: 5, exp: 2100, totalEarn: 11200, withdrawn: 8000, avatar: "น", joined: now - 50 * day },
    { id: "br5", name: "คุณบาส เกมเมอร์", level: 4, exp: 1280, totalEarn: 6800, withdrawn: 4000, avatar: "บ", joined: now - 30 * day },
  ];

  const customers = [
    { id: "c1", name: "พรพิมล ส.", phone: "081-234-5678", addr: "เขตวัฒนา กรุงเทพฯ" },
    { id: "c2", name: "นภัส ก.", phone: "082-345-6789", addr: "เขตจตุจักร กรุงเทพฯ" },
    { id: "c3", name: "วรพล ม.", phone: "083-456-7890", addr: "เมือง เชียงใหม่" },
    { id: "c4", name: "สมหญิง ป.", phone: "084-567-8901", addr: "หาดใหญ่ สงขลา" },
    { id: "c5", name: "ปิยะ บ.", phone: "085-678-9012", addr: "บางพลี สมุทรปราการ" },
    { id: "c6", name: "กรรณิการ์ ส.", phone: "086-789-0123", addr: "เมือง ขอนแก่น" },
  ];

  // Build a history of orders across maai 1-4
  const orders = [];
  let oCount = 0;
  function pushOrder(custId, prodId, brokerId, maai, daysAgo, status = "delivered") {
    const product = products.find(p => p.id === prodId);
    orders.push({
      id: "o" + (1000 + oCount++),
      customerId: custId,
      productId: prodId,
      productName: product.name,
      brokerId,
      brandId: product.brandId,
      maai,
      amount: product.price,
      status,
      paymentMethod: ["COD", "QR", "CARD"][oCount % 3],
      createdAt: now - daysAgo * day + Math.random() * day,
    });
  }
  // maai 1 — affiliate links
  pushOrder("c1", "p1", "br1", 1, 25);
  pushOrder("c2", "p3", "br2", 1, 22);
  pushOrder("c3", "p6", "br3", 1, 20);
  pushOrder("c4", "p2", "br1", 1, 18);
  pushOrder("c5", "p4", "br3", 1, 14);
  pushOrder("c6", "p7", "br4", 1, 10);
  pushOrder("c1", "p5", "br2", 1, 7);
  pushOrder("c3", "p1", "br3", 1, 4);
  // maai 2 — telesales upsell
  pushOrder("c1", "ph1", "br1", 2, 23);
  pushOrder("c2", "p4", "br2", 2, 20);
  pushOrder("c3", "ph2", "br3", 2, 18);
  pushOrder("c4", "ph3", "br1", 2, 15);
  pushOrder("c5", "ph2", "br3", 2, 12);
  // maai 3 — repeat year 1
  pushOrder("c1", "p1", "br1", 3, 8);
  pushOrder("c2", "p3", "br2", 3, 5);
  pushOrder("c3", "ph2", "br3", 3, 2);
  // maai 4 — repeat year 2+
  pushOrder("c1", "ph1", "br1", 4, 1);

  const tickets = [
    { id: "t1", subject: "สินค้าชำรุดระหว่างจัดส่ง", category: "ผู้ซื้อ", priority: "high", status: "open", openedBy: "พรพิมล ส.", createdAt: now - 2 * 3600 * 1000, messages: [{ from: "customer", text: "เซรั่มที่ได้รับมาขวดบุบค่ะ ขอเปลี่ยนได้ไหม", at: now - 2 * 3600 * 1000 }] },
    { id: "t2", subject: "ค่าคอมไม้ 2 ยังไม่เข้า", category: "นายหน้า", priority: "medium", status: "open", openedBy: "คุณก้อย แม่ค้าออนไลน์", createdAt: now - 5 * 3600 * 1000, messages: [{ from: "broker", text: "เคสที่ปิดเมื่อวานยังไม่เห็นในกระเป๋าเลยค่ะ", at: now - 5 * 3600 * 1000 }] },
    { id: "t3", subject: "แก้ไขราคาสินค้า", category: "แบรนด์", priority: "low", status: "in_progress", openedBy: "Vita Plus", createdAt: now - 1 * 86400000, messages: [{ from: "brand", text: "ขอปรับราคาคอลลาเจน Premium เป็น 1,390 บาทครับ", at: now - 86400000 }] },
    { id: "t4", subject: "ลิงก์แชร์ใช้ไม่ได้", category: "นายหน้า", priority: "high", status: "closed", openedBy: "คุณบาส เกมเมอร์", createdAt: now - 3 * 86400000, messages: [{ from: "broker", text: "ลิงก์เปิดไม่ขึ้นครับ", at: now - 3 * 86400000 }, { from: "support", text: "แก้ไขเรียบร้อยแล้วครับ ลองเช็คอีกครั้งนะครับ", at: now - 2 * 86400000 }] },
  ];

  // Leads — queue สำหรับ Telesales (มาจาก orders ไม้ 1 ที่ยังไม่ได้โทร)
  const leads = orders
    .filter(o => o.maai === 1)
    .slice(0, 4)
    .map(o => ({
      id: "L_" + o.id,
      orderId: o.id,
      customerId: o.customerId,
      productId: o.productId,
      brokerId: o.brokerId,
      status: "pending", // pending | calling | closed | rejected
      assignedTo: null,
      createdAt: o.createdAt + 30 * 60 * 1000,
      attempts: 0,
    }));

  const coupons = [
    { id: "cp1", code: "TS-SAVE100", desc: "ส่วนลด 100฿ สำหรับ Telesales", value: 100, scope: "telesales", used: 23, limit: 200, status: "active", createdAt: now - 7 * day },
    { id: "cp2", code: "WELCOME50", desc: "ลูกค้าใหม่ลด 50฿", value: 50, scope: "customer", used: 142, limit: 500, status: "active", createdAt: now - 14 * day },
  ];

  const campaigns = [
    { id: "cm1", name: "Mid-Year Mega Sale", budget: 80000, spent: 42100, gmv: 218000, status: "active", channel: "Facebook + TikTok", startsAt: now - 14 * day },
    { id: "cm2", name: "Affiliate Boost Q2", budget: 30000, spent: 18200, gmv: 96400, status: "active", channel: "Affiliate Push", startsAt: now - 8 * day },
  ];

  const pushLog = [
    { id: "n1", title: "โปรใหม่ Vita Plus +10% Commission", body: "วันนี้ - 23:59 เท่านั้น", sentAt: now - 4 * 3600 * 1000, reach: 1248 },
    { id: "n2", title: "อัพเดทระบบลิงก์ใหม่", body: "ลิงก์สั้นขึ้น แชร์ง่ายขึ้น", sentAt: now - 86400000, reach: 1820 },
  ];

  const settlements = [
    { id: "s1", periodStart: now - 30 * day, periodEnd: now - 1 * day, gmv: 1860000, fixedCost: 86000, gatewayFee: 46500, marketingSpent: 60300, netProfit: 0, paidOut: false },
  ];
  settlements[0].netProfit = settlements[0].gmv * 0.45 - settlements[0].fixedCost - settlements[0].gatewayFee - settlements[0].marketingSpent;

  const supplierPayouts = brands.filter(b => !b.isHouse).map(b => {
    const bOrders = orders.filter(o => o.brandId === b.id);
    const gross = bOrders.reduce((a, o) => a + o.amount, 0);
    const supplierShare = gross * (1 - b.gp / 100);
    return { brandId: b.id, gross, supplierShare, withdrawn: supplierShare * 0.6 };
  });

  const affiliateTemplates = [
    { id: "at1", name: "Beauty Bold", category: "ความงาม", uses: 412 },
    { id: "at2", name: "Health Trust", category: "อาหารเสริม", uses: 318 },
    { id: "at3", name: "Lifestyle Soft", category: "ทั่วไป", uses: 156 },
  ];

  const flaggedPosts = [
    { id: "fp1", brokerId: "br5", excerpt: "...โปรดี ห้ามพลาด ของจัด!! ##spam##", reason: "ใช้คำซ้ำเชิง spam", reportedAt: now - 3600 * 1000, status: "pending" },
    { id: "fp2", brokerId: "br4", excerpt: "...เห้ย กดเลยอย่ารอ...", reason: "พบคำหยาบ", reportedAt: now - 7200 * 1000, status: "pending" },
  ];

  const settings = {
    coFounderSplit: { yiw: 55, dev: 45 },
    webhookUrl: "https://api.nicecall.co/yjmall/webhooks/v1",
    apiToken: "yjm_live_" + Math.random().toString(36).slice(2, 14),
    pdpaText: "ข้าพเจ้ายินยอมให้ YJmall และพันธมิตรทางธุรกิจ (รวมถึง Nice Call) เก็บ ใช้ และเปิดเผยข้อมูลส่วนบุคคลตามนโยบาย PDPA เพื่อวัตถุประสงค์ในการจัดส่งสินค้า ติดต่อรับบริการหลังการขาย และนำเสนอผลิตภัณฑ์ที่เกี่ยวข้อง",
    primaryColor: "#1E4FD9",
    theme: "light",
    gpDefault: 50,
  };

  return {
    brands, products, brokers, customers, orders, tickets, leads,
    coupons, campaigns, pushLog, settlements, supplierPayouts,
    affiliateTemplates, flaggedPosts, settings,
    currentBrokerId: "br1",
    currentBrandId: "b1",
  };
}

// === Persistence ===
let _state = null;
const _listeners = new Set();

function load() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) return JSON.parse(raw);
  } catch {}
  return makeSeed();
}
function save() { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(_state)); } catch {} }
function emit() { _listeners.forEach(fn => fn()); }

function getState() {
  if (!_state) _state = load();
  return _state;
}
function setState(updater) {
  _state = typeof updater === "function" ? updater(getState()) : { ...getState(), ...updater };
  save();
  emit();
}
function resetState() {
  _state = makeSeed();
  save();
  emit();
}

// === Hook ===
function useStore(selector = s => s) {
  const [, force] = React.useReducer(x => x + 1, 0);
  React.useEffect(() => {
    const fn = () => force();
    _listeners.add(fn);
    return () => _listeners.delete(fn);
  }, []);
  return selector(getState());
}

// === Action helpers ===
const actions = {
  // Customer places maai-1 order → creates lead for Telesales
  placeOrder({ customerId, productId, brokerId, paymentMethod, customer }) {
    const s = getState();
    const product = s.products.find(p => p.id === productId);
    if (!product) return null;
    if (product.stock <= 0) return null;

    // Create or reuse customer
    let cid = customerId;
    if (!cid && customer) {
      cid = uid("c");
      setState(st => ({ ...st, customers: [{ id: cid, ...customer }, ...st.customers] }));
    }

    const orderId = "o" + Date.now();
    const order = {
      id: orderId,
      customerId: cid,
      productId,
      productName: product.name,
      brokerId: brokerId || null,
      brandId: product.brandId,
      maai: 1,
      amount: product.price,
      status: paymentMethod === "COD" ? "pending" : "paid",
      paymentMethod,
      createdAt: Date.now(),
    };
    const lead = {
      id: "L_" + orderId,
      orderId,
      customerId: cid,
      productId,
      brokerId: brokerId || null,
      status: "pending",
      assignedTo: null,
      createdAt: Date.now() + 60 * 1000,
      attempts: 0,
    };
    setState(st => ({
      ...st,
      orders: [order, ...st.orders],
      leads: [lead, ...st.leads],
      products: st.products.map(p => p.id === productId ? { ...p, stock: Math.max(0, p.stock - 1), sold: p.sold + 1 } : p),
    }));
    return order;
  },

  // Telesales closes a maai-2 upsell
  closeUpsell({ leadId, productId, useHouseBrand, discount }) {
    const s = getState();
    const lead = s.leads.find(l => l.id === leadId);
    if (!lead) return;
    const product = s.products.find(p => p.id === productId);
    if (!product) return;
    const orderId = "o" + Date.now();
    const order = {
      id: orderId,
      customerId: lead.customerId,
      productId,
      productName: product.name,
      brokerId: lead.brokerId,
      brandId: product.brandId,
      maai: 2,
      amount: Math.max(0, product.price - (discount || 0)),
      status: "paid",
      paymentMethod: "TELESALES",
      isHouseBrand: !!useHouseBrand,
      createdAt: Date.now(),
    };
    setState(st => ({
      ...st,
      orders: [order, ...st.orders],
      leads: st.leads.map(l => l.id === leadId ? { ...l, status: "closed", closedAt: Date.now() } : l),
      products: st.products.map(p => p.id === productId ? { ...p, sold: p.sold + 1 } : p),
    }));
    return order;
  },

  rejectLead(leadId, reason) {
    setState(st => ({
      ...st,
      leads: st.leads.map(l => l.id === leadId ? { ...l, status: "rejected", reason, closedAt: Date.now() } : l),
    }));
  },

  assignLead(leadId, agent) {
    setState(st => ({
      ...st,
      leads: st.leads.map(l => l.id === leadId ? { ...l, status: "calling", assignedTo: agent, attempts: (l.attempts || 0) + 1 } : l),
    }));
  },

  // Broker withdraws
  brokerWithdraw(brokerId, amount) {
    setState(st => ({
      ...st,
      brokers: st.brokers.map(b => b.id === brokerId ? { ...b, withdrawn: (b.withdrawn || 0) + amount } : b),
    }));
  },

  // Supplier withdraws
  supplierWithdraw(brandId, amount) {
    setState(st => ({
      ...st,
      supplierPayouts: st.supplierPayouts.map(p => p.brandId === brandId ? { ...p, withdrawn: (p.withdrawn || 0) + amount } : p),
    }));
  },

  // Co-Founder dividend
  payDividend(settlementId) {
    setState(st => ({
      ...st,
      settlements: st.settlements.map(s => s.id === settlementId ? { ...s, paidOut: true, paidAt: Date.now() } : s),
    }));
  },

  upsertProduct(product) {
    setState(st => {
      const exists = st.products.find(p => p.id === product.id);
      return {
        ...st,
        products: exists
          ? st.products.map(p => p.id === product.id ? { ...p, ...product } : p)
          : [{ ...product, id: product.id || uid("p"), stock: product.stock || 0, sold: 0 }, ...st.products],
      };
    });
  },

  deleteProduct(productId) {
    setState(st => ({ ...st, products: st.products.filter(p => p.id !== productId) }));
  },

  approveBrand(brandId) {
    setState(st => ({ ...st, brands: st.brands.map(b => b.id === brandId ? { ...b, status: "active" } : b) }));
  },

  toggleBrandStatus(brandId) {
    setState(st => ({ ...st, brands: st.brands.map(b => b.id === brandId ? { ...b, status: b.status === "active" ? "suspended" : "active" } : b) }));
  },

  addBrand(b) {
    setState(st => ({ ...st, brands: [{ id: uid("b"), status: "active", joined: Date.now(), isHouse: false, ...b }, ...st.brands] }));
  },

  addCoupon(c) {
    setState(st => ({ ...st, coupons: [{ id: uid("cp"), used: 0, status: "active", createdAt: Date.now(), ...c }, ...st.coupons] }));
  },

  addCampaign(c) {
    setState(st => ({ ...st, campaigns: [{ id: uid("cm"), spent: 0, gmv: 0, status: "active", startsAt: Date.now(), ...c }, ...st.campaigns] }));
  },

  sendPush(p) {
    setState(st => ({ ...st, pushLog: [{ id: uid("n"), sentAt: Date.now(), reach: st.brokers.length, ...p }, ...st.pushLog] }));
  },

  // Tickets
  replyTicket(ticketId, text, from = "support") {
    setState(st => ({
      ...st,
      tickets: st.tickets.map(t => t.id === ticketId ? {
        ...t,
        messages: [...t.messages, { from, text, at: Date.now() }],
        status: from === "support" ? "in_progress" : t.status,
      } : t),
    }));
  },
  closeTicket(ticketId) {
    setState(st => ({ ...st, tickets: st.tickets.map(t => t.id === ticketId ? { ...t, status: "closed" } : t) }));
  },

  // Flagged posts
  moderatePost(postId, action) {
    setState(st => ({ ...st, flaggedPosts: st.flaggedPosts.map(p => p.id === postId ? { ...p, status: action } : p) }));
  },

  // Settings
  updateSettings(patch) {
    setState(st => ({ ...st, settings: { ...st.settings, ...patch } }));
  },

  switchBroker(brokerId) {
    setState(st => ({ ...st, currentBrokerId: brokerId }));
  },
  switchBrand(brandId) {
    setState(st => ({ ...st, currentBrandId: brandId }));
  },
};

// === Computed selectors ===
const select = {
  gmv: (s, days) => {
    const cutoff = Date.now() - days * 86400000;
    return s.orders.filter(o => o.createdAt >= cutoff && o.status !== "rejected").reduce((a, o) => a + o.amount, 0);
  },
  byMaai: (s) => {
    const totals = { 1: 0, 2: 0, 3: 0, 4: 0 };
    s.orders.forEach(o => { if (o.status !== "rejected") totals[o.maai] = (totals[o.maai] || 0) + o.amount; });
    return totals;
  },
  activeBrokers: (s) => s.brokers.filter(b => b.totalEarn > 0).length,
  activeSellers: (s) => s.brands.filter(b => b.status === "active" && !b.isHouse).length,
  houseBrandShare: (s) => {
    const total = s.orders.reduce((a, o) => a + o.amount, 0);
    const house = s.orders.filter(o => {
      const b = s.brands.find(br => br.id === o.brandId);
      return b && b.isHouse;
    }).reduce((a, o) => a + o.amount, 0);
    return { total, house, general: total - house };
  },
  brokerEarn: (s, brokerId) => {
    return s.orders
      .filter(o => o.brokerId === brokerId)
      .reduce((a, o) => a + o.amount * 0.05, 0); // 5% sample commission
  },
  topBrokers: (s, n = 3) => {
    const map = {};
    s.orders.forEach(o => { if (!o.brokerId) return; map[o.brokerId] = (map[o.brokerId] || 0) + o.amount * 0.05; });
    return Object.entries(map)
      .map(([id, earn]) => ({ broker: s.brokers.find(b => b.id === id), earn }))
      .filter(x => x.broker)
      .sort((a, b) => b.earn - a.earn)
      .slice(0, n);
  },
  customerHistory: (s, customerId) => s.orders.filter(o => o.customerId === customerId).sort((a, b) => b.createdAt - a.createdAt),
  pendingLeads: (s) => s.leads.filter(l => l.status === "pending" || l.status === "calling"),
};

// Expose globals
Object.assign(window, {
  YJ: { getState, setState, resetState, useStore, actions, select, makeSeed },
  fmtTHB, fmtNum, fmtDate, fmtTime, fmtRelTime, uid, clamp,
});
