import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import {
  CourseEnrollment,
  MyCourse,
  MyCourseDetail,
  CompletionReport,
} from '@/interface/Lms';
import { PaginationMeta } from '@/interface/Assessment';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft, PayloadAction } from '@reduxjs/toolkit';
import { message } from 'antd';
import { EnrollmentsActions } from './actionTypes';
import { apiGet, apiPost } from '@/services/api/api';
import axios, { AxiosResponse } from 'axios';

interface EnrollmentsState {
  enrollees: CourseEnrollment[];
  enrolleesMeta: PaginationMeta | null;
  myCourses: MyCourse[];
  myCoursesMeta: PaginationMeta | null;
  selectedMyCourse: MyCourseDetail | null;
  completionReport: CompletionReport | null;
  loading: boolean;
  error: string | null;
}

const initialState: EnrollmentsState = {
  enrollees: [],
  enrolleesMeta: null,
  myCourses: [],
  myCoursesMeta: null,
  selectedMyCourse: null,
  completionReport: null,
  loading: false,
  error: null,
};

export const fetchEnrollees = createAsyncThunk(
  EnrollmentsActions.FETCH_ENROLLEES_REQUEST,
  async (params: { courseId: string; status?: string; page?: number }) => {
    const queryParams = new URLSearchParams();
    if (params.status) queryParams.append('status', params.status);
    if (params.page) queryParams.append('page', params.page.toString());
    const query = queryParams.toString() ? `?${queryParams.toString()}` : '';
    const response = (await apiGet(
      `/lms/courses/${params.courseId}/enrollees${query}`,
    )) as AxiosResponse<{ data: CourseEnrollment[]; meta: PaginationMeta }>;
    return response.data;
  },
);

export const fetchMyCourses = createAsyncThunk(
  EnrollmentsActions.FETCH_MY_COURSES_REQUEST,
  async (params?: { status?: string; page?: number }) => {
    const queryParams = new URLSearchParams();
    if (params?.status) queryParams.append('status', params.status);
    if (params?.page) queryParams.append('page', params.page.toString());
    const query = queryParams.toString() ? `?${queryParams.toString()}` : '';
    const response = (await apiGet(`/lms/my-courses${query}`)) as AxiosResponse<{
      data: MyCourse[];
      meta: PaginationMeta;
    }>;
    return response.data;
  },
);

export const fetchMyCourseDetail = createAsyncThunk(
  EnrollmentsActions.FETCH_MY_COURSE_DETAIL_REQUEST,
  async (courseId: string) => {
    const response = (await apiGet(`/lms/my-courses/${courseId}`)) as AxiosResponse<MyCourseDetail>;
    return response.data;
  },
);

