"use client";

import { useCallback, useMemo, useState } from "react";

import { useRouter } from "next/navigation";

import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
import CircularProgress from "@mui/material/CircularProgress";

import { ToastNotification } from "@/components/ui/toast-notification";
import { ProgressReportPageContainer } from "@/features/ministry/progress-report/components/progress-report-page-container";
import { useAppLanguage } from "@/components/providers/app-language-provider";
import { ProgressReportDecisionsSection } from "./progress-report-decisions-section";
import type { MinistryProgressReportDecisionRow } from "./progress-report-decisions-data";

import {
  mapMinistryOpenIssuesToRows,
  mapApiProgressReportToDetail,
  mapMinistryRgcDecisionsToRows,
} from "../../progress-report-detail-data";
import {
  canMinistryUploadDocument,
  type ApiRgcDecisionStatus,
} from "../../service/progress-report-service";
import { getProgressReportWorkflowActions } from "../../progress-report-workflow";
import {
  useProgressReport,
  useSubmitMyProgressReport,
  useUpdateMyProgressReport,
  useUpsertMyProgressReportIssue,
  useUpsertMyProgressReportRgcDecision,
} from "../../hook/use-progress-reports";
import { ProgressReportDetailHeader } from "./progress-report-detail-header";
import { ProgressReportDescriptionSection } from "./progress-report-description-section";
import { ProgressReportDetailInfoSection } from "./progress-report-detail-info-section";
import { ProgressReportDocumentSection } from "./progress-report-document-section";
import { ProgressReportIssuesSection } from "./progress-report-issues-section";
import type { MinistryProgressReportIssueRow } from "./progress-report-issues-data";
import { buildProgressReportIssuesPrintModel } from "./print/progress-report-issues-print-model";
import { ProgressReportIssuesPrintView } from "./print/progress-report-issues-print-view";
import { UpdateProgressReportDecisionDrawer } from "./update-progress-report-decision-drawer";
import type { UpdateProgressReportDecisionSavePayload } from "./update-progress-report-decision-drawer";
import { ProgressReportViewCommentDrawer } from "./progress-report-add-comment-drawer";
import { UpdateProgressReportIssueDialog } from "./update-progress-report-issue-dialog";
import type { UpdateProgressReportIssueSavePayload } from "./update-progress-report-issue-dialog";

type ProgressReportDetailScreenProps = {
  id: string;
};

function toApiRgcDecisionStatus(
  status: MinistryProgressReportDecisionRow["status"],
): ApiRgcDecisionStatus {
  if (status === "Solved") return "SOLVED";
  if (status === "In Progress") return "IN_PROGRESS";
  return "NOT_ADDRESSED";
}

