"use client";

import {
  createContext,
  useContext,
  useRef,
  useState,
  type ReactNode,
} from "react";
import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
import { useTheme } from "@mui/material/styles";
import { useAppLanguage } from "@/components/providers/app-language-provider";
import type { ExportFormat } from "@/components/ui/export-format-menu";
import {
  buildCsvBlob,
  buildXlsxBlob,
  downloadBlob,
  downloadNodeAsPng,
  todayForFilename,
  type ExportTable,
} from "@/lib/export-file";

// Header actions can be supplied by a role's page. Context lets those actions
// export the same displayed data without changing the role's New menu.
const DashboardExportContext = createContext<{
  busy: boolean;
  exportFile: (format: ExportFormat, chart?: string) => void;
} | null>(null);

export const useDashboardExport = () => useContext(DashboardExportContext);

export function DashboardExportProvider({
  children,
  name,
  tables,
  disabled = false,
}: {
  children: ReactNode;
  name: string;
  tables: Record<string, ExportTable[]>;
  disabled?: boolean;
}) {
  const contentRef = useRef<HTMLDivElement>(null);
  const running = useRef(false);
  const [busy, setBusy] = useState(false);
  const [failed, setFailed] = useState(false);
  const theme = useTheme();
  const { language } = useAppLanguage();

  async function exportFile(format: ExportFormat, chart?: string) {
    if (running.current || disabled) return;
    running.current = true;
    setBusy(true);
    setFailed(false);
    try {
      const selectedTables = chart
        ? tables[chart]
        : Object.values(tables).flat();
      if (!selectedTables) throw new Error("Missing chart data");
      const filename = `${name}-${chart ?? "all"}-${todayForFilename()}`;
      if (format === "Image") {
        const content = contentRef.current;
        const node = chart
          ? content?.querySelector<HTMLElement>(
              `[data-dashboard-chart="${chart}"]`,
            )
          : content;
        if (!node) throw new Error("Missing chart element");
        await downloadNodeAsPng(
          node,
          `${filename}.png`,
          theme.palette.background.default,
          true,
        );
      } else {
        const blob =
          format === "CSV"
            ? buildCsvBlob(selectedTables)
            : await buildXlsxBlob(selectedTables);
        downloadBlob(blob, `${filename}.${format === "CSV" ? "csv" : "xlsx"}`);
      }
    } catch {
      setFailed(true);
    } finally {
      running.current = false;
      setBusy(false);
    }
  }

  return (
    <DashboardExportContext.Provider
      value={{ busy: busy || disabled, exportFile }}
    >
      {failed && (
        <Alert severity="error" onClose={() => setFailed(false)} sx={{ mb: 2 }}>
          {language === "kh"
            ? "មិនអាចនាំចេញបានទេ។ សូមព្យាយាមម្តងទៀត។"
            : "Export failed. Please try again."}
        </Alert>
      )}
      <Box ref={contentRef} sx={{ width: "100%" }}>
        {children}
      </Box>
    </DashboardExportContext.Provider>
  );
}

// Each wrapper identifies the PNG region and supplies the existing card menu.
export function DashboardChartExport({
  name,
  children,
}: {
  name: string;
  children: ReactNode;
}) {
  return (
    <ChartExportContext.Provider value={name}>
      <Box data-dashboard-chart={name} sx={{ height: "100%" }}>
        {children}
      </Box>
    </ChartExportContext.Provider>
  );
}
const ChartExportContext = createContext<string | undefined>(undefined);
export const useDashboardChartExport = () => useContext(ChartExportContext);
