"use client";

import Link from "next/link";
import { useParams } from "next/navigation";
import { useRef, useState } from "react";

import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import CircularProgress from "@mui/material/CircularProgress";
import Typography from "@mui/material/Typography";
import { useTheme } from "@mui/material/styles";

import { useAppLanguage } from "@/components/providers/app-language-provider";
import { AlertDialog } from "@/components/ui/alert-dialog";
import { AppSecondaryButton } from "@/components/ui/button";
import { ExportButton } from "@/components/ui/export-button";
import type { ExportFormat } from "@/components/ui/export-format-menu";
import { ToastNotification } from "@/components/ui/toast-notification";
import { formatDate } from "@/lib/date-utils";
import { formatNumber } from "@/lib/number-utils";
import {
  buildCsvBlob,
  buildXlsxBlob,
  downloadBlob,
  downloadNodeAsPng,
  type ExportTable,
} from "@/lib/export-file";
import { AgencyStatusCard } from "@/features/cdc-gpsf/plenary/dashboard/components/charts/agency-status-card";
import { ImplementationStatusCard } from "@/features/cdc-gpsf/plenary/dashboard/components/charts/implementation-status-card";
import { MeasureCategoryCard } from "@/features/cdc-gpsf/plenary/dashboard/components/charts/measure-category-card";
import { WorkingGroupNameCard } from "@/features/cdc-gpsf/plenary/dashboard/components/charts/working-group-name-card";
import { PlenaryPageContainer } from "@/features/cdc-gpsf/plenary/dashboard/components/plenary-page-container";

import { useProgressReport } from "../../hook/use-progress-reports";
import {
  normalizeProgressReportLanguage,
  progressReportText,
} from "../../progress-report-i18n";

import { DraftDashboardSummaryCards } from "./draft-dashboard-summary-cards";
import type { DraftDashboardStage } from "./draft-dashboard-service";
import {
  mapPlenaryAgencyRows,
  mapPlenaryCardsToSummary,
  mapPlenaryCategoryRows,
  mapPlenaryInProgressDonut,
  mapPlenaryOverallDonut,
  mapPlenaryWorkingGroupRows,
} from "./plenary-draft-dashboard-mapper";
import {
  useDraftDashboard,
  useGenerateDraftDashboard,
  usePublishLiveDashboard,
} from "./use-draft-dashboard";

type PlenaryDraftDashboardScreenProps = {
  // The same page serves the draft and the final dashboard; only the saved
  // numbers and a few words differ.
  stage?: DraftDashboardStage;
};

