import { configContext } from "ConfigContext";
import React from "react";
import { userContext } from "UserContext";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { armRequest } from "../../../Utils/arm/request";
import ContainerCopyMessages from "../ContainerCopyMessages";
import {
    buildDataTransferJobPath,
    convertTime,
    convertToCamelCase,
    COPY_JOB_API_VERSION,
    COSMOS_SQL_COMPONENT,
    extractErrorMessage,
    formatUTCDateTime
} from "../CopyJobUtils";
import CreateCopyJobScreensProvider from "../CreateCopyJob/Screens/CreateCopyJobScreensProvider";
import { CopyJobStatusType } from "../Enums";
import { MonitorCopyJobsRefState } from "../MonitorCopyJobs/MonitorCopyJobRefState";
import { CopyJobContextState, CopyJobError, CopyJobType, DataTransferJobType } from "../Types";

export const openCreateCopyJobPanel = () => {
    const sidePanelState = useSidePanel.getState()
    sidePanelState.setPanelHasConsole(false);
    sidePanelState.openSidePanel(
        ContainerCopyMessages.createCopyJobPanelTitle,
        <CreateCopyJobScreensProvider />,
        "650px"
    );
}

let copyJobsAbortController: AbortController | null = null;

export const getCopyJobs = async (): Promise<CopyJobType[]> => {
    // Abort previous request if still in-flight
    if (copyJobsAbortController) {
        copyJobsAbortController.abort();
    }
    copyJobsAbortController = new AbortController();
    try {
        const path = buildDataTransferJobPath({
            subscriptionId: userContext.subscriptionId,
            resourceGroup: userContext.databaseAccount?.resourceGroup || "",
            accountName: userContext.databaseAccount?.name || ""
        });

        const response: { value: DataTransferJobType[] } = await armRequest({
            host: configContext.ARM_ENDPOINT,
            path,
            method: "GET",
            apiVersion: COPY_JOB_API_VERSION,
            signal: copyJobsAbortController.signal
        });

        const jobs = response.value || [];
        if (!Array.isArray(jobs)) {
            throw new Error("Invalid migration job status response: Expected an array of jobs.");
        }
        copyJobsAbortController = null;

        /* added a lower bound to "0" and upper bound to "100" */
        const calculateCompletionPercentage = (processed: number, total: number): number => {
            if (
                typeof processed !== 'number' ||
                typeof total !== 'number' ||
                !isFinite(processed) ||
                !isFinite(total) ||
                total <= 0
            ) {
                return 0;
            }

            const percentage = Math.round((processed / total) * 100);
            return Math.max(0, Math.min(100, percentage));
        };

        const formattedJobs: CopyJobType[] = jobs
            .filter((job: DataTransferJobType) =>
                job.properties?.source?.component === COSMOS_SQL_COMPONENT &&
                job.properties?.destination?.component === COSMOS_SQL_COMPONENT
            )
            .sort((current: DataTransferJobType, next: DataTransferJobType) =>
                new Date(next.properties.lastUpdatedUtcTime).getTime() - new Date(current.properties.lastUpdatedUtcTime).getTime()
            )
            .map((job: DataTransferJobType, index: number) => {
                const dateTimeObj = formatUTCDateTime(job.properties.lastUpdatedUtcTime);

                return {
                    ID: (index + 1).toString(),
                    Mode: job.properties.mode,
                    Name: job.properties.jobName,
                    Status: convertToCamelCase(job.properties.status) as CopyJobType["Status"],
                    CompletionPercentage: calculateCompletionPercentage(job.properties.processedCount, job.properties.totalCount),
                    Duration: convertTime(job.properties.duration),
                    LastUpdatedTime: dateTimeObj.formattedDateTime,
                    timestamp: dateTimeObj.timestamp,
                    Error: job.properties.error ? extractErrorMessage(job.properties.error) : null,
                } as CopyJobType;
            });
        return formattedJobs;
    } catch (error) {
        const errorContent = JSON.stringify(error.content || error);
        console.error(`Error fetching copy jobs: ${errorContent}`);
        throw error;
    }
}

export const submitCreateCopyJob = async (state: CopyJobContextState, onSuccess: () => void) => {
    try {
        const { source, target, migrationType, jobName } = state;
        const path = buildDataTransferJobPath({
            subscriptionId: userContext.subscriptionId,
            resourceGroup: userContext.databaseAccount?.resourceGroup || "",
            accountName: userContext.databaseAccount?.name || "",
            jobName
        });
        const body = {
            "properties": {
                "source": {
                    "component": "CosmosDBSql",
                    "remoteAccountName": source?.account?.name,
                    "databaseName": source?.databaseId,
                    "containerName": source?.containerId
                },
                "destination": {
                    "component": "CosmosDBSql",
                    "databaseName": target?.databaseId,
                    "containerName": target?.containerId
                },
                "mode": migrationType
            }
        };

        const response: DataTransferJobType = await armRequest({
            host: configContext.ARM_ENDPOINT, path, method: "PUT", body, apiVersion: COPY_JOB_API_VERSION
        });
        MonitorCopyJobsRefState.getState().ref?.refreshJobList();
        onSuccess();
        return response;
    } catch (error) {
        console.error("Error submitting create copy job:", error);
        throw error;
    }
}

export const updateCopyJobStatus = async (job: CopyJobType, action: string): Promise<DataTransferJobType> => {
    try {
        const path = buildDataTransferJobPath({
            subscriptionId: userContext.subscriptionId,
            resourceGroup: userContext.databaseAccount?.resourceGroup || "",
            accountName: userContext.databaseAccount?.name || "",
            jobName: job.Name,
            action: action
        });

        const response: DataTransferJobType = await armRequest({
            host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion: COPY_JOB_API_VERSION
        });
        return response;
    } catch (error) {
        const errorMessage = JSON.stringify((error as CopyJobError).message || error.content || error);

        const statusList = [CopyJobStatusType.Running, CopyJobStatusType.InProgress, CopyJobStatusType.Partitioning];
        const pattern = new RegExp(`'(${statusList.join('|')})'`, 'g');
        const normalizedErrorMessage = errorMessage.replace(pattern, `'${ContainerCopyMessages.MonitorJobs.Status.InProgress}'`);

        console.error(`Error updating copy job status: ${normalizedErrorMessage}`);
        throw error;
    }
}