export function ProgressReportDetailScreen({
  id,
}: ProgressReportDetailScreenProps) {
  const router = useRouter();
  const { language } = useAppLanguage();
  const { assignment, isValidId, isLoading, error } = useProgressReport(id);
  const progressReportId = Number(id);
  const uploadProgressDocument = useUpdateMyProgressReport(progressReportId);
  const submitProgressReport = useSubmitMyProgressReport(progressReportId);
  const updateProgressIssue =
    useUpsertMyProgressReportIssue(progressReportId);
  const updateProgressRgcDecision =
    useUpsertMyProgressReportRgcDecision(progressReportId);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);
  const detail = useMemo(
    () =>
      assignment
        ? mapApiProgressReportToDetail(assignment, language)
        : null,
    [assignment, language],
  );
  const apiIssueRows = useMemo(
    () => mapMinistryOpenIssuesToRows(assignment?.openIssues ?? []),
    [assignment?.openIssues],
  );
  const issueRows = apiIssueRows;
  const issuePrintModel = useMemo(
    () => (detail ? buildProgressReportIssuesPrintModel(detail, issueRows) : null),
    [detail, issueRows],
  );
  const [selectedIssue, setSelectedIssue] =
    useState<MinistryProgressReportIssueRow | null>(null);
  const [commentIssue, setCommentIssue] =
    useState<MinistryProgressReportIssueRow | null>(null);
  const apiDecisionRows = useMemo(
    () =>
      assignment
        ? mapMinistryRgcDecisionsToRows(
            assignment.rgcDecisions,
            assignment.ministry,
          )
        : [],
    [assignment],
  );
  const decisionRows = apiDecisionRows;
  const [selectedDecision, setSelectedDecision] =
    useState<MinistryProgressReportDecisionRow | null>(null);
  const [commentDecision, setCommentDecision] =
    useState<MinistryProgressReportDecisionRow | null>(null);

  const handleUpdateIssue = useCallback((row: MinistryProgressReportIssueRow) => {
    setSelectedIssue(row);
  }, []);

  const handleViewComment = useCallback((row: MinistryProgressReportIssueRow) => {
    setCommentIssue(row);
  }, []);

  const handleUpdateDecision = useCallback(
    (row: MinistryProgressReportDecisionRow) => {
      setSelectedDecision(row);
    },
    [],
  );

  const handleViewDecisionComment = useCallback(
    (row: MinistryProgressReportDecisionRow) => {
      setCommentDecision(row);
    },
    [],
  );

  const handleSaveDecision = useCallback(
    async ({
      decision,
      status,
      indicators,
      progressSolution,
      implementationChallenges,
      requests,
      sourceOfVerification,
      linkToVerificationSource,
      nextStep,
      dateOfIssueSolution,
      attachment,
    }: UpdateProgressReportDecisionSavePayload) => {
      await updateProgressRgcDecision.mutateAsync({
        plenaryDecisionId: decision.id,
        status: toApiRgcDecisionStatus(status),
        category: decision.category,
        meetingDate: decision.meetingDate,
        focalPerson: decision.focalPerson,
        decision: decision.rgcDecision,
        indicators,
        progressSolution,
        implementationChallenges,
        requests,
        sourceOfVerification,
        linkToVerificationSource,
        nextStep,
        dateOfIssueSolution,
        attachment,
      });
      setSuccessMessage("RGC Decision progress updated successfully.");
    },
    [updateProgressRgcDecision],
  );

  const handleSaveIssue = useCallback(
    async ({
      issue,
      issueStatusId,
      indicators,
      progressSolution,
      implementationChallenges,
      requests,
      sourceOfVerification,
      linkToVerificationSource,
      nextStep,
      dateOfIssueSolution,
      attachment,
    }: UpdateProgressReportIssueSavePayload) => {
      await updateProgressIssue.mutateAsync({
        issueId: issue.id,
        issueStatusId,
        indicators,
        progressSolution,
        implementationChallenges,
        requests,
        sourceOfVerification,
        linkToVerificationSource,
        nextStep,
        dateOfIssueSolution,
        attachment,
      });
      setSuccessMessage("Issue progress updated successfully.");
    },
    [updateProgressIssue],
  );

  const handleUploadProgressDocument = useCallback(
    async (file: File) => {
      if (!assignment) {
        throw new Error("Progress report is not loaded.");
      }

      if (!canMinistryUploadDocument(assignment.status)) {
        throw new Error(
          "Progress document upload is unavailable for the current report status.",
        );
      }

      // Omit the status so the report keeps its current status; uploading a
      // document never advances the workflow on its own.
      await uploadProgressDocument.mutateAsync({ file });
    },
    [assignment, uploadProgressDocument],
  );

  const handleShareWithPswg = useCallback(async () => {
    await uploadProgressDocument.mutateAsync({ status: "SHARED_WITH_PSWG" });
    setSuccessMessage("Progress report shared with PSWG successfully.");
  }, [uploadProgressDocument]);

  const handleSaveDraft = useCallback(async () => {
    // Save in place: omit the status so the report keeps its current status
    // instead of advancing the workflow.
    await uploadProgressDocument.mutateAsync({});
    setSuccessMessage("Progress report draft saved successfully.");
  }, [uploadProgressDocument]);

  const handleSubmitToCdc = useCallback(async () => {
    await submitProgressReport.mutateAsync();
    setSuccessMessage("Progress report submitted to CDC successfully.");
  }, [submitProgressReport]);

  if (isLoading) {
    return (
      <ProgressReportPageContainer>
        <Box
          sx={{
            minHeight: 320,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
          }}
        >
          <CircularProgress />
        </Box>
      </ProgressReportPageContainer>
    );
  }

  if (!isValidId || error || !assignment || !detail) {
    const message = !isValidId
      ? "Invalid progress report ID."
      : error || "Progress report not found.";

    return (
      <ProgressReportPageContainer>
        <Alert severity="error">{message}</Alert>
      </ProgressReportPageContainer>
    );
  }

  const approvalDocument =
    assignment.ministryInformation.approvalProgressReport;
  const workflowActions = getProgressReportWorkflowActions(
    assignment.status,
    Boolean(approvalDocument),
  );
  const isUpdating =
    uploadProgressDocument.isPending || submitProgressReport.isPending;

  return (
    <ProgressReportPageContainer>
      <Box
        sx={{
          display: "flex",
          flexDirection: "column",
          gap: 3,
          width: "100%",
          maxWidth: "100%",
          overflowX: "hidden",
        }}
      >
        <ProgressReportDetailHeader
          title={detail.title}
          ministryName={detail.ministryName}
          ministryLogo={detail.ministryLogo}
          canShare={workflowActions.canShare}
          canSaveDraft={workflowActions.canSaveDraft}
          canSubmit={workflowActions.canSubmit}
          isUpdating={isUpdating}
          onBack={() => router.push("/ministry/progress-reports")}
          onShare={handleShareWithPswg}
          onSaveDraft={handleSaveDraft}
          onSubmit={handleSubmitToCdc}
        />

        <ProgressReportDetailInfoSection detail={detail} />

        <ProgressReportDescriptionSection description={detail.description} />

        <ProgressReportIssuesSection
          rows={issueRows}
          onUpdateIssue={handleUpdateIssue}
          onViewComment={handleViewComment}
          onPrint={() => window.print()}
        />
        <ProgressReportDecisionsSection
          rows={decisionRows}
          onUpdateIssue={handleUpdateDecision}
          onViewComment={handleViewDecisionComment}
        />
        <ProgressReportDocumentSection
          attachment={approvalDocument}
          assignmentStatus={assignment.status}
          isUploading={uploadProgressDocument.isPending}
          onUpload={handleUploadProgressDocument}
        />

        <UpdateProgressReportIssueDialog
          open={Boolean(selectedIssue)}
          issue={selectedIssue}
          onClose={() => setSelectedIssue(null)}
          onSave={handleSaveIssue}
          issueAttachment={selectedIssue?.progressUpdateAttachment ?? null}
        />

        <ProgressReportViewCommentDrawer
          open={Boolean(commentIssue)}
          comment={
            commentIssue?.cdcComment
              ? {
                  commentType: commentIssue.cdcComment.commentType.name,
                  comment: commentIssue.cdcComment.comment,
                  authorName: commentIssue.cdcComment.author.name,
                }
              : null
          }
          onClose={() => setCommentIssue(null)}
        />

        <ProgressReportViewCommentDrawer
          open={Boolean(commentDecision)}
          comment={
            commentDecision?.cdcComment
              ? {
                  commentType: commentDecision.cdcComment.commentType.name,
                  comment: commentDecision.cdcComment.comment,
                  authorName: commentDecision.cdcComment.author.name,
                }
              : null
          }
          onClose={() => setCommentDecision(null)}
        />

        <UpdateProgressReportDecisionDrawer
          open={Boolean(selectedDecision)}
          decision={selectedDecision}
          onClose={() => setSelectedDecision(null)}
          onSave={handleSaveDecision}
        />

        <ToastNotification
          open={Boolean(successMessage)}
          message={successMessage ?? ""}
          onClose={() => setSuccessMessage(null)}
        />

        {issuePrintModel ? (
          <ProgressReportIssuesPrintView model={issuePrintModel} />
        ) : null}
      </Box>
    </ProgressReportPageContainer>
  );
}

export default ProgressReportDetailScreen;
