import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import {
  profileService,
  RawFullProfile,
  RawChannelContent,
  RawFeedContent,
  RawRentContent,
  UpdateProfilePayload,
} from "@/services/profileService";

interface ProfileState {
  profile: RawFullProfile | null;
  isProfileLoading: boolean;
  isUpdating: boolean;
  updateError: string | null;
  updateSuccess: boolean;
  contentByType: Record<number, RawChannelContent[]>;
  isContentLoading: boolean;
  feeds: RawFeedContent[];
  isFeedsLoading: boolean;
  rentContent: RawRentContent[];
  isRentLoading: boolean;
  error: string | null;
}

const initialState: ProfileState = {
  profile: null,
  isProfileLoading: false,
  isUpdating: false,
  updateError: null,
  updateSuccess: false,
  contentByType: {},
  isContentLoading: false,
  feeds: [],
  isFeedsLoading: false,
  rentContent: [],
  isRentLoading: false,
  error: null,
};

export const fetchProfile = createAsyncThunk(
  "profile/fetchProfile",
  async (_: void, { rejectWithValue }) => {
    try {
      const res = await profileService.getProfile();

      if (res.status !== 200) {
        return rejectWithValue("Failed to load profile");
      }

      const raw = Array.isArray(res.result)
        ? res.result[0]
        : res.result;

      return raw as RawFullProfile;

    } catch (err: unknown) {
      return rejectWithValue(
        err instanceof Error
          ? err.message
          : "Failed to load profile"
      );
    }
  },
  {
    // Skip fetch if profile data is already cached — prevents re-fetching on every
    // ProfilePage mount. updateProfile.fulfilled clears the cache so the
    // post-update dispatch still triggers a fresh fetch.
    condition: (_, { getState }) => {
      const { profile } = getState() as { profile: ProfileState };
      return !profile.profile && !profile.isProfileLoading;
    },
  },
);
export const fetchChannelContent = createAsyncThunk(
  "profile/fetchChannelContent",
  async (
    { channelId, contentType }: { channelId: string; contentType: number },
    { rejectWithValue },
  ) => {
    try {
      const res = await profileService.getContentByChannel(channelId, contentType);
      if (res.status !== 200) return rejectWithValue(res.message);
      return { contentType, items: res.result };
    } catch (err: unknown) {
      return rejectWithValue(err instanceof Error ? err.message : "Failed to load content");
    }
  },
);

export const fetchChannelFeed = createAsyncThunk(
  "profile/fetchChannelFeed",
  async (channelId: string, { rejectWithValue }) => {
    try {
      const res = await profileService.getChannelFeed(channelId);
      if (res.status !== 200) return rejectWithValue(res.message);
      return res.result;
    } catch (err: unknown) {
      return rejectWithValue(err instanceof Error ? err.message : "Failed to load feeds");
    }
  },
);

export const updateProfile = createAsyncThunk(
  "profile/update",
  async (payload: UpdateProfilePayload, { rejectWithValue }) => {
    try {
      const res = await profileService.updateProfile(payload);
      if (res.status !== 200 && res.status !== 1) return rejectWithValue(res.message ?? "Update failed");
      return res.message;
    } catch (err: unknown) {
      return rejectWithValue(err instanceof Error ? err.message : "Update failed");
    }
  },
);

export const fetchUserRentContent = createAsyncThunk(
  "profile/fetchUserRentContent",
  async (_, { rejectWithValue }) => {
    try {
      const res = await profileService.getUserRentContent();
      if (res.status !== 200) return rejectWithValue(res.message);
      return res.result;
    } catch (err: unknown) {
      return rejectWithValue(err instanceof Error ? err.message : "Failed to load rent content");
    }
  },
);

const profileSlice = createSlice({
  name: "profile",
  initialState,
  reducers: {
    clearProfile: () => initialState,
    resetUpdateState: (state) => {
      state.isUpdating = false;
      state.updateError = null;
      state.updateSuccess = false;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(updateProfile.pending, (state) => {
        state.isUpdating = true;
        state.updateError = null;
        state.updateSuccess = false;
      })
      .addCase(updateProfile.fulfilled, (state) => {
        state.isUpdating = false;
        state.updateSuccess = true;
        state.profile = null; // invalidate cache so the next fetchProfile() bypasses the condition guard
      })
      .addCase(updateProfile.rejected, (state, action) => {
        state.isUpdating = false;
        state.updateError = action.payload as string;
      })
      .addCase(fetchProfile.pending, (state) => {
        state.isProfileLoading = true;
        state.error = null;
      })
      .addCase(fetchProfile.fulfilled, (state, action) => {
        state.isProfileLoading = false;
        state.profile = action.payload;
      })
      .addCase(fetchProfile.rejected, (state, action) => {
        state.isProfileLoading = false;
        state.error = action.payload as string;
      })
      .addCase(fetchChannelContent.pending, (state) => {
        state.isContentLoading = true;
      })
      .addCase(fetchChannelContent.fulfilled, (state, action) => {
        state.isContentLoading = false;
        state.contentByType[action.payload.contentType] = action.payload.items;
      })
      .addCase(fetchChannelContent.rejected, (state) => {
        state.isContentLoading = false;
      })
      .addCase(fetchChannelFeed.pending, (state) => {
        state.isFeedsLoading = true;
      })
      .addCase(fetchChannelFeed.fulfilled, (state, action) => {
        state.isFeedsLoading = false;
        state.feeds = action.payload;
      })
      .addCase(fetchChannelFeed.rejected, (state) => {
        state.isFeedsLoading = false;
      })
      .addCase(fetchUserRentContent.pending, (state) => {
        state.isRentLoading = true;
      })
      .addCase(fetchUserRentContent.fulfilled, (state, action) => {
        state.isRentLoading = false;
        state.rentContent = action.payload;
      })
      .addCase(fetchUserRentContent.rejected, (state) => {
        state.isRentLoading = false;
      });
  },
});

export const { clearProfile, resetUpdateState } = profileSlice.actions;
export default profileSlice.reducer;