export const markMaterialViewed = createAsyncThunk(
  EnrollmentsActions.MARK_MATERIAL_VIEWED_REQUEST,
  async (
    payload: { courseId: string; materialId: string },
    { rejectWithValue },
  ) => {
    try {
      const response = (await apiPost(
        `/lms/my-courses/${payload.courseId}/materials/${payload.materialId}/viewed`,
        {},
      )) as AxiosResponse<{
        message: string;
        completion_percentage: number;
        status: string;
      }>;
      return { ...response.data, materialId: payload.materialId };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const selfEnroll = createAsyncThunk(
  EnrollmentsActions.SELF_ENROLL_REQUEST,
  async (courseId: string, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/lms/my-courses/${courseId}/enroll`,
        {},
      )) as AxiosResponse<{ message: string; enrollment_id: string }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const fetchCompletionReport = createAsyncThunk(
  EnrollmentsActions.FETCH_COMPLETION_REPORT_REQUEST,
  async (courseId: string) => {
    const response = (await apiGet(
      `/lms/courses/${courseId}/completion-report`,
    )) as AxiosResponse<CompletionReport>;
    return response.data;
  },
);

export const bulkEnrollTargets = createAsyncThunk(
  EnrollmentsActions.BULK_ENROLL_TARGETS_REQUEST,
  async (courseId: string, { rejectWithValue }) => {
    try {
      const response = (await apiPost(
        `/lms/courses/${courseId}/enroll-targets`,
        {},
      )) as AxiosResponse<{ message: string; enrolled_count: number }>;
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const EnrollmentsSlice = createSlice({
  name: 'lmsEnrollments',
  initialState,
  reducers: {
    clearSelectedMyCourse: (state: Draft<EnrollmentsState>) => {
      state.selectedMyCourse = null;
    },
    clearCompletionReport: (state: Draft<EnrollmentsState>) => {
      state.completionReport = null;
    },
  },
  extraReducers(builder) {
    builder
      .addCase(fetchEnrollees.pending, (state: Draft<EnrollmentsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchEnrollees.fulfilled,
        (
          state: Draft<EnrollmentsState>,
          action: PayloadAction<{ data: CourseEnrollment[]; meta: PaginationMeta }>,
        ) => {
          state.enrollees = action.payload.data;
          state.enrolleesMeta = action.payload.meta;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchEnrollees.rejected, (state: Draft<EnrollmentsState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load enrollees';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(fetchMyCourses.pending, (state: Draft<EnrollmentsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchMyCourses.fulfilled,
        (
          state: Draft<EnrollmentsState>,
          action: PayloadAction<{ data: MyCourse[]; meta: PaginationMeta }>,
        ) => {
          state.myCourses = action.payload.data;
          state.myCoursesMeta = action.payload.meta;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchMyCourses.rejected, (state: Draft<EnrollmentsState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load courses';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(fetchMyCourseDetail.pending, (state: Draft<EnrollmentsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchMyCourseDetail.fulfilled,
        (state: Draft<EnrollmentsState>, action: PayloadAction<MyCourseDetail>) => {
          state.selectedMyCourse = action.payload;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchMyCourseDetail.rejected, (state: Draft<EnrollmentsState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load course details';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(markMaterialViewed.fulfilled, (state: Draft<EnrollmentsState>, action) => {
        if (state.selectedMyCourse) {
          state.selectedMyCourse.enrollment.completion_percentage =
            action.payload.completion_percentage;
          state.selectedMyCourse.enrollment.status = action.payload.status as MyCourseDetail['enrollment']['status'];
          const material = state.selectedMyCourse.materials.find(
            (m) => m.id === action.payload.materialId,
          );
          if (material) {
            material.is_viewed = true;
          }
        }
      })
      .addCase(
        markMaterialViewed.rejected,
        (state: Draft<EnrollmentsState>, action: RejectedActionPayload) => {
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(selfEnroll.fulfilled, () => {
        message.success('Enrolled successfully');
      })
      .addCase(
        selfEnroll.rejected,
        (state: Draft<EnrollmentsState>, action: RejectedActionPayload) => {
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(fetchCompletionReport.pending, (state: Draft<EnrollmentsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(
        fetchCompletionReport.fulfilled,
        (state: Draft<EnrollmentsState>, action: PayloadAction<CompletionReport>) => {
          state.completionReport = action.payload;
          state.loading = false;
          state.error = null;
        },
      )
      .addCase(fetchCompletionReport.rejected, (state: Draft<EnrollmentsState>, action: RejectedActionPayload) => {
        state.loading = false;
        state.error = 'Failed to load completion report';
        message.error(Helpers.handleServerError(action.payload), 8);
      });

    builder
      .addCase(
        bulkEnrollTargets.fulfilled,
        (_state: Draft<EnrollmentsState>, action: PayloadAction<{ message: string; enrolled_count: number }>) => {
          message.success(action.payload.message);
        },
      )
      .addCase(
        bulkEnrollTargets.rejected,
        (state: Draft<EnrollmentsState>, action: RejectedActionPayload) => {
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );
  },
});

export const { clearSelectedMyCourse, clearCompletionReport } = EnrollmentsSlice.actions;
export default EnrollmentsSlice;
export type { EnrollmentsState };
