import { RejectedActionPayload, ServerErrorResponse } from '@/interface/Shared';
import { CourseMaterial, CreateMaterialPayload, UpdateMaterialPayload } from '@/interface/Lms';
import Helpers from '@/utilities/Helpers';
import { createAsyncThunk, createSlice, Draft } from '@reduxjs/toolkit';
import { message } from 'antd';
import { MaterialsActions } from './actionTypes';
import { apiDelete, apiPost, apiPut } from '@/services/api/api';
import axios, { AxiosResponse } from 'axios';

interface MaterialsState {
  loading: boolean;
  error: string | null;
}

const initialState: MaterialsState = {
  loading: false,
  error: null,
};

function buildMaterialFormData(payload: CreateMaterialPayload | UpdateMaterialPayload): FormData | Record<string, unknown> {
  if (payload.file) {
    const formData = new FormData();
    formData.append('title', payload.title || '');
    formData.append('content_type', payload.content_type || '');
    formData.append('file', payload.file);
    if (payload.duration_minutes) formData.append('duration_minutes', payload.duration_minutes.toString());
    return formData;
  }

  const data: Record<string, unknown> = {};
  if (payload.title) data.title = payload.title;
  if (payload.content_type) data.content_type = payload.content_type;
  if (payload.rich_content) data.rich_content = payload.rich_content;
  if (payload.video_url) data.video_url = payload.video_url;
  if (payload.external_url) data.external_url = payload.external_url;
  if (payload.duration_minutes) data.duration_minutes = payload.duration_minutes;
  return data;
}

export const storeMaterial = createAsyncThunk(
  MaterialsActions.STORE_MATERIAL_REQUEST,
  async (payload: CreateMaterialPayload, { rejectWithValue }) => {
    try {
      const data = buildMaterialFormData(payload);
      const response = (await apiPost(
        `/lms/courses/${payload.courseId}/materials`,
        data,
      )) as AxiosResponse<{ data: CourseMaterial }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const updateMaterial = createAsyncThunk(
  MaterialsActions.UPDATE_MATERIAL_REQUEST,
  async (payload: UpdateMaterialPayload, { rejectWithValue }) => {
    try {
      const data = buildMaterialFormData(payload);
      const response = (await apiPut(
        `/lms/courses/${payload.courseId}/materials/${payload.materialId}`,
        data,
      )) as AxiosResponse<{ data: CourseMaterial }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const deleteMaterial = createAsyncThunk(
  MaterialsActions.DELETE_MATERIAL_REQUEST,
  async (payload: { courseId: string; materialId: string }, { rejectWithValue }) => {
    try {
      await apiDelete(`/lms/courses/${payload.courseId}/materials/${payload.materialId}`);
      return { materialId: payload.materialId };
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const reorderMaterials = createAsyncThunk(
  MaterialsActions.REORDER_MATERIALS_REQUEST,
  async (payload: { courseId: string; material_ids: string[] }, { rejectWithValue }) => {
    try {
      const response = (await apiPut(`/lms/courses/${payload.courseId}/materials/reorder`, {
        material_ids: payload.material_ids,
      })) as AxiosResponse<{ data: CourseMaterial[] }>;
      return response.data.data;
    } catch (error) {
      if (axios.isAxiosError(error) && error.response) {
        return rejectWithValue(error.response.data as ServerErrorResponse);
      }
      throw error;
    }
  },
);

export const MaterialsSlice = createSlice({
  name: 'lmsMaterials',
  initialState,
  reducers: {},
  extraReducers(builder) {
    builder
      .addCase(storeMaterial.pending, (state: Draft<MaterialsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(storeMaterial.fulfilled, (state: Draft<MaterialsState>) => {
        state.loading = false;
        state.error = null;
        message.success('Material added successfully');
      })
      .addCase(
        storeMaterial.rejected,
        (state: Draft<MaterialsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(updateMaterial.pending, (state: Draft<MaterialsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(updateMaterial.fulfilled, (state: Draft<MaterialsState>) => {
        state.loading = false;
        state.error = null;
        message.success('Material updated successfully');
      })
      .addCase(
        updateMaterial.rejected,
        (state: Draft<MaterialsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(deleteMaterial.pending, (state: Draft<MaterialsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(deleteMaterial.fulfilled, (state: Draft<MaterialsState>) => {
        state.loading = false;
        state.error = null;
        message.success('Material deleted successfully');
      })
      .addCase(
        deleteMaterial.rejected,
        (state: Draft<MaterialsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );

    builder
      .addCase(reorderMaterials.pending, (state: Draft<MaterialsState>) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(reorderMaterials.fulfilled, (state: Draft<MaterialsState>) => {
        state.loading = false;
        state.error = null;
        message.success('Materials reordered successfully');
      })
      .addCase(
        reorderMaterials.rejected,
        (state: Draft<MaterialsState>, action: RejectedActionPayload) => {
          state.loading = false;
          state.error = Helpers.handleServerError(action.payload);
          message.error(Helpers.handleServerError(action.payload), 10);
        },
      );
  },
});

export default MaterialsSlice;
export type { MaterialsState };
