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

import {
    GET_INCIDENT_REPORT_DASHBOARD_FORM_FAILED,
    GET_INCIDENT_REPORT_DASHBOARD_FORM_REQUEST,
    GET_INCIDENT_REPORT_DASHBOARD_FORM_SUCCESS,
    SUBMIT_INCIDENT_FAILED,
    SUBMIT_INCIDENT_REQUEST,
    SUBMIT_INCIDENT_SUCCESS,
} from "./types";

import config from '../../config/config';
import { axiosErrorMessage } from "../../utils/helper";
import { RootState } from "../store";
import { addHistory } from "./historyScreenActions";

// Types
interface InvolvedPerson {
  address?: string;
  involvedPersonName?: string;
  phoneNumber?: string;
  involvedUserRole: string[];
  user: string[];
  Nationality?: string[];
}

interface Witness {
  address?: string;
  involvedPersonName?: string;
  phoneNumber?: string;
  involvedUserRole: string[];
  user: string[];
  Nationality?: string[];
}

interface IncidentFormData {
  title: string;
  incidentType: string[];
  incidentSubType?: string[];
  group: string[];
  area: string[];
  body: string;
  date: Date;
  time: Date;
  involvedPeople: InvolvedPerson[];
  witnesses: Witness[];
  images: any[];
  videos: any[];
  docs: any[];
  field_firstaid?: string;
  field_staff_off_from_work?: string;
  field_staff_off_days?: string | number;
  field_taken_home?: string;
  field_hospitalized?: string;
  field_no_of_days_hospitalized?: string | number;
  field_sent_or_taken_to_hospital?: string;
  field_hospital_name?: string;
}

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

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

    try {
      const res: AxiosResponse<any> = await axios.get(
        `${config.apiserver}/api/v1/incident-report/get-incident-report-full-form`
      );

      dispatch({
        type: GET_INCIDENT_REPORT_DASHBOARD_FORM_SUCCESS,
        payload: res.data,
      });
    } catch (error) {
      axiosErrorMessage(
        "Something went wrong while fetching incident report form data. Try to sync again",
        error as AxiosError
      );
      dispatch({
        type: GET_INCIDENT_REPORT_DASHBOARD_FORM_FAILED,
        payload: error,
      });
    }
  };
};

/**
 * ✅ Submit Incident
 */
export const submitIncident = (
  formData: IncidentFormData
): AnyAction => {
  const form = new FormData();

  const {
    title,
    incidentType,
    incidentSubType,
    group,
    area,
    body,
    date,
    time,
    involvedPeople,
    witnesses,
    images,
    videos,
    docs,
    field_firstaid,
    field_staff_off_from_work,
    field_staff_off_days,
    field_taken_home,
    field_hospitalized,
    field_no_of_days_hospitalized,
    field_sent_or_taken_to_hospital,
    field_hospital_name,
  } = formData;

  const incidentTypeId = incidentType[0].toString();
  const incidentSubTypeId =
    incidentSubType && incidentSubType.length > 0 ? incidentSubType[0].toString() : null;
  const areaId = area[0].toString();
  const groupId = group[0].toString();

  // Set date & time
  const incidentDate = new Date(date);
  incidentDate.setHours(time.getHours(), time.getMinutes());

  // Parse involved people
  const parsePeople = (list: InvolvedPerson[] | Witness[]) =>
    list.map((item) => ({
      field_address: item.address || null,
      field_involved_person_name: item.involvedPersonName || null,
      field_phone_number: item.phoneNumber || null,
      field_person_role_type: item.involvedUserRole[0] || null,
      field_user_email: item.user[0] || null,
      field_nationality:
        item.Nationality && item.Nationality.length > 0 ? item.Nationality[0] : null,
    }));

  const involvedPeopleParsed = parsePeople(involvedPeople);
  const witnessesParsed = parsePeople(witnesses);

  const field_date_time = moment.utc(incidentDate).format("YYYY-MM-DD[T]HH:mm:ss");

  const postData = {
    title,
    body,
    field_date_time,
    field_incident_report_completed: false,
    field_area: areaId,
    field_group: groupId,
    field_incident_type: incidentTypeId,
    field_incident_sub_type: incidentSubTypeId,
    field_involved_people: involvedPeopleParsed,
    field_witnesses: witnessesParsed,
    field_immediate_actions: {
      field_firstaid,
      field_staff_off_from_work,
      field_staff_off_days: field_staff_off_from_work === "yes" ? field_staff_off_days : "",
      field_taken_home,
      field_hospitalized,
      field_no_of_days_hospitalized:
        field_hospitalized === "yes" ? field_no_of_days_hospitalized : "",
      field_sent_or_taken_to_hospital,
      field_hospital_name: field_sent_or_taken_to_hospital === "yes" ? field_hospital_name : "",
    },
  };

  form.append("submission_data", JSON.stringify(postData));

  // Add files
  const appendFiles = (files: any[], prefix: string) => {
    const keys: string[] = [];
    files.forEach((file, index) => {
      const ext = file.type === "video/mp4" ? ".mp4" : ".jpg";
      const key = `imageKey_${index}${prefix}${file.key}`;
      keys.push(key);
      form.append(key, { uri: file.uri, type: file.type, name: file.name || `file00${index}${ext}` } as any);
    });
    return keys;
  };

  const imageKeys = [
    ...appendFiles(images, "image"),
    ...appendFiles(videos, "video"),
    ...appendFiles(docs, "doc"),
  ];

  if (imageKeys.length > 0) form.append("image_keys", imageKeys.join());

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

  addHistory({
    title: `${title} has submitted on ${formattedDate} at ${formattedTime}`,
    data: form,
    url: `${config.apiserver}/api/v1/incident-report/create-incident`,
  });

  return {
    type: SUBMIT_INCIDENT_REQUEST,
    payload: {},
    meta: {
      offline: {
        effect: {
          url: `${config.apiserver}/api/v1/incident-report/create-incident`,
          method: "post",
          data: form,
          headers: { Accept: "*/*" },
        },
        commit: { type: SUBMIT_INCIDENT_SUCCESS, meta: {} },
        rollback: {
          type: SUBMIT_INCIDENT_FAILED,
          meta: {
            title,
            url: `${config.apiserver}/api/v1/incident-report/create-incident`,
            data: form,
          },
        },
      },
    },
  };
};