export function PlenaryDraftDashboardScreen({
  stage = "draft",
}: PlenaryDraftDashboardScreenProps = {}) {
  const theme = useTheme();
  const params = useParams<{ id: string }>();
  const reportId = params.id ?? "";
  const { language } = useAppLanguage();
  const labels = progressReportText[normalizeProgressReportLanguage(language)];
  const dashboardLabels = labels.draftDashboard;
  const chartLabels = dashboardLabels.plenaryCharts;
  const { report } = useProgressReport(reportId);
  const isFinal = stage === "final";

  // The plenary dashboard counts the RGC decisions, so it reads its own saved
  // numbers — the working group one is untouched.
  const { dashboard, isValidId, isLoading, error } = useDraftDashboard(
    reportId,
    stage,
    "plenary",
  );
  const { mutateAsync: generateDashboard, isPending: isGenerating } =
    useGenerateDraftDashboard(stage, "plenary");

  const { mutateAsync: publishLiveDashboard, isPending: isPublishing } =
    usePublishLiveDashboard("plenary");
  const [toastMessage, setToastMessage] = useState("");
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [liveConfirmOpen, setLiveConfirmOpen] = useState(false);
  const [actionError, setActionError] = useState("");
  const [exporting, setExporting] = useState(false);
  const contentRef = useRef<HTMLDivElement | null>(null);

  // Recalculates from the RGC decisions and saves the result, replacing the
  // numbers saved before — which is why it asks first.
  const handleGenerate = async () => {
    if (!isValidId || isGenerating) return;

    setConfirmOpen(false);
    setActionError("");

    try {
      await generateDashboard(Number(reportId));
      setToastMessage(
        isFinal
          ? dashboardLabels.plenaryFinalGenerated
          : dashboardLabels.plenaryGenerated,
      );
    } catch (generateError) {
      setActionError(
        generateError instanceof Error
          ? generateError.message
          : isFinal
            ? dashboardLabels.plenaryFinalFailed
            : dashboardLabels.plenaryFailed,
      );
    }
  };

  // "Live": hands the saved final numbers to every plenary dashboard. Nothing
  // is recalculated, so what they see is what is on screen here.
  const handlePublishLive = async () => {
    if (!isValidId || isPublishing) return;

    setLiveConfirmOpen(false);
    setActionError("");

    try {
      await publishLiveDashboard(Number(reportId));
      setToastMessage(dashboardLabels.livePublished);
    } catch (publishError) {
      setActionError(
        publishError instanceof Error
          ? publishError.message
          : dashboardLabels.liveFailed,
      );
    }
  };

  const cards = dashboard?.cards ?? null;
  const pageError = !isValidId
    ? dashboardLabels.invalidReportId
    : error || (!isLoading && !cards ? dashboardLabels.loadError : null);

  // Rows are built once and shared by the charts and the export, so a
  // downloaded file always matches what is on screen.
  const agencyRows = mapPlenaryAgencyRows(dashboard?.byPrimaryAgency ?? []);
  const categoryRows = mapPlenaryCategoryRows(
    dashboard?.byCategory ?? [],
    chartLabels.other,
  );
  const workingGroupRows = mapPlenaryWorkingGroupRows(
    dashboard?.byWorkingGroup ?? [],
    chartLabels.other,
  );
  const overallDonut = cards
    ? mapPlenaryOverallDonut(
        cards,
        { solved: chartLabels.solved, inProgress: chartLabels.inProgress },
        theme.palette.success.main,
        language,
      )
    : [];
  const inProgressDonut = cards
    ? mapPlenaryInProgressDonut(
        cards,
        {
          midProgress: chartLabels.midProgress,
          earlyProgress: chartLabels.earlyProgress,
        },
        language,
      )
    : [];

  // The tables behind the Export button: one sheet per chart.
  const exportTables: ExportTable[] | null = cards
    ? [
        {
          title: chartLabels.overallStatus,
          headers: [chartLabels.solved, chartLabels.inProgress],
          rows: [[String(cards.solved), String(cards.inProgress)]],
        },
        {
          title: chartLabels.inProgressStatus,
          headers: [chartLabels.midProgress, chartLabels.earlyProgress],
          rows: [
            [String(cards.midProgress ?? 0), String(cards.earlyProgress ?? 0)],
          ],
        },
        {
          title: chartLabels.primaryAgencies,
          headers: ["", chartLabels.solved, chartLabels.inProgress],
          rows: agencyRows.map((row) => [
            row.name,
            String(row.solved),
            String(row.inProgress),
          ]),
        },
        {
          title: chartLabels.measureCategory,
          headers: ["", chartLabels.solved, chartLabels.inProgress],
          rows: categoryRows.map((row) => [
            row.label,
            String(row.solved),
            String(row.inProgress),
          ]),
        },
        {
          title: chartLabels.workingGroupName,
          headers: ["", chartLabels.solved, chartLabels.inProgress],
          rows: workingGroupRows.map((row) => [
            row.label,
            String(row.solved),
            String(row.inProgress),
          ]),
        },
      ]
    : null;

  const runExport = async (format: ExportFormat) => {
    if (!exportTables || exporting) return;

    setExporting(true);
    setActionError("");

    const fileName = `plenary-${stage}-dashboard`;

    try {
      if (format === "CSV") {
        downloadBlob(buildCsvBlob(exportTables), `${fileName}.csv`);
      } else if (format === "XLSX") {
        downloadBlob(await buildXlsxBlob(exportTables), `${fileName}.xlsx`);
      } else if (contentRef.current) {
        await downloadNodeAsPng(
          contentRef.current,
          `${fileName}.png`,
          theme.palette.background.default,
        );
      }
    } catch (downloadError) {
      setActionError(
        downloadError instanceof Error
          ? downloadError.message
          : dashboardLabels.exportError,
      );
    } finally {
      setExporting(false);
    }
  };

  const semesterLabel =
    report?.semester === "S2"
      ? dashboardLabels.semesterTwo
      : dashboardLabels.semesterOne;
  const title = isFinal
    ? dashboardLabels.plenaryFinalTitle(semesterLabel)
    : dashboardLabels.plenaryTitle(semesterLabel);
  // Every number on the page is written in the current language's digits.
  const toPageNumber = (value: number) => formatNumber(value, language);
  const backHref = "/cdc-gpsf/progress-reports";

  return (
    <PlenaryPageContainer>
      <Box
        sx={{
          display: "flex",
          flexDirection: "column",
          gap: 3,
          color: theme.palette.text.primary,
        }}
      >
        <Box
          sx={{
            display: "flex",
            flexWrap: "wrap",
            alignItems: "center",
            justifyContent: "space-between",
            gap: 2,
          }}
        >
          <Box
            sx={{
              display: "flex",
              alignItems: "center",
              gap: { xs: 1.5, md: "23px" },
              minWidth: 0,
            }}
          >
            <AppSecondaryButton
              component={Link}
              href={backHref}
              startIcon={<ArrowBackIosNewIcon sx={{ fontSize: 14 }} />}
              sx={{
                width: 104,
                minWidth: 104,
                height: 40,
                bgcolor: "transparent",
                borderColor: "transparent",
                color: theme.palette.text.secondary,
                "&:hover": {
                  bgcolor: theme.palette.action.hover,
                  borderColor: "transparent",
                },
              }}
            >
              {dashboardLabels.back}
            </AppSecondaryButton>

            <Typography
              sx={{
                fontSize: { xs: 20, md: 24 },
                fontWeight: 700,
                lineHeight: 1.2,
                color: theme.palette.text.primary,
              }}
            >
              {title}
            </Typography>
          </Box>

          <Box
            sx={{
              display: "flex",
              flexDirection: "column",
              alignItems: "flex-end",
              gap: 0.75,
            }}
          >
            <Box sx={{ display: "flex", alignItems: "center", gap: 1.5 }}>
              {/* Saves the numbers currently on screen. */}
              <Button
                variant="contained"
                disabled={!isValidId || isGenerating}
                onClick={() => setConfirmOpen(true)}
                startIcon={
                  isGenerating ? (
                    <CircularProgress size={14} color="inherit" />
                  ) : undefined
                }
                sx={{
                  height: 40,
                  px: 2,
                  borderRadius: "6px",
                  bgcolor: "#1a64a8",
                  color: "#ffffff",
                  boxShadow: "none",
                  textTransform: "none",
                  fontSize: 13,
                  fontWeight: 500,
                  whiteSpace: "nowrap",
                  "&:hover": { bgcolor: "#155489", boxShadow: "none" },
                }}
              >
                {isGenerating
                  ? dashboardLabels.generating
                  : isFinal
                    ? dashboardLabels.generateFinal
                    : dashboardLabels.generate}
              </Button>

              {/* Only a generated final dashboard can be published, so the
                  button appears once there are saved numbers. */}
              {isFinal && dashboard?.generatedAt ? (
                <Button
                  variant="outlined"
                  disabled={!isValidId || isPublishing}
                  onClick={() => setLiveConfirmOpen(true)}
                  startIcon={
                    isPublishing ? (
                      <CircularProgress size={14} color="inherit" />
                    ) : undefined
                  }
                  sx={{
                    height: 40,
                    px: 2,
                    borderRadius: "6px",
                    borderColor: "#1a64a8",
                    color: "#1a64a8",
                    textTransform: "none",
                    fontSize: 13,
                    fontWeight: 500,
                    whiteSpace: "nowrap",
                    "&:hover": {
                      borderColor: "#155489",
                      bgcolor: theme.palette.action.hover,
                    },
                  }}
                >
                  {isPublishing
                    ? dashboardLabels.livePublishing
                    : dashboardLabels.live}
                </Button>
              ) : null}

              <ExportButton
                compact
                showMenu
                loading={exporting}
                disabled={!exportTables}
                onExport={(format) => void runExport(format)}
              >
                {dashboardLabels.export}
              </ExportButton>
            </Box>

            {/* When the numbers on screen were last saved. */}
            <Typography
              sx={{ fontSize: 12, color: theme.palette.text.secondary }}
            >
              {dashboard?.generatedAt
                ? `${dashboardLabels.lastUpdate}: ${formatDate(
                    dashboard.generatedAt,
                    language,
                    "dd MMMM yyyy, HH:mm",
                  )}`
                : dashboardLabels.notGeneratedYet}
            </Typography>
          </Box>
        </Box>

        {actionError ? <Alert severity="error">{actionError}</Alert> : null}

        {isLoading ? (
          <Box
            sx={{
              minHeight: 320,
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
            }}
          >
            <CircularProgress size={32} />
          </Box>
        ) : pageError || !cards ? (
          <Alert severity="error">
            {pageError || dashboardLabels.loadError}
          </Alert>
        ) : (
          <Box
            ref={contentRef}
            sx={{ display: "flex", flexDirection: "column", gap: 3 }}
          >
            <DraftDashboardSummaryCards
              summary={mapPlenaryCardsToSummary(cards)}
              labels={dashboardLabels.cards}
              formatNumber={toPageNumber}
            />

            <Box
              sx={{
                display: "flex",
                flexWrap: { xs: "wrap", md: "nowrap" },
                alignItems: "stretch",
                gap: 3,
              }}
            >
              <Box
                sx={{ flex: { xs: "1 1 100%", md: "0 0 486px" }, minWidth: 0 }}
              >
                <ImplementationStatusCard
                  overallCenterValue={toPageNumber(cards.totalIssues)}
                  inProgressCenterValue={toPageNumber(cards.inProgress)}
                  overallData={overallDonut}
                  inProgressData={inProgressDonut}
                  labels={{
                    overallTitle: chartLabels.overallStatus,
                    inProgressTitle: chartLabels.inProgressStatus,
                    totalIssues: chartLabels.totalIssues,
                    inProgress: chartLabels.inProgress,
                    solved: chartLabels.solved,
                    midProgress: chartLabels.midProgress,
                    earlyProgress: chartLabels.earlyProgress,
                  }}
                />
              </Box>
              <Box
                sx={{ flex: { xs: "1 1 100%", md: "1 1 666px" }, minWidth: 0 }}
              >
                <AgencyStatusCard
                  rows={agencyRows}
                  labels={{
                    title: chartLabels.primaryAgencies,
                    solved: chartLabels.solved,
                    inProgress: chartLabels.inProgress,
                    notAddressed: chartLabels.notAddressed,
                  }}
                />
              </Box>
            </Box>

            <Box
              sx={{
                display: "flex",
                flexWrap: { xs: "wrap", md: "nowrap" },
                alignItems: "stretch",
                gap: 2.75,
              }}
            >
              <Box sx={{ flex: { xs: "1 1 100%", md: "1 1 0" }, minWidth: 0 }}>
                <MeasureCategoryCard
                  title={chartLabels.measureCategory}
                  rows={categoryRows}
                  labels={{
                    solved: chartLabels.solved,
                    inProgress: chartLabels.inProgress,
                    notAddressed: chartLabels.notAddressed,
                    status: chartLabels.status,
                  }}
                />
              </Box>
              <Box sx={{ flex: { xs: "1 1 100%", md: "1 1 0" }, minWidth: 0 }}>
                <WorkingGroupNameCard
                  title={chartLabels.workingGroupName}
                  rows={workingGroupRows}
                  labels={{
                    solved: chartLabels.solved,
                    inProgress: chartLabels.inProgress,
                    notAddressed: chartLabels.notAddressed,
                    status: chartLabels.status,
                  }}
                />
              </Box>
            </Box>
          </Box>
        )}
      </Box>

      <AlertDialog
        open={confirmOpen}
        title={
          isFinal
            ? dashboardLabels.confirmFinalTitle
            : dashboardLabels.confirmTitle
        }
        description={
          isFinal
            ? dashboardLabels.confirmFinalDescription
            : dashboardLabels.confirmDescription
        }
        confirmLabel={dashboardLabels.confirm}
        cancelLabel={dashboardLabels.cancel}
        loading={isGenerating}
        onConfirm={() => void handleGenerate()}
        onCancel={() => setConfirmOpen(false)}
      />

      <AlertDialog
        open={liveConfirmOpen}
        title={dashboardLabels.confirmLiveTitle}
        description={dashboardLabels.confirmPlenaryLiveDescription}
        confirmLabel={dashboardLabels.live}
        cancelLabel={dashboardLabels.cancel}
        loading={isPublishing}
        onConfirm={() => void handlePublishLive()}
        onCancel={() => setLiveConfirmOpen(false)}
      />

      <ToastNotification
        open={Boolean(toastMessage)}
        message={toastMessage}
        onClose={() => setToastMessage("")}
      />
    </PlenaryPageContainer>
  );
}
