// ====== Reports page ======

const REPORTS_STORAGE_KEY = "teaGangReportsPrefsV1";
const REPORT_ADDED_DATE_BASIS = "created";

const REPORT_PERIODS = [
  { id: "today", label: "Today", icon: "calendar" },
  { id: "week", label: "Week", icon: "calendar" },
  { id: "sun-sat-added", label: "Sun-Sat", icon: "clock" },
  { id: "month", label: "Month", icon: "calendar" },
  { id: "quarter", label: "Quarter", icon: "calendar" },
  { id: "year", label: "Year", icon: "calendar" },
  { id: "custom", label: "Custom", icon: "filter" },
];

const reportPad = (value) => String(value).padStart(2, "0");
const reportStartOfDay = (value = new Date()) => {
  const date = value instanceof Date ? value : new Date(value);
  return new Date(date.getFullYear(), date.getMonth(), date.getDate());
};
const reportAddDays = (date, days) => {
  const next = new Date(date);
  next.setDate(next.getDate() + days);
  return next;
};
const reportAddMonths = (date, months) => {
  const next = new Date(date);
  next.setMonth(next.getMonth() + months);
  return next;
};
const reportAddYears = (date, years) => new Date(date.getFullYear() + years, date.getMonth(), date.getDate());
const reportStartOfQuarter = (date) => new Date(date.getFullYear(), Math.floor(date.getMonth() / 3) * 3, 1);
const reportAddQuarters = (date, quarters) => reportAddMonths(date, quarters * 3);
const reportStartOfWeek = (date, firstDay = 1) => {
  const start = reportStartOfDay(date);
  const offset = (start.getDay() - firstDay + 7) % 7;
  start.setDate(start.getDate() - offset);
  return start;
};
const reportDateValue = (date) => `${date.getFullYear()}-${reportPad(date.getMonth() + 1)}-${reportPad(date.getDate())}`;
const reportDateFromInput = (value) => value ? new Date(`${value}T00:00:00`) : null;
const reportMoney = (value) => Math.round((Number(value) || 0) * 100) / 100;
const reportFormatMoney = (value) => `$${reportMoney(value).toFixed(2)}`;
const reportFormatDate = (date, options = {}) => date.toLocaleDateString("en-US", options);

const readReportsPrefs = () => {
  try {
    const saved = JSON.parse(window.localStorage.getItem(REPORTS_STORAGE_KEY) || "{}");
    return {
      period: REPORT_PERIODS.some(p => p.id === saved.period) ? saved.period : "sun-sat-added",
      selectedItemKey: typeof saved.selectedItemKey === "string" ? saved.selectedItemKey : "",
      customRange: saved.customRange && typeof saved.customRange === "object"
        ? { from: saved.customRange.from || "", to: saved.customRange.to || "" }
        : { from: "", to: "" },
    };
  } catch {
    return {
      period: "sun-sat-added",
      selectedItemKey: "",
      customRange: { from: "", to: "" },
    };
  }
};

const reportRangeForPeriod = (period, customRange) => {
  const now = new Date();
  const today = reportStartOfDay(now);
  const day = 864e5;

  if (period === "today") {
    return { valid: true, dateFrom: today, dateTo: new Date(today.getTime() + day), label: "Today" };
  }
  if (period === "week") {
    const start = reportStartOfWeek(today, 1);
    return { valid: true, dateFrom: start, dateTo: reportAddDays(start, 7), label: "This week" };
  }
  if (period === "sun-sat-added") {
    const start = reportStartOfWeek(today, 0);
    return { valid: true, dateFrom: start, dateTo: reportAddDays(start, 7), label: "Sun-Sat" };
  }
  if (period === "month") {
    return {
      valid: true,
      dateFrom: new Date(now.getFullYear(), now.getMonth(), 1),
      dateTo: new Date(now.getFullYear(), now.getMonth() + 1, 1),
      label: "This month",
    };
  }
  if (period === "quarter") {
    const quarterStart = Math.floor(now.getMonth() / 3) * 3;
    return {
      valid: true,
      dateFrom: new Date(now.getFullYear(), quarterStart, 1),
      dateTo: new Date(now.getFullYear(), quarterStart + 3, 1),
      label: "This quarter",
    };
  }
  if (period === "year") {
    return {
      valid: true,
      dateFrom: new Date(now.getFullYear(), 0, 1),
      dateTo: new Date(now.getFullYear() + 1, 0, 1),
      label: "This year",
    };
  }

  const from = reportDateFromInput(customRange?.from);
  const to = reportDateFromInput(customRange?.to);
  if (!from || !to || from > to) {
    return { valid: false, dateFrom: null, dateTo: null, label: "Choose dates" };
  }
  return {
    valid: true,
    dateFrom: from,
    dateTo: reportAddDays(to, 1),
    label: "Custom range",
  };
};

