import {
  EmployeeReportData,
  TeamReportData,
  DepartmentReportData,
  OrganizationReportData,
  TrendReportData,
  NineBoxGridData,
} from '@/interface/PerformanceReport';
import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import { apiGet } from '@/services/api/api';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import axios, { AxiosResponse } from 'axios';
import { PerformanceReportActions } from './actionTypes';

interface PerformanceReportsState {
  employeeReport: EmployeeReportData | null;
  teamReport: TeamReportData | null;
  departmentReport: DepartmentReportData | null;
  organizationReport: OrganizationReportData | null;
  trendReport: TrendReportData | null;
  nineBoxGrid: NineBoxGridData | null;
  loading: boolean;
  error: string | null;
}

const initialState: PerformanceReportsState = {
  employeeReport: null,
  teamReport: null,
  departmentReport: null,
  organizationReport: null,
  trendReport: null,
  nineBoxGrid: null,
  loading: false,
  error: null,
};

export const fetchEmployeeReport = createAsyncThunk(
  PerformanceReportActions.FETCH_EMPLOYEE_REPORT,
  async (params: { employeeId: string; cycleId: string }, { rejectWithValue }) => {
    try {
      const response = (await apiGet(
        `/reports/employee/${params.employeeId}?cycle_id=${params.cycleId}`,
      )) as AxiosResponse<EmployeeReportData>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchTeamReport = createAsyncThunk(
  PerformanceReportActions.FETCH_TEAM_REPORT,
  async (params: { cycleId: string }, { rejectWithValue }) => {
    try {
      const response = (await apiGet(
        `/reports/team?cycle_id=${params.cycleId}`,
      )) as AxiosResponse<TeamReportData>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchDepartmentReport = createAsyncThunk(
  PerformanceReportActions.FETCH_DEPARTMENT_REPORT,
  async (params: { departmentId: string; cycleId: string }, { rejectWithValue }) => {
    try {
      const response = (await apiGet(
        `/reports/department/${params.departmentId}?cycle_id=${params.cycleId}`,
      )) as AxiosResponse<DepartmentReportData>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchOrganizationReport = createAsyncThunk(
  PerformanceReportActions.FETCH_ORGANIZATION_REPORT,
  async (params: { cycleId: string }, { rejectWithValue }) => {
    try {
      const response = (await apiGet(
        `/reports/organization?cycle_id=${params.cycleId}`,
      )) as AxiosResponse<OrganizationReportData>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchTrendReport = createAsyncThunk(
  PerformanceReportActions.FETCH_TREND_REPORT,
  async (params: { employeeId: string; cycleIds: string[] }, { rejectWithValue }) => {
    try {
      const cycleParams = params.cycleIds.map((id) => `cycle_ids[]=${id}`).join('&');
      const response = (await apiGet(
        `/reports/trend/${params.employeeId}?${cycleParams}`,
      )) as AxiosResponse<TrendReportData>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchNineBoxGrid = createAsyncThunk(
  PerformanceReportActions.FETCH_NINE_BOX_GRID,
  async (params: { cycleId: string; departmentId?: string }, { rejectWithValue }) => {
    try {
      const queryParams = new URLSearchParams({ cycle_id: params.cycleId });
      if (params.departmentId) queryParams.append('department_id', params.departmentId);
      const response = (await apiGet(
        `/reports/nine-box-grid?${queryParams.toString()}`,
      )) as AxiosResponse<NineBoxGridData>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const PerformanceReportsSlice = createSlice({
  name: 'performanceReports',
  initialState,
  reducers: {
    clearReport: (state: Draft<PerformanceReportsState>) => {
      state.employeeReport = null;
      state.teamReport = null;
      state.departmentReport = null;
      state.organizationReport = null;
      state.trendReport = null;
      state.nineBoxGrid = null;
      state.error = null;
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchEmployeeReport.pending, (state: Draft<PerformanceReportsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchEmployeeReport.fulfilled,
        (state: Draft<PerformanceReportsState>, action: PayloadAction<EmployeeReportData>) => {
          state.loading = false;
          state.employeeReport = action.payload;
        },
      )
      .addCase(
        fetchEmployeeReport.rejected,
        (state: Draft<PerformanceReportsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      )

      .addCase(fetchTeamReport.pending, (state: Draft<PerformanceReportsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchTeamReport.fulfilled,
        (state: Draft<PerformanceReportsState>, action: PayloadAction<TeamReportData>) => {
          state.loading = false;
          state.teamReport = action.payload;
        },
      )
      .addCase(
        fetchTeamReport.rejected,
        (state: Draft<PerformanceReportsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      )

      .addCase(fetchDepartmentReport.pending, (state: Draft<PerformanceReportsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchDepartmentReport.fulfilled,
        (state: Draft<PerformanceReportsState>, action: PayloadAction<DepartmentReportData>) => {
          state.loading = false;
          state.departmentReport = action.payload;
        },
      )
      .addCase(
        fetchDepartmentReport.rejected,
        (state: Draft<PerformanceReportsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      )

      .addCase(fetchOrganizationReport.pending, (state: Draft<PerformanceReportsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchOrganizationReport.fulfilled,
        (
          state: Draft<PerformanceReportsState>,
          action: PayloadAction<OrganizationReportData>,
        ) => {
          state.loading = false;
          state.organizationReport = action.payload;
        },
      )
      .addCase(
        fetchOrganizationReport.rejected,
        (state: Draft<PerformanceReportsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      )

      .addCase(fetchTrendReport.pending, (state: Draft<PerformanceReportsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchTrendReport.fulfilled,
        (state: Draft<PerformanceReportsState>, action: PayloadAction<TrendReportData>) => {
          state.loading = false;
          state.trendReport = action.payload;
        },
      )
      .addCase(
        fetchTrendReport.rejected,
        (state: Draft<PerformanceReportsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      )

      .addCase(fetchNineBoxGrid.pending, (state: Draft<PerformanceReportsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchNineBoxGrid.fulfilled,
        (state: Draft<PerformanceReportsState>, action: PayloadAction<NineBoxGridData>) => {
          state.loading = false;
          state.nineBoxGrid = action.payload;
        },
      )
      .addCase(
        fetchNineBoxGrid.rejected,
        (state: Draft<PerformanceReportsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(state.error, 10);
        },
      );
  },
});

export const { clearReport } = PerformanceReportsSlice.actions;
export default PerformanceReportsSlice;
