import axios, { AxiosError, AxiosResponse } from "axios";
import moment from "moment";
import { AnyAction } from "redux";
import { ThunkAction, ThunkDispatch } from "redux-thunk";

import {
    GET_INSPECTION_FORM_DATA_FAILED,
    GET_INSPECTION_FORM_DATA_REQUEST,
    GET_INSPECTION_FORM_DATA_SUCCESS,
    SUBMIT_INSPECTION_FAILED,
    SUBMIT_INSPECTION_REQUEST,
    SUBMIT_INSPECTION_SUCCESS,
} from "./types";

import config from '../../config/config';
import { RootState } from "../store";

import { axiosErrorMessage } from "../../utils/helper";

import { addHistory } from "./historyScreenActions";

// Types
interface FormFile {
  uri: string;
  type: string;
  name?: string;
  key: string;
}

interface InspectionFormData {
  [key: string]: any;
  images?: FormFile[];
  videos?: FormFile[];
  docs?: FormFile[];
}

// Thunk Type
type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  AnyAction
>;

/**
 * ✅ Fetch Inspection Form Data
 */
export const getInspectionFormData = (): AppThunk<Promise<void>> => {
  return async (dispatch: ThunkDispatch<RootState, unknown, AnyAction>) => {
    dispatch({ type: GET_INSPECTION_FORM_DATA_REQUEST });

    try {
      const res: AxiosResponse<any> = await axios.get(
        `${config.apiserver}/api/v1/inspection/get-inspection-types-and-locations`
      );
      dispatch({
        type: GET_INSPECTION_FORM_DATA_SUCCESS,
        payload: res.data,
      });
    } catch (error) {
      axiosErrorMessage(
        "Something went wrong while fetching inspection form data. Try to sync again",
        error as AxiosError
      );
      dispatch({
        type: GET_INSPECTION_FORM_DATA_FAILED,
        payload: error,
      });
    }
  };
};

/**
 * ✅ Submit Inspection Form
 */
export const submitInspection = (
  data: InspectionFormData,
  inspectionFormId: string,
  selectedEntity: string,
  inspectionTypeId: string,
  selectedBUManager?: string
): AnyAction => {
  const formData = new FormData();
  const keys: string[] = [];
  const allData: Record<string, any> = {};
  allData[inspectionFormId] = {
    id: inspectionTypeId,
    entity_id: selectedEntity,
    selectedBUManager,
    actions: [],
  };

  const actions: any[] = [];

  // Parse form data
  Object.entries(data).forEach(([key, value]) => {
    let questionId = "";

    if (key.includes("_actions") && value?.body?.length > 0) {
      actions.push(value);
    }

    if (key.includes("_answer")) {
      questionId = key.replace("_answer", "");
      allData[inspectionFormId][questionId] = {
        ...allData[inspectionFormId][questionId],
        composite_radio_webform_custom_composite: value,
      };
    }

    if (key.includes("_observation")) {
      questionId = key.replace("_observation", "");
      allData[inspectionFormId][questionId] = {
        ...allData[inspectionFormId][questionId],
        composite_textarea_webform_custom_composite: value,
      };
    }

    if (key.includes("_uri") && value?.length > 0) {
      questionId = key.replace("_uri", "");
      const filenames: string[] = [];

      value.forEach((file: FormFile) => {
        const extension = file.name
          ? "." + file.name.split(".").pop()
          : file.type === "video/mp4"
          ? ".mp4"
          : ".jpg";

        const fileKey = `${questionId}image${file.key}${extension}`;
        filenames.push(fileKey);
        keys.push(`imageKey_${questionId}image${file.key}`);

        formData.append(`imageKey_${questionId}image${file.key}`, {
          uri: file.uri,
          type: file.type,
          name: file.name || fileKey,
        } as any);
      });

      allData[inspectionFormId][questionId] = {
        ...allData[inspectionFormId][questionId],
        composite_file_webform_custom_composite: filenames.join(),
      };
    }
  });

  allData[inspectionFormId]["actions"] = actions;

  formData.append("submission_data", JSON.stringify(allData));

  if (keys.length > 0) {
    formData.append("image_keys", keys.join());
  }

  const formattedDate = moment().format("DD-MM-YYYY");
  const formattedTime = moment().format("h:mm:ss a");

  addHistory({
    title: `${inspectionFormId} has submitted on ${formattedDate} at ${formattedTime}`,
    data: formData,
    url: `${config.apiserver}/api/v1/inspection/webform-submission`,
  });

  return {
    type: SUBMIT_INSPECTION_REQUEST,
    payload: formData,
    meta: {
      offline: {
        effect: {
          url: `${config.apiserver}/api/v1/inspection/webform-submission`,
          method: "post",
          data: formData,
          headers: { Accept: "*/*" },
        },
        commit: { type: SUBMIT_INSPECTION_SUCCESS, meta: {} },
        rollback: {
          type: SUBMIT_INSPECTION_FAILED,
          meta: {
            title: inspectionFormId,
            url: `${config.apiserver}/api/v1/inspection/webform-submission`,
            data: formData,
          },
        },
      },
    },
  };
};