const reportRangeDateLabel = (range) => {
  if (!range?.valid || !range.dateFrom || !range.dateTo) return "No date range selected";
  const from = range.dateFrom;
  const inclusiveTo = reportAddDays(range.dateTo, -1);
  const sameDay = reportDateValue(from) === reportDateValue(inclusiveTo);
  if (sameDay) {
    return reportFormatDate(from, { month: "short", day: "numeric", year: "numeric" });
  }
  return `${reportFormatDate(from, { month: "short", day: "numeric" })} - ${reportFormatDate(inclusiveTo, { month: "short", day: "numeric", year: "numeric" })}`;
};

const reportRangeKey = (range, basis) => {
  const stamp = (value) => value ? new Date(value).toISOString() : "";
  return JSON.stringify({ from: stamp(range?.dateFrom), to: stamp(range?.dateTo), basis });
};

const reportOrderBasisDate = (order, basis) => {
  const value = basis === "scheduled" ? (order.scheduled_at || order.created_at) : order.created_at;
  if (!value) return null;
  const date = new Date(value);
  return Number.isFinite(date.getTime()) ? date : null;
};

const reportOrderInRange = (order, range, basis) => {
  if (!range?.valid) return false;
  const date = reportOrderBasisDate(order, basis);
  if (!date) return false;
  if (range.dateFrom && date < range.dateFrom) return false;
  if (range.dateTo && date >= range.dateTo) return false;
  return true;
};

const reportOrderTotal = (order) => reportMoney(Number(order.total || 0));
const reportIsCompleted = (order) => order.status === "completed";
const reportIsOpen = (order) => order.status === "pending" || order.status === "ready";
const reportVisibleOrderItems = (order) => (order?.items || []).filter(item => (
  item?.is_included_addon !== true && item?.isIncludedAddon !== true
));
const reportItemName = (item) => item?.name || item?.menu_item_name || item?.label || "Unknown item";
const reportNormalizeText = (value) => {
  const text = String(value || "").trim().toLowerCase();
  if (!text) return "";
  if (typeof normalizeVi === "function") return normalizeVi(text);
  return text.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
};
const reportItemKey = (item, nameToKey = {}) => {
  const id = item?.menuItemId || item?.menu_item_id || item?.id;
  if (id) return String(id);
  const nameKey = reportNormalizeText(reportItemName(item));
  return nameToKey[nameKey] || `name:${nameKey || "unknown"}`;
};
const reportItemQuantity = (item) => {
  const value = Number(item?.qty ?? item?.quantity ?? 1);
  return Number.isFinite(value) ? value : 0;
};
const reportItemLineTotal = (item) => {
  const direct = Number(item?.line_total ?? item?.lineTotal);
  if (Number.isFinite(direct)) return reportMoney(direct);
  return reportMoney(Number(item?.price || 0) * reportItemQuantity(item));
};

