"use client";

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

import {
  createProgressReport,
  createProgressReportDeadline,
  createProgressReportIssueComment,
  createProgressReportRgcDecisionComment,
  createProgressReportMeeting,
  deleteProgressReportIssueComment,
  deleteProgressReportRgcDecisionComment,
  getProgressReport,
  getProgressReportCommentTypes,
  getProgressReportMinistries,
  getProgressReportMinistryDetail,
  getProgressReports,
  reviewProgressReportMinistry,
  sendProgressReport,
  sendProgressReportDeadline,
  sendProgressReportMeeting,
  updateProgressReport,
  updateProgressReportDeadline,
  updateProgressReportMeeting,
  updateProgressReportIssueComment,
  updateProgressReportRgcDecisionComment,
  updateProgressReportMinistryIssueStatus,
  updateProgressReportMinistryRgcDecisionStatus,
  uploadDraftSemester,
  type ProgressReportPaginationMeta,
} from "../service/progress-report-service";

const EMPTY_META: ProgressReportPaginationMeta = {
  page: 1,
  limit: 100,
  total: 0,
  totalPages: 0,
};

export const progressReportQueryKeys = {
  all: ["cdc-gpsf-progress-reports"] as const,
  list: () => [...progressReportQueryKeys.all, "list"] as const,
  detail: (progressReportId: number) =>
    [...progressReportQueryKeys.all, "detail", progressReportId] as const,
  ministries: (progressReportId: number) =>
    [
      ...progressReportQueryKeys.detail(progressReportId),
      "ministries",
    ] as const,
  ministryDetail: (progressReportId: number, ministryId: number) =>
    [
      ...progressReportQueryKeys.detail(progressReportId),
      "ministries",
      ministryId,
    ] as const,
  commentTypes: () => [...progressReportQueryKeys.all, "comment-types"] as const,
};

export function useProgressReportCommentTypes() {
  const query = useQuery({
    queryKey: progressReportQueryKeys.commentTypes(),
    queryFn: getProgressReportCommentTypes,
  });

  return {
    commentTypes: query.data ?? [],
    isLoading: query.isLoading,
    error:
      query.error instanceof Error
        ? query.error.message
        : query.error
          ? "Unable to load comment types."
          : null,
  };
}

export function useProgressReports() {
  const query = useQuery({
    queryKey: progressReportQueryKeys.list(),
    queryFn: getProgressReports,
  });

  return {
    rows: query.data?.rows ?? [],
    calendarEvents: query.data?.calendarEvents ?? [],
    meta: query.data?.meta ?? EMPTY_META,
    isLoading: query.isLoading,
    error:
      query.error instanceof Error
        ? query.error.message
        : query.error
          ? "Unable to load progress reports."
          : null,
  };
}

export function useReviewProgressReportMinistry(
  progressReportId: number,
  ministryId: number,
) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (status: "CDC_UNDER_REVIEW" | "COMPLETED") =>
      reviewProgressReportMinistry({
        progressReportId,
        ministryId,
        status,
      }),
    onSuccess: async () => {
      await queryClient.invalidateQueries({
        queryKey: progressReportQueryKeys.all,
      });
    },
  });
}

export function useUpdateProgressReportMinistryIssueStatus(
  progressReportId: number,
  ministryId: number,
) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (input: { issueId: number; issueStatusId: number }) =>
      updateProgressReportMinistryIssueStatus({
        progressReportId,
        ministryId,
        ...input,
      }),
    onSuccess: async () => {
      await Promise.all([
        queryClient.invalidateQueries({
          queryKey: progressReportQueryKeys.ministryDetail(
            progressReportId,
            ministryId,
          ),
        }),
        queryClient.invalidateQueries({
          queryKey: ["ministry-progress-reports"],
        }),
        queryClient.invalidateQueries({
          queryKey: ["cdc-issue-matrix"],
        }),
        queryClient.invalidateQueries({
          queryKey: ["issue-matrix"],
        }),
        queryClient.invalidateQueries({
          queryKey: ["working-group-issues"],
        }),
      ]);
    },
  });
}

