import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import apiClient from "@app/services/apiClient";
import { useFileContext } from "@app/contexts/file/fileHooks";
import { ToolOperationHook } from "@app/hooks/tools/shared/useToolOperation";
import type { StirlingFile } from "@app/types/fileContext";
import { extractErrorMessage } from "@app/utils/toolErrorHandler";
import {
  SignatureValidationBackendResult,
  SignatureValidationFileResult,
  SignatureValidationReportEntry,
} from "@app/types/validateSignature";
import { ValidateSignatureParameters } from "@app/hooks/tools/validateSignature/useValidateSignatureParameters";
import { buildReportEntries } from "@app/hooks/tools/validateSignature/utils/signatureReportBuilder";
import { createReportPdf } from "@app/hooks/tools/validateSignature/signatureReportPdf";
import { createCsvFile as buildCsvFile } from "@app/hooks/tools/validateSignature/utils/signatureCsv";
import {
  normalizeBackendResult,
  RESULT_JSON_FILENAME,
} from "@app/hooks/tools/validateSignature/utils/signatureUtils";

export interface ValidateSignatureOperationHook extends ToolOperationHook<ValidateSignatureParameters> {
  results: SignatureValidationReportEntry[];
}

export const useValidateSignatureOperation =
  (): ValidateSignatureOperationHook => {
    const { t } = useTranslation();
    const { selectors } = useFileContext();
    const [isLoading, setIsLoading] = useState(false);
    const [status, setStatus] = useState("");
    const [errorMessage, setErrorMessage] = useState<string | null>(null);
    const [files, setFiles] = useState<File[]>([]);
    const [downloadUrl, setDownloadUrl] = useState<string | null>(null);
    const [downloadFilename, setDownloadFilename] = useState("");
    const [results, setResults] = useState<SignatureValidationReportEntry[]>(
      [],
    );

    const cancelRequested = useRef(false);
    const previousUrl = useRef<string | null>(null);

    const cleanupDownloadUrl = useCallback(() => {
      if (previousUrl.current) {
        URL.revokeObjectURL(previousUrl.current);
        previousUrl.current = null;
      }
    }, []);

    const resetResults = useCallback(() => {
      cancelRequested.current = false;
      setResults([]);
      setFiles([]);
      cleanupDownloadUrl();
      setDownloadUrl(null);
      setDownloadFilename("");
      setStatus("");
      setErrorMessage(null);
    }, [cleanupDownloadUrl]);

    const clearError = useCallback(() => {
      setErrorMessage(null);
    }, []);

    const executeOperation = useCallback(
      async (
        params: ValidateSignatureParameters,
        selectedFiles: StirlingFile[],
      ) => {
        if (selectedFiles.length === 0) {
          setErrorMessage(t("noFileSelected", "No files selected"));
          return;
        }

        cancelRequested.current = false;
        setIsLoading(true);
        setStatus(
          t("validateSignature.processing", "Validating signatures..."),
        );
        setErrorMessage(null);
        setResults([]);
        setFiles([]);
        cleanupDownloadUrl();
        setDownloadUrl(null);
        setDownloadFilename("");

        try {
          const aggregated: SignatureValidationFileResult[] = [];

          for (const file of selectedFiles) {
            if (cancelRequested.current) {
              break;
            }

            const formData = new FormData();
            formData.append("fileInput", file);
            if (params.certFile) {
              formData.append("certFile", params.certFile);
            }

            try {
              const response = await apiClient.post(
                "/api/v1/security/validate-signature",
                formData,
              );

              const data = Array.isArray(response.data)
                ? (response.data as SignatureValidationBackendResult[])
                : [];
              const signatures = data.map((item, index) =>
                normalizeBackendResult(item, file, index),
              );

              aggregated.push({
                fileId: file.fileId,
                fileName: file.name,
                signatures,
                error: null,
                fileSize: file.size ?? null,
                lastModified: file.lastModified ?? null,
              });
            } catch (error) {
              aggregated.push({
                fileId: file.fileId,
                fileName: file.name,
                signatures: [],
                error: extractErrorMessage(error),
                fileSize: file.size ?? null,
                lastModified: file.lastModified ?? null,
              });
            }
          }

          if (!cancelRequested.current) {
            const summaryTimestamp = Date.now();
            const enrichedEntries = buildReportEntries({
              results: aggregated,
              selectors,
              generatedAt: summaryTimestamp,
              t,
            });

            setResults(enrichedEntries);

            if (enrichedEntries.length > 0) {
              const json = JSON.stringify(enrichedEntries, null, 2);
              const resultFile = new File([json], RESULT_JSON_FILENAME, {
                type: "application/json",
              });
              const csvFile = buildCsvFile(enrichedEntries);

              setFiles([resultFile, csvFile]);

              (async () => {
                try {
                  const pdfFile = await createReportPdf(enrichedEntries, t);
                  setFiles((prev) => [
                    pdfFile,
                    ...prev.filter(
                      (f) => !f.name.toLowerCase().endsWith(".pdf"),
                    ),
                  ]);
                  setDownloadFilename(pdfFile.name);
                  cleanupDownloadUrl();
                  const blobUrl = URL.createObjectURL(pdfFile);
                  previousUrl.current = blobUrl;
                  setDownloadUrl(blobUrl);
                } catch (err) {
                  console.warn(
                    "[validateSignature] PDF report generation failed",
                    err,
                  );
                  setErrorMessage(
                    (prev) =>
                      prev ??
                      t(
                        "validateSignature.error.reportGeneration",
                        "Could not generate the PDF report. JSON and CSV are available.",
                      ),
                  );
                }
              })();
            }

            const anyError = aggregated.some((item) => item.error);
            const anySuccess = aggregated.some(
              (item) => item.signatures.length > 0,
            );

            if (anyError && !anySuccess) {
              setErrorMessage(
                t(
                  "validateSignature.error.allFailed",
                  "Unable to validate the selected files.",
                ),
              );
            } else if (anyError) {
              setErrorMessage(
                t(
                  "validateSignature.error.partial",
                  "Some files could not be validated.",
                ),
              );
            }

            setStatus(
              t("validateSignature.status.complete", "Validation complete"),
            );
          }
        } catch (e) {
          console.error("[validateSignature] unexpected failure", e);
          setErrorMessage(
            t(
              "validateSignature.error.unexpected",
              "Unexpected error during validation.",
            ),
          );
        } finally {
          setIsLoading(false);
        }
      },
      [cleanupDownloadUrl, selectors, t],
    );

    const cancelOperation = useCallback(() => {
      if (isLoading) {
        cancelRequested.current = true;
        setIsLoading(false);
        setStatus(t("operationCancelled", "Operation cancelled"));
      }
    }, [isLoading, t]);

    const undoOperation = useCallback(async () => {
      resetResults();
    }, [resetResults]);

    useEffect(() => {
      return () => {
        cleanupDownloadUrl();
      };
    }, [cleanupDownloadUrl]);

    return useMemo<ValidateSignatureOperationHook>(
      () => ({
        files,
        thumbnails: [],
        isGeneratingThumbnails: false,
        downloadUrl,
        downloadFilename,
        isLoading,
        status,
        errorMessage,
        progress: null,
        executeOperation,
        resetResults,
        clearError,
        cancelOperation,
        undoOperation,
        results,
      }),
      [
        cancelOperation,
        clearError,
        downloadFilename,
        downloadUrl,
        errorMessage,
        executeOperation,
        files,
        isLoading,
        resetResults,
        results,
        status,
      ],
    );
  };