const reportPeriodChartConfig = (period, range) => {
  if (!range?.valid || !range.dateFrom || !range.dateTo) return { valid: false };
  const currentStart = range.dateFrom;
  if (period === "today") {
    return {
      valid: true,
      bucket: "range",
      dateFrom: range.dateFrom,
      dateTo: range.dateTo,
      rowStart: range.dateFrom,
      currentStart,
      title: "Money by period",
      subtitle: "Current day as one bar",
    };
  }
  if (period === "week") {
    const start = reportAddDays(currentStart, -49);
    return {
      valid: true,
      bucket: "week-monday",
      dateFrom: start,
      dateTo: reportAddDays(currentStart, 7),
      rowStart: start,
      currentStart,
      title: "Weekly money",
      subtitle: "Each bar is a Monday-Sunday week",
    };
  }
  if (period === "sun-sat-added") {
    const start = reportAddDays(currentStart, -49);
    return {
      valid: true,
      bucket: "week-sunday",
      dateFrom: start,
      dateTo: reportAddDays(currentStart, 7),
      rowStart: start,
      currentStart,
      title: "Sun-Sat money",
      subtitle: "Each bar is a Sunday-Saturday period",
    };
  }
  if (period === "month") {
    const start = reportAddMonths(currentStart, -5);
    return {
      valid: true,
      bucket: "month",
      dateFrom: start,
      dateTo: reportAddMonths(currentStart, 1),
      rowStart: start,
      currentStart,
      title: "Monthly money",
      subtitle: "Each bar is one month",
    };
  }
  if (period === "quarter") {
    const start = reportAddQuarters(reportStartOfQuarter(currentStart), -5);
    return {
      valid: true,
      bucket: "quarter",
      dateFrom: start,
      dateTo: reportAddQuarters(reportStartOfQuarter(currentStart), 1),
      rowStart: start,
      currentStart: reportStartOfQuarter(currentStart),
      title: "Quarterly money",
      subtitle: "Each bar is one quarter",
    };
  }
  if (period === "year") {
    const start = new Date(currentStart.getFullYear() - 4, 0, 1);
    return {
      valid: true,
      bucket: "year",
      dateFrom: start,
      dateTo: new Date(currentStart.getFullYear() + 1, 0, 1),
      rowStart: start,
      currentStart: new Date(currentStart.getFullYear(), 0, 1),
      title: "Yearly money",
      subtitle: "Each bar is one year",
    };
  }
  const days = Math.max(1, Math.round((range.dateTo - range.dateFrom) / 864e5));
  const bucket = days > 120 ? "month" : "week-sunday";
  return {
    valid: true,
    bucket,
    dateFrom: range.dateFrom,
    dateTo: range.dateTo,
    rowStart: reportBucketStart(range.dateFrom, bucket),
    currentStart: reportBucketStart(range.dateFrom, bucket),
    title: "Custom range money",
    subtitle: bucket === "month" ? "Each bar is one month" : "Each bar is one Sunday-Saturday week",
  };
};

const reportBucketStart = (date, mode) => {
  const start = reportStartOfDay(date);
  if (mode === "week-sunday") return reportStartOfWeek(start, 0);
  if (mode === "week-monday") return reportStartOfWeek(start, 1);
  if (mode === "month") return new Date(start.getFullYear(), start.getMonth(), 1);
  if (mode === "quarter") return reportStartOfQuarter(start);
  if (mode === "year") return new Date(start.getFullYear(), 0, 1);
  return start;
};

const reportNextBucketStart = (date, mode) => {
  if (mode === "week-sunday" || mode === "week-monday") return reportAddDays(date, 7);
  if (mode === "month") return reportAddMonths(date, 1);
  if (mode === "quarter") return reportAddQuarters(date, 1);
  if (mode === "year") return reportAddYears(date, 1);
  return reportAddDays(date, 1);
};

const reportBucketKey = (date, mode) => reportDateValue(reportBucketStart(date, mode));

const reportBucketLabel = (date, mode) => {
  const start = reportBucketStart(date, mode);
  if (mode === "month") return reportFormatDate(start, { month: "short", year: "numeric" });
  if (mode === "quarter") return `Q${Math.floor(start.getMonth() / 3) + 1} ${start.getFullYear()}`;
  if (mode === "year") return String(start.getFullYear());
  if (mode === "week-sunday" || mode === "week-monday") {
    const end = reportAddDays(start, 6);
    return `${reportFormatDate(start, { month: "short", day: "numeric" })} - ${reportFormatDate(end, { month: "short", day: "numeric" })}`;
  }
  return reportFormatDate(start, { weekday: "short", month: "short", day: "numeric" });
};

const reportChartBucketKey = (date, config) => config.bucket === "range" ? "current" : reportBucketKey(date, config.bucket);

const reportBuildChartRows = (config) => {
  if (!config?.valid || !config.dateFrom || !config.dateTo) return [];
  if (config.bucket === "range") {
    return [{
      key: "current",
      label: "Current period",
      date: new Date(config.dateFrom),
      dateFrom: config.dateFrom,
      dateTo: config.dateTo,
      isCurrent: true,
      completedMoney: 0,
      openMoney: 0,
      orderCount: 0,
      completedCount: 0,
    }];
  }
  const rows = [];
  let cursor = config.rowStart || reportBucketStart(config.dateFrom, config.bucket);
  const guard = 420;
  while (cursor < config.dateTo && rows.length < guard) {
    const next = reportNextBucketStart(cursor, config.bucket);
    const key = reportBucketKey(cursor, config.bucket);
    rows.push({
      key,
      label: reportBucketLabel(cursor, config.bucket),
      date: new Date(cursor),
      dateFrom: new Date(cursor),
      dateTo: next,
      isCurrent: reportDateValue(cursor) === reportDateValue(config.currentStart || config.dateFrom),
      completedMoney: 0,
      openMoney: 0,
      orderCount: 0,
      completedCount: 0,
    });
    cursor = next;
  }
  return rows;
};