export function useProgressReportIssueCommentMutations(
  progressReportId: number,
  ministryId: number,
) {
  const queryClient = useQueryClient();

  async function refreshDetails() {
    await Promise.all([
      queryClient.invalidateQueries({
        queryKey: progressReportQueryKeys.ministryDetail(
          progressReportId,
          ministryId,
        ),
      }),
      queryClient.invalidateQueries({
        queryKey: ["ministry-progress-reports"],
      }),
    ]);
  }

  const createComment = useMutation({
    mutationFn: (input: {
      issueId: number;
      commentTypeId: number;
      comment: string;
    }) =>
      createProgressReportIssueComment({
        progressReportId,
        ministryId,
        ...input,
      }),
    onSuccess: refreshDetails,
  });

  const updateComment = useMutation({
    mutationFn: (input: {
      issueId: number;
      commentId: number;
      commentTypeId: number;
      comment: string;
    }) =>
      updateProgressReportIssueComment({
        progressReportId,
        ministryId,
        ...input,
      }),
    onSuccess: refreshDetails,
  });

  const deleteComment = useMutation({
    mutationFn: (input: { issueId: number; commentId: number }) =>
      deleteProgressReportIssueComment({
        progressReportId,
        ministryId,
        ...input,
      }),
    onSuccess: refreshDetails,
  });

  return {
    createComment,
    updateComment,
    deleteComment,
  };
}

export function useProgressReportRgcDecisionCommentMutations(
  progressReportId: number,
  ministryId: number,
) {
  const queryClient = useQueryClient();

  async function refreshDetails() {
    await Promise.all([
      queryClient.invalidateQueries({
        queryKey: progressReportQueryKeys.ministryDetail(
          progressReportId,
          ministryId,
        ),
      }),
      queryClient.invalidateQueries({
        queryKey: ["ministry-progress-reports"],
      }),
    ]);
  }

  const createComment = useMutation({
    mutationFn: (input: {
      plenaryDecisionId: number;
      commentTypeId: number;
      comment: string;
    }) =>
      createProgressReportRgcDecisionComment({
        progressReportId,
        ministryId,
        ...input,
      }),
    onSuccess: refreshDetails,
  });

  const updateComment = useMutation({
    mutationFn: (input: {
      plenaryDecisionId: number;
      commentId: number;
      commentTypeId: number;
      comment: string;
    }) =>
      updateProgressReportRgcDecisionComment({
        progressReportId,
        ministryId,
        ...input,
      }),
    onSuccess: refreshDetails,
  });

  const deleteComment = useMutation({
    mutationFn: (input: {
      plenaryDecisionId: number;
      commentId: number;
    }) =>
      deleteProgressReportRgcDecisionComment({
        progressReportId,
        ministryId,
        ...input,
      }),
    onSuccess: refreshDetails,
  });

  return {
    createComment,
    updateComment,
    deleteComment,
  };
}

export function useUpdateProgressReportMinistryRgcDecisionStatus(
  progressReportId: number,
  ministryId: number,
) {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (input: {
      plenaryDecisionId: number;
      status: "NOT_ADDRESSED" | "IN_PROGRESS" | "SOLVED";
    }) =>
      updateProgressReportMinistryRgcDecisionStatus({
        progressReportId,
        ministryId,
        ...input,
      }),
    onSuccess: async () => {
      await queryClient.invalidateQueries({
        queryKey: progressReportQueryKeys.ministryDetail(
          progressReportId,
          ministryId,
        ),
      });
    },
  });
}

export function useProgressReport(id: string) {
  const progressReportId = Number(id);
  const isValidId =
    Number.isInteger(progressReportId) && progressReportId > 0;

  const query = useQuery({
    queryKey: progressReportQueryKeys.detail(progressReportId),
    queryFn: () => getProgressReport(progressReportId),
    enabled: isValidId,
  });

  return {
    report: query.data ?? null,
    isValidId,
    isLoading: isValidId && query.isLoading,
    error:
      query.error instanceof Error
        ? query.error.message
        : query.error
          ? "Unable to load the progress report."
          : null,
  };
}

