import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import type { PayloadAction } from "@reduxjs/toolkit";
import {
  orderService,
  ORDER_STATUS,
  type MarketplaceOrder,
  type OrderCounts,
  type OrderReview,
  type OrderStatusCode,
} from "@/services/orderService";

/* ─── Thunks ─────────────────────────────────────────────────────────────── */

export interface FetchMyOrdersParams {
  status?: OrderStatusCode | "all";
  search?: string;
  page?: number;
  /** true = append to the existing list (load more), false = replace */
  append?: boolean;
}

export const fetchMyOrders = createAsyncThunk(
  "marketplaceOrders/fetchMyOrders",
  async (params: FetchMyOrdersParams = {}, { rejectWithValue }) => {
    try {
      const page = await orderService.getMyOrders({
        status: params.status ?? "all",
        search: params.search || undefined,
        page: params.page ?? 1,
      });
      return { ...page, append: params.append ?? false };
    } catch (err: unknown) {
      return rejectWithValue(
        err instanceof Error ? err.message : "Failed to load orders",
      );
    }
  },
);

export interface FetchMySalesParams {
  status?: OrderStatusCode | "all";
  page?: number;
}

export const fetchMySales = createAsyncThunk(
  "marketplaceOrders/fetchMySales",
  async (params: FetchMySalesParams = {}, { rejectWithValue }) => {
    try {
      return await orderService.getMySales({
        status: params.status ?? "all",
        page: params.page ?? 1,
      });
    } catch (err: unknown) {
      return rejectWithValue(
        err instanceof Error ? err.message : "Failed to load orders",
      );
    }
  },
);

export const fetchOrderDetail = createAsyncThunk(
  "marketplaceOrders/fetchOrderDetail",
  async (orderId: number | string, { rejectWithValue }) => {
    try {
      const order = await orderService.getOrderDetail(orderId);
      let myReview: OrderReview | null = null;
      if (order.status === ORDER_STATUS.DELIVERED) {
        try {
          const reviews = await orderService.getMyReviews();
          myReview =
            reviews.find((r) => r.classifiedOrderId === order.id) ?? null;
        } catch {
          // review lookup is non-critical
        }
      }
      return { order, myReview };
    } catch (err: unknown) {
      return rejectWithValue(
        err instanceof Error ? err.message : "Failed to load order",
      );
    }
  },
);

/* ─── State ──────────────────────────────────────────────────────────────── */

interface MyOrdersState {
  orders: MarketplaceOrder[];
  counts: OrderCounts;
  totalRows: number;
  totalPage: number;
  currentPage: number;
  hasMore: boolean;
  isLoading: boolean;
  isLoadingMore: boolean;
  error: string | null;
  latestRequestId: string | null;
}

interface MySalesState {
  orders: MarketplaceOrder[];
  totalRows: number;
  hasMore: boolean;
  isLoading: boolean;
  error: string | null;
  latestRequestId: string | null;
}

interface OrderDetailState {
  order: MarketplaceOrder | null;
  myReview: OrderReview | null;
  isLoading: boolean;
  error: string | null;
}

interface MarketplaceOrdersState {
  myOrders: MyOrdersState;
  mySales: MySalesState;
  detail: OrderDetailState;
}

const emptyCounts: OrderCounts = {
  total: 0,
  confirmed: 0,
  shipped: 0,
  delivered: 0,
  cancelled: 0,
};

const initialState: MarketplaceOrdersState = {
  myOrders: {
    orders: [],
    counts: emptyCounts,
    totalRows: 0,
    totalPage: 1,
    currentPage: 1,
    hasMore: false,
    isLoading: false,
    isLoadingMore: false,
    error: null,
    latestRequestId: null,
  },
  mySales: {
    orders: [],
    totalRows: 0,
    hasMore: false,
    isLoading: false,
    error: null,
    latestRequestId: null,
  },
  detail: {
    order: null,
    myReview: null,
    isLoading: false,
    error: null,
  },
};

/* ─── Slice ──────────────────────────────────────────────────────────────── */

const marketplaceOrdersSlice = createSlice({
  name: "marketplaceOrders",
  initialState,
  reducers: {
    /** Set after a successful add_order_review so the detail page updates. */
    setMyReview: (state, action: PayloadAction<OrderReview>) => {
      state.detail.myReview = action.payload;
    },
    clearOrderDetail: (state) => {
      state.detail = initialState.detail;
    },
  },
  extraReducers: (builder) => {
    builder
      /* My orders (buyer) */
      .addCase(fetchMyOrders.pending, (state, action) => {
        state.myOrders.latestRequestId = action.meta.requestId;
        if (action.meta.arg?.append) state.myOrders.isLoadingMore = true;
        else state.myOrders.isLoading = true;
        state.myOrders.error = null;
      })
      .addCase(fetchMyOrders.fulfilled, (state, action) => {
        if (action.meta.requestId !== state.myOrders.latestRequestId) return;
        const s = state.myOrders;
        s.isLoading = false;
        s.isLoadingMore = false;
        s.orders = action.payload.append
          ? [...s.orders, ...action.payload.orders]
          : action.payload.orders;
        s.counts = action.payload.counts;
        s.totalRows = action.payload.totalRows;
        s.totalPage = action.payload.totalPage;
        s.currentPage = action.payload.currentPage;
        s.hasMore = action.payload.hasMore;
      })
      .addCase(fetchMyOrders.rejected, (state, action) => {
        if (action.meta.requestId !== state.myOrders.latestRequestId) return;
        const s = state.myOrders;
        state.myOrders.isLoading = false;
        state.myOrders.isLoadingMore = false;
        s.orders = [];

        s.totalRows = 0;
        s.totalPage = 0;
        s.currentPage = 0;
        s.hasMore = false;
        state.myOrders.error = action.payload as string;
      })

      /* My sales (seller) */
      .addCase(fetchMySales.pending, (state, action) => {
        state.mySales.latestRequestId = action.meta.requestId;
        state.mySales.isLoading = true;
        state.mySales.error = null;
      })
      .addCase(fetchMySales.fulfilled, (state, action) => {
        if (action.meta.requestId !== state.mySales.latestRequestId) return;
        state.mySales.isLoading = false;
        state.mySales.orders = action.payload.orders;
        state.mySales.totalRows = action.payload.totalRows;
        state.mySales.hasMore = action.payload.hasMore;
      })
      .addCase(fetchMySales.rejected, (state, action) => {
        if (action.meta.requestId !== state.mySales.latestRequestId) return;
        state.mySales.isLoading = false;
        state.mySales.orders = [];
        state.mySales.totalRows = 0;
        state.mySales.hasMore = false;
        state.mySales.error = action.payload as string;
      })

      /* Order detail */
      .addCase(fetchOrderDetail.pending, (state) => {
        state.detail.isLoading = true;
        state.detail.error = null;
      })
      .addCase(fetchOrderDetail.fulfilled, (state, action) => {
        state.detail.isLoading = false;
        state.detail.order = action.payload.order;
        state.detail.myReview = action.payload.myReview;
      })
      .addCase(fetchOrderDetail.rejected, (state, action) => {
        state.detail.isLoading = false;
        state.detail.order = null;
        state.detail.error = action.payload as string;
      });
  },
});

export const { setMyReview, clearOrderDetail } = marketplaceOrdersSlice.actions;
export default marketplaceOrdersSlice.reducer;