const Reports = () => {
  const initialPrefs = React.useMemo(readReportsPrefs, []);
  const [period, setPeriod] = React.useState(initialPrefs.period);
  const [selectedItemKey, setSelectedItemKey] = React.useState(initialPrefs.selectedItemKey);
  const [itemSearch, setItemSearch] = React.useState("");
  const [itemSearchOpen, setItemSearchOpen] = React.useState(false);
  const [customRange, setCustomRange] = React.useState(initialPrefs.customRange);
  const [orders, setOrders] = React.useState([]);
  const [menuItems, setMenuItems] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [dataReady, setDataReady] = React.useState(false);
  const [loadedRangeKey, setLoadedRangeKey] = React.useState("");
  const [error, setError] = React.useState("");
  const loadSeqRef = React.useRef(0);

  const range = React.useMemo(() => reportRangeForPeriod(period, customRange), [period, customRange.from, customRange.to]);
  const periodChartConfig = React.useMemo(() => reportPeriodChartConfig(period, range), [period, range]);
  const requestedRangeKey = React.useMemo(() => (
    `${period}:${periodChartConfig.bucket || ""}:${reportRangeKey(periodChartConfig.valid ? periodChartConfig : range, REPORT_ADDED_DATE_BASIS)}`
  ), [period, periodChartConfig, range]);

  React.useEffect(() => {
    window.localStorage.setItem(REPORTS_STORAGE_KEY, JSON.stringify({
      period,
      customRange,
      selectedItemKey,
    }));
  }, [period, customRange, selectedItemKey]);

  const loadReports = React.useCallback(async ({ keepCurrent = false } = {}) => {
    const requestId = ++loadSeqRef.current;
    if (!range.valid || !periodChartConfig.valid) {
      setOrders([]);
      setMenuItems([]);
      setLoadedRangeKey(requestedRangeKey);
      setDataReady(true);
      setLoading(false);
      return;
    }
    const backend = window.TeaGangBackend;
    if (!keepCurrent) setLoading(true);
    setError("");
    if (!backend?.enabled) {
      if (requestId === loadSeqRef.current) {
        setOrders([]);
        setMenuItems([]);
        setLoadedRangeKey(requestedRangeKey);
        setDataReady(true);
        setLoading(false);
      }
      return;
    }
    try {
      const [orderRows, menu] = await Promise.all([
        backend.fetchOrders({
          dateFrom: periodChartConfig.dateFrom,
          dateTo: periodChartConfig.dateTo,
          dateBasis: REPORT_ADDED_DATE_BASIS,
        }),
        backend.fetchMenu
          ? backend.fetchMenu().catch(err => {
            console.warn("Reports menu lookup unavailable.", err);
            return { items: [] };
          })
          : Promise.resolve({ items: [] }),
      ]);
      if (requestId !== loadSeqRef.current) return;
      setOrders(orderRows || []);
      setMenuItems(menu?.items || []);
      setLoadedRangeKey(requestedRangeKey);
    } catch (err) {
      if (requestId !== loadSeqRef.current) return;
      console.error("Reports backend unavailable.", err);
      setOrders([]);
      setMenuItems([]);
      setError(err.message || "Could not load report data.");
      setLoadedRangeKey(requestedRangeKey);
    } finally {
      if (requestId === loadSeqRef.current) {
        setDataReady(true);
        setLoading(false);
      }
    }
  }, [range.valid, periodChartConfig, requestedRangeKey]);

  React.useEffect(() => {
    loadReports();
  }, [loadReports]);

  React.useEffect(() => {
    const backend = window.TeaGangBackend;
    if (!backend?.subscribeToStoreData || !range.valid) return undefined;
    let disposed = false;
    let subscription = null;
    const refreshSoon = () => {
      if (!disposed) loadReports({ keepCurrent: true });
    };
    backend
      .subscribeToStoreData(refreshSoon, ["orders", "order_items", "menu_items"])
      .then(next => {
        if (disposed) next?.unsubscribe?.();
        else subscription = next;
      })
      .catch(err => console.warn("Reports realtime unavailable.", err));
    return () => {
      disposed = true;
      subscription?.unsubscribe?.();
    };
  }, [loadReports, range.valid]);

  const preparing = loading || !dataReady || loadedRangeKey !== requestedRangeKey;

  const periodChartRows = React.useMemo(() => {
    const baseRows = reportBuildChartRows(periodChartConfig);
    const rowByKey = new Map(baseRows.map(row => [row.key, row]));
    const chartOrders = orders.filter(order => reportOrderInRange(order, periodChartConfig, REPORT_ADDED_DATE_BASIS));
    chartOrders.forEach(order => {
      const date = reportOrderBasisDate(order, REPORT_ADDED_DATE_BASIS);
      if (!date) return;
      const key = reportChartBucketKey(date, periodChartConfig);
      const row = rowByKey.get(key);
      if (!row) return;
      row.orderCount += 1;
      if (reportIsCompleted(order)) {
        row.completedCount += 1;
        row.completedMoney += reportOrderTotal(order);
      } else if (reportIsOpen(order)) {
        row.openMoney += reportOrderTotal(order);
      }
    });
    return baseRows;
  }, [orders, periodChartConfig]);
  const maxPeriodChartMoney = Math.max(1, ...periodChartRows.map(row => row.completedMoney + row.openMoney));

  const itemNameToKey = React.useMemo(() => {
    const names = {};
    (menuItems || []).forEach(item => {
      const key = reportItemKey(item);
      const nameKey = reportNormalizeText(reportItemName(item));
      if (nameKey) names[nameKey] = key;
    });
    return names;
  }, [menuItems]);

  const itemStats = React.useMemo(() => {
    const rows = new Map();
    const ensureRow = (key, item) => {
      if (!rows.has(key)) {
        rows.set(key, {
          key,
          name: reportItemName(item),
          category: item?.category || item?.category_name || "",
          image: item?.image_url || item?.imageUrl || null,
          completedMoney: 0,
          openMoney: 0,
          completedUnits: 0,
          openUnits: 0,
          units: 0,
        });
      }
      const row = rows.get(key);
      if (!row.image && (item?.image_url || item?.imageUrl)) row.image = item.image_url || item.imageUrl;
      if (!row.category && (item?.category || item?.category_name)) row.category = item.category || item.category_name;
      return row;
    };

    (menuItems || []).forEach(item => ensureRow(reportItemKey(item), item));
    orders
      .filter(order => reportOrderInRange(order, periodChartConfig, REPORT_ADDED_DATE_BASIS))
      .forEach(order => {
        reportVisibleOrderItems(order).forEach(item => {
          const row = ensureRow(reportItemKey(item, itemNameToKey), item);
          const quantity = reportItemQuantity(item);
          const money = reportItemLineTotal(item);
          row.units += quantity;
          if (reportIsCompleted(order)) {
            row.completedUnits += quantity;
            row.completedMoney += money;
          } else if (reportIsOpen(order)) {
            row.openUnits += quantity;
            row.openMoney += money;
          }
        });
      });

    return Array.from(rows.values())
      .map(row => ({
        ...row,
        completedMoney: reportMoney(row.completedMoney),
        openMoney: reportMoney(row.openMoney),
        totalMoney: reportMoney(row.completedMoney + row.openMoney),
      }))
      .sort((a, b) => {
        const activeDiff = Number(b.totalMoney > 0 || b.units > 0) - Number(a.totalMoney > 0 || a.units > 0);
        if (activeDiff) return activeDiff;
        return (b.totalMoney - a.totalMoney) || (b.units - a.units) || a.name.localeCompare(b.name);
      });
  }, [orders, menuItems, periodChartConfig, itemNameToKey]);

  const selectedItem = React.useMemo(() => (
    itemStats.find(item => item.key === selectedItemKey) || itemStats[0] || null
  ), [itemStats, selectedItemKey]);

  const filteredItemStats = React.useMemo(() => {
    const query = reportNormalizeText(itemSearch);
    if (!query) return itemStats;
    return itemStats.filter(item => (
      reportNormalizeText(item.name).includes(query) ||
      reportNormalizeText(item.category).includes(query)
    ));
  }, [itemStats, itemSearch]);
  const visibleItemSearchResults = filteredItemStats;
  const selectReportItem = React.useCallback((item) => {
    if (!item) return;
    setSelectedItemKey(item.key);
    setItemSearch(item.name);
    setItemSearchOpen(false);
  }, []);

  React.useEffect(() => {
    if (!itemStats.length) {
      if (selectedItemKey) setSelectedItemKey("");
      if (itemSearch) setItemSearch("");
      return;
    }
    if (!itemStats.some(item => item.key === selectedItemKey)) {
      setSelectedItemKey(itemStats[0].key);
      setItemSearch(itemStats[0].name);
    }
  }, [itemStats, selectedItemKey, itemSearch]);

  const itemChartRows = React.useMemo(() => {
    if (!selectedItem) return [];
    const baseRows = reportBuildChartRows(periodChartConfig).map(row => ({
      ...row,
      completedMoney: 0,
      openMoney: 0,
      completedUnits: 0,
      openUnits: 0,
      completedOrders: new Set(),
      openOrders: new Set(),
    }));
    const rowByKey = new Map(baseRows.map(row => [row.key, row]));
    orders
      .filter(order => reportOrderInRange(order, periodChartConfig, REPORT_ADDED_DATE_BASIS))
      .forEach(order => {
        const date = reportOrderBasisDate(order, REPORT_ADDED_DATE_BASIS);
        if (!date) return;
        const row = rowByKey.get(reportChartBucketKey(date, periodChartConfig));
        if (!row) return;
        reportVisibleOrderItems(order).forEach(item => {
          if (reportItemKey(item, itemNameToKey) !== selectedItem.key) return;
          const quantity = reportItemQuantity(item);
          const money = reportItemLineTotal(item);
          const orderKey = order.dbId || order.id || `${row.key}-${row.completedOrders.size + row.openOrders.size}`;
          if (reportIsCompleted(order)) {
            row.completedUnits += quantity;
            row.completedMoney += money;
            row.completedOrders.add(orderKey);
          } else if (reportIsOpen(order)) {
            row.openUnits += quantity;
            row.openMoney += money;
            row.openOrders.add(orderKey);
          }
        });
      });
    return baseRows.map(row => ({
      ...row,
      completedMoney: reportMoney(row.completedMoney),
      openMoney: reportMoney(row.openMoney),
      completedOrderCount: row.completedOrders.size,
      openOrderCount: row.openOrders.size,
    }));
  }, [orders, periodChartConfig, itemNameToKey, selectedItem?.key]);
  const maxItemChartMoney = Math.max(1, ...itemChartRows.map(row => row.completedMoney + row.openMoney));

  const unitSoldRows = React.useMemo(() => {
    const rows = new Map();
    const ensureRow = (key, item) => {
      if (!rows.has(key)) {
        rows.set(key, {
          key,
          name: reportItemName(item),
          category: item?.category || item?.category_name || "",
          completedUnits: 0,
          openUnits: 0,
          completedMoney: 0,
          completedOrders: new Set(),
        });
      }
      const row = rows.get(key);
      if (!row.category && (item?.category || item?.category_name)) row.category = item.category || item.category_name;
      return row;
    };

    (menuItems || []).forEach(item => ensureRow(reportItemKey(item), item));
    orders
      .filter(order => reportOrderInRange(order, range, REPORT_ADDED_DATE_BASIS))
      .forEach(order => {
        reportVisibleOrderItems(order).forEach(item => {
          const row = ensureRow(reportItemKey(item, itemNameToKey), item);
          const quantity = reportItemQuantity(item);
          if (reportIsCompleted(order)) {
            row.completedUnits += quantity;
            row.completedMoney += reportItemLineTotal(item);
            row.completedOrders.add(order.dbId || order.id || `${row.key}-${row.completedOrders.size}`);
          } else if (reportIsOpen(order)) {
            row.openUnits += quantity;
          }
        });
      });

    return Array.from(rows.values())
      .map(row => ({
        ...row,
        completedMoney: reportMoney(row.completedMoney),
        completedOrderCount: row.completedOrders.size,
      }))
      .filter(row => row.completedUnits > 0)
      .sort((a, b) => (
        (b.completedUnits - a.completedUnits) ||
        (b.completedMoney - a.completedMoney) ||
        a.name.localeCompare(b.name)
      ));
  }, [orders, menuItems, range, itemNameToKey]);
  const maxUnitSold = Math.max(1, ...unitSoldRows.map(row => row.completedUnits));
  const periodSubtitle = `${reportRangeDateLabel(range)} by added date`;

  return (
    <div className="reports-page">
      <div className="page-head">
        <div>
          <div className="page-eyebrow">Store reports</div>
          <h1 className="page-title">Reports</h1>
          <div className="page-meta" style={{ marginTop: 8 }}>
            <span className="ornament"></span>
            <span>{periodSubtitle}</span>
          </div>
        </div>
        <button className="btn btn-ghost" type="button" onClick={() => loadReports()}>
          <Ic name="refresh" />
          Refresh
        </button>
      </div>

      <div className="reports-filter-panel">
        <div className="reports-filter-group">
          <span className="reports-filter-label">Period</span>
          <div className="reports-chip-row">
            {REPORT_PERIODS.map(option => (
              <button
                key={option.id}
                type="button"
                className={`reports-chip ${period === option.id ? "active" : ""}`}
                onClick={() => setPeriod(option.id)}
              >
                <Ic name={option.icon} size={12} />
                <span>{option.label}</span>
              </button>
            ))}
          </div>
        </div>
        <div className="reports-filter-group">
          <span className="reports-filter-label">Date basis</span>
          <div className="reports-basis-locked">
            <Ic name="clock" size={13} />
            Added date
          </div>
        </div>
        {period === "custom" && (
          <div className="reports-custom-range">
            <label>
              <span>Start</span>
              <input type="date" value={customRange.from} onChange={e => setCustomRange(range => ({ ...range, from: e.target.value }))} />
            </label>
            <label>
              <span>End</span>
              <input type="date" value={customRange.to} onChange={e => setCustomRange(range => ({ ...range, to: e.target.value }))} />
            </label>
          </div>
        )}
      </div>

      {!range.valid && (
        <div className="card dashboard-loading-card">
          <Ic name="calendar" size={18} />
          <div>
            <div className="card-title">Choose a custom range</div>
            <div className="card-sub">Pick a start and end day to build the report.</div>
          </div>
        </div>
      )}

      {range.valid && preparing && (
        <div className="card dashboard-loading-card">
          <span className="search-spin" aria-hidden="true"></span>
          <div>
            <div className="card-title">Loading report</div>
            <div className="card-sub">Preparing period money totals.</div>
          </div>
        </div>
      )}

      {range.valid && !preparing && error && (
        <div className="card dashboard-loading-card reports-error-card">
          <Ic name="x" size={18} />
          <div>
            <div className="card-title">Could not load reports</div>
            <div className="card-sub">{error}</div>
          </div>
        </div>
      )}

      {range.valid && !preparing && !error && (
        <React.Fragment>
          <div className="reports-chart-grid">
            <div className="card reports-period-card">
              <div className="card-head">
                <div>
                  <div className="card-title">{periodChartConfig.title}</div>
                  <div className="card-sub">{periodChartConfig.subtitle}</div>
                </div>
              </div>
              <div className="reports-bar-chart">
                <div className="reports-chart-legend">
                  <span><i className="completed"></i>Completed</span>
                  <span><i className="open"></i>Pending/ready</span>
                </div>
                {periodChartRows.length === 0 && (
                  <div className="reports-empty-panel">No period data in this range.</div>
                )}
                {periodChartRows.map(row => {
                  const completed = reportMoney(row.completedMoney);
                  const open = reportMoney(row.openMoney);
                  const total = completed + open;
                  const totalPct = total > 0 ? Math.max(4, (total / maxPeriodChartMoney) * 100) : 0;
                  const completedPct = total > 0 ? (completed / total) * 100 : 0;
                  const openPct = total > 0 ? (open / total) * 100 : 0;
                  const completedOrders = row.completedCount;
                  const openOrders = Math.max(0, row.orderCount - row.completedCount);
                  return (
                    <div key={row.key} className={`reports-chart-row ${row.isCurrent ? "current" : ""}`}>
                      <div className="reports-chart-label">
                        <span>{row.label}</span>
                      </div>
                      <div className="reports-chart-track" aria-label={`${row.label}: ${reportFormatMoney(completed)} completed, ${reportFormatMoney(open)} open`}>
                        {total > 0 && (
                          <span className="reports-chart-fill" style={{ width: `${totalPct}%` }}>
                            <i className="completed" style={{ width: `${completedPct}%` }} />
                            <i className="open" style={{ width: `${openPct}%` }} />
                          </span>
                        )}
                      </div>
                      <div className="reports-chart-money">
                        <b>{reportFormatMoney(completed)}</b>
                        <small>+{reportFormatMoney(open)} open</small>
                        <small>{completedOrders} completed · {openOrders} open</small>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
            <div className="card reports-item-card">
              <div className="card-head">
                <div>
                  <div className="card-title">Selected item</div>
                  <div className="card-sub">
                    {selectedItem
                      ? `${selectedItem.name} · ${reportFormatMoney(selectedItem.completedMoney)} completed · ${selectedItem.completedUnits} sold`
                      : "No items found for this range"}
                  </div>
                </div>
                {itemStats.length > 0 && (
                  <div className="reports-item-controls">
                    <label className="reports-item-search">
                      <Ic name="search" size={14} />
                      <input
                        type="search"
                        value={itemSearch}
                        onFocus={event => {
                          setItemSearchOpen(true);
                          event.currentTarget.select();
                        }}
                        onBlur={() => {
                          window.setTimeout(() => setItemSearchOpen(false), 120);
                        }}
                        onChange={event => {
                          setItemSearch(event.target.value);
                          setItemSearchOpen(true);
                        }}
                        onKeyDown={event => {
                          if (event.key === "Enter" && visibleItemSearchResults[0]) {
                            event.preventDefault();
                            selectReportItem(visibleItemSearchResults[0]);
                          }
                          if (event.key === "Escape") {
                            setItemSearchOpen(false);
                          }
                        }}
                        placeholder="Search and select item..."
                        aria-label="Search item for report chart"
                      />
                    </label>
                    {itemSearchOpen && (
                      <div className="reports-item-results" role="listbox" aria-label="Item search results">
                        {visibleItemSearchResults.length === 0 && (
                          <div className="reports-item-no-results">No item matches</div>
                        )}
                        {visibleItemSearchResults.map(item => (
                          <button
                            key={item.key}
                            type="button"
                            className={`reports-item-result ${selectedItem?.key === item.key ? "active" : ""}`}
                            onMouseDown={event => event.preventDefault()}
                            onClick={() => selectReportItem(item)}
                            role="option"
                            aria-selected={selectedItem?.key === item.key}
                          >
                            <span>{item.name}</span>
                            <small>{reportFormatMoney(item.completedMoney)} · {item.completedUnits} sold</small>
                          </button>
                        ))}
                      </div>
                    )}
                  </div>
                )}
              </div>
              <div className="reports-bar-chart">
                <div className="reports-chart-legend">
                  <span><i className="completed"></i>Completed</span>
                  <span><i className="open"></i>Pending/ready</span>
                </div>
                {!selectedItem && (
                  <div className="reports-empty-panel">No item data in this range.</div>
                )}
                {selectedItem && itemChartRows.map(row => {
                  const completed = reportMoney(row.completedMoney);
                  const open = reportMoney(row.openMoney);
                  const total = completed + open;
                  const totalPct = total > 0 ? Math.max(4, (total / maxItemChartMoney) * 100) : 0;
                  const completedPct = total > 0 ? (completed / total) * 100 : 0;
                  const openPct = total > 0 ? (open / total) * 100 : 0;
                  const completedOrders = row.completedOrderCount;
                  const openOrders = row.openOrderCount;
                  return (
                    <div key={row.key} className={`reports-chart-row ${row.isCurrent ? "current" : ""}`}>
                      <div className="reports-chart-label">
                        <span>{row.label}</span>
                      </div>
                      <div className="reports-chart-track" aria-label={`${row.label}: ${reportFormatMoney(completed)} completed, ${reportFormatMoney(open)} open`}>
                        {total > 0 && (
                          <span className="reports-chart-fill" style={{ width: `${totalPct}%` }}>
                            <i className="completed" style={{ width: `${completedPct}%` }} />
                            <i className="open" style={{ width: `${openPct}%` }} />
                          </span>
                        )}
                      </div>
                      <div className="reports-chart-money">
                        <b>{reportFormatMoney(completed)}</b>
                        <small>+{reportFormatMoney(open)} open</small>
                        <small>{completedOrders} completed · {openOrders} open</small>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
            <div className="card reports-units-card">
              <div className="card-head">
                <div>
                  <div className="card-title">Units sold</div>
                  <div className="card-sub">{reportRangeDateLabel(range)} by added date</div>
                </div>
              </div>
              <div className="reports-units-list">
                {unitSoldRows.length === 0 && (
                  <div className="reports-empty-panel">No completed units sold in this period.</div>
                )}
                {unitSoldRows.map((item, index) => {
                  const soldPct = item.completedUnits > 0 ? Math.max(4, (item.completedUnits / maxUnitSold) * 100) : 0;
                  return (
                    <div key={item.key} className="reports-unit-row">
                      <div className="reports-unit-rank">{index + 1}</div>
                      <div className="reports-unit-name">
                        <span>{item.name}</span>
                        {item.category && <small>{item.category}</small>}
                      </div>
                      <div className="reports-unit-track" aria-label={`${item.name}: ${item.completedUnits} units sold`}>
                        <span className="reports-unit-fill" style={{ width: `${soldPct}%` }} />
                      </div>
                      <div className="reports-unit-value">
                        <b>{item.completedUnits}</b>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          </div>
        </React.Fragment>
      )}
    </div>
  );
};

window.Reports = Reports;