export function useProgressReportMinistries(id: string) {
  const progressReportId = Number(id);
  const isValidId =
    Number.isInteger(progressReportId) && progressReportId > 0;

  const query = useQuery({
    queryKey: progressReportQueryKeys.ministries(progressReportId),
    queryFn: () => getProgressReportMinistries(progressReportId),
    enabled: isValidId,
  });

  return {
    assignments: query.data ?? [],
    isLoading: isValidId && query.isLoading,
    error:
      query.error instanceof Error
        ? query.error.message
        : query.error
          ? "Unable to load submitted Ministry reports."
          : null,
  };
}

export function useProgressReportMinistryDetail(
  progressReportIdValue: string,
  ministryIdValue: string,
) {
  const progressReportId = Number(progressReportIdValue);
  const ministryId = Number(ministryIdValue);
  const isValidId =
    Number.isInteger(progressReportId) &&
    progressReportId > 0 &&
    Number.isInteger(ministryId) &&
    ministryId > 0;

  const query = useQuery({
    queryKey: progressReportQueryKeys.ministryDetail(
      progressReportId,
      ministryId,
    ),
    queryFn: () =>
      getProgressReportMinistryDetail(progressReportId, ministryId),
    enabled: isValidId,
  });

  return {
    assignment: query.data ?? null,
    isValidId,
    isLoading: isValidId && query.isLoading,
    error:
      query.error instanceof Error
        ? query.error.message
        : query.error
          ? "Unable to load the Ministry progress report."
          : null,
  };
}

export function useProgressReportMutations() {
  const queryClient = useQueryClient();

  function refreshProgressReports() {
    return queryClient.invalidateQueries({
      queryKey: progressReportQueryKeys.all,
    });
  }

  const createReportMutation = useMutation({
    mutationFn: createProgressReport,
    onSuccess: refreshProgressReports,
  });

  const createMeetingMutation = useMutation({
    mutationFn: createProgressReportMeeting,
    onSuccess: refreshProgressReports,
  });

  const sendMeetingMutation = useMutation({
    mutationFn: sendProgressReportMeeting,
    onSuccess: refreshProgressReports,
  });

  const updateMeetingMutation = useMutation({
    mutationFn: updateProgressReportMeeting,
    onSuccess: refreshProgressReports,
  });

  const updateReportMutation = useMutation({
    mutationFn: updateProgressReport,
    onSuccess: refreshProgressReports,
  });

  const sendReportMutation = useMutation({
    mutationFn: sendProgressReport,
    onSuccess: refreshProgressReports,
  });

  const createDeadlineMutation = useMutation({
    mutationFn: createProgressReportDeadline,
    onSuccess: refreshProgressReports,
  });

  const updateDeadlineMutation = useMutation({
    mutationFn: updateProgressReportDeadline,
    onSuccess: refreshProgressReports,
  });

  const sendDeadlineMutation = useMutation({
    mutationFn: sendProgressReportDeadline,
    onSuccess: refreshProgressReports,
  });

  const uploadDraftSemesterMutation = useMutation({
    mutationFn: uploadDraftSemester,
    onSuccess: refreshProgressReports,
  });

  return {
    createReport: createReportMutation.mutateAsync,
    updateReport: updateReportMutation.mutateAsync,
    createMeeting: createMeetingMutation.mutateAsync,
    updateMeeting: updateMeetingMutation.mutateAsync,
    sendMeeting: sendMeetingMutation.mutateAsync,
    sendReport: sendReportMutation.mutateAsync,
    createDeadline: createDeadlineMutation.mutateAsync,
    updateDeadline: updateDeadlineMutation.mutateAsync,
    sendDeadline: sendDeadlineMutation.mutateAsync,
    uploadDraftSemester: uploadDraftSemesterMutation.mutateAsync,
  };
}
