import { apiClient, type ApiResponse } from "@/lib/api/client";
import type {
  Article,
  AffiliateSummary,
  CashbackOffer,
  CashbackTransaction,
  Category,
  Country,
  Coupon,
  FavoriteItem,
  FavoriteListPayload,
  HomePayload,
  Language,
  LandingPage,
  NotificationItem,
  PageContent,
  PublicSetting,
  Store,
  TrackingCode,
  User,
  UserBankAccount,
  WalletWithdrawal,
  WalletTransaction,
} from "@/types/domain";
import type { Paginated } from "@/types/api";

const normalizePaginated = <T>(payload: ApiResponse<T[]>): Paginated<T> => ({
  items: payload.data,
  meta: {
    current_page: payload.meta?.current_page ?? 1,
    last_page: payload.meta?.last_page ?? 1,
    per_page: payload.meta?.per_page ?? payload.data.length,
    total: payload.meta?.total ?? payload.data.length,
  },
});

export type ListParams = Record<string, string | number | boolean | undefined>;

export const publicApi = {
  async home(params?: ListParams): Promise<HomePayload> {
    const { data } = await apiClient.get<ApiResponse<HomePayload>>("/home", { params });
    return data.data;
  },

  async categories(params?: ListParams): Promise<Paginated<Category>> {
    const { data } = await apiClient.get<ApiResponse<Category[]>>("/categories", { params });
    return normalizePaginated(data);
  },

  async articles(params?: ListParams): Promise<Paginated<Article>> {
    const { data } = await apiClient.get<ApiResponse<Article[]>>("/articles", { params });
    return normalizePaginated(data);
  },

  async articleDetails(articleId: number): Promise<Article> {
    const { data } = await apiClient.get<ApiResponse<Article>>(`/articles/${articleId}`);
    return data.data;
  },

  async categoryStores(categoryId: number, params?: ListParams): Promise<Paginated<Store>> {
    const { data } = await apiClient.get<ApiResponse<Store[]>>(`/categories/${categoryId}/stores`, { params });
    return normalizePaginated(data);
  },

  async stores(params?: ListParams): Promise<Paginated<Store>> {
    const { data } = await apiClient.get<ApiResponse<Store[]>>("/stores", { params });
    return normalizePaginated(data);
  },

  async storeDetails(storeId: number): Promise<Store> {
    const { data } = await apiClient.get<ApiResponse<Store>>(`/stores/${storeId}`);
    return data.data;
  },

  async storeCoupons(storeId: number, params?: ListParams): Promise<Paginated<Coupon>> {
    const { data } = await apiClient.get<ApiResponse<Coupon[]>>(`/stores/${storeId}/coupons`, { params });
    return normalizePaginated(data);
  },

  async storeCashback(storeId: number, params?: ListParams): Promise<Paginated<CashbackOffer>> {
    const { data } = await apiClient.get<ApiResponse<CashbackOffer[]>>(`/stores/${storeId}/cashback`, { params });
    return normalizePaginated(data);
  },

  async coupons(params?: ListParams): Promise<Paginated<Coupon>> {
    const { data } = await apiClient.get<ApiResponse<Coupon[]>>("/coupons", { params });
    return normalizePaginated(data);
  },

  async couponDetails(couponId: number): Promise<Coupon> {
    const { data } = await apiClient.get<ApiResponse<Coupon>>(`/coupons/${couponId}`);
    return data.data;
  },

  async couponCopy(couponId: number): Promise<void> {
    await apiClient.post(`/coupons/${couponId}/copy`);
  },

  async couponClick(couponId: number): Promise<{ redirect_url?: string | null }> {
    const { data } = await apiClient.post<ApiResponse<{ redirect_url?: string | null }>>(`/coupons/${couponId}/click`);
    return data.data;
  },

  async cashbackStores(params?: ListParams): Promise<Paginated<Store>> {
    const { data } = await apiClient.get<ApiResponse<Store[]>>("/cashback/stores", { params });
    return normalizePaginated(data);
  },

  async cashbackOffers(params?: ListParams): Promise<Paginated<CashbackOffer>> {
    const { data } = await apiClient.get<ApiResponse<CashbackOffer[]>>("/cashback/offers", { params });
    return normalizePaginated(data);
  },

  async countries(): Promise<Country[]> {
    const { data } = await apiClient.get<ApiResponse<Country[]>>("/countries");
    return data.data;
  },

  async languages(): Promise<Language[]> {
    const { data } = await apiClient.get<ApiResponse<Language[]>>("/languages");
    return data.data;
  },

  async pageByKey(key: string): Promise<PageContent> {
    const { data } = await apiClient.get<ApiResponse<PageContent>>(`/pages/${key}`);
    return data.data;
  },

  async publicSettings(keys?: string[]): Promise<PublicSetting[]> {
    const { data } = await apiClient.get<ApiResponse<PublicSetting[]>>("/settings/public", {
      params: keys && keys.length > 0 ? { keys: keys.join(",") } : undefined,
    });
    return data.data;
  },

  async landingPage(slug: string): Promise<LandingPage> {
    const { data } = await apiClient.get<ApiResponse<LandingPage>>(`/landing-pages/${slug}`);
    return data.data;
  },

  async landingCopy(slug: string): Promise<{
    message_ar: string;
    message_en: string;
    cta_button_text_ar: string;
    cta_button_text_en: string;
  }> {
    const { data } = await apiClient.post<ApiResponse<{
      message_ar: string;
      message_en: string;
      cta_button_text_ar: string;
      cta_button_text_en: string;
    }>>(`/landing-pages/${slug}/copy`);
    return data.data;
  },

  async landingCta(slug: string): Promise<{ redirect_url: string }> {
    const { data } = await apiClient.post<ApiResponse<{ redirect_url: string }>>(`/landing-pages/${slug}/cta`);
    return data.data;
  },

  async trackingCodes(position?: "head" | "body_end"): Promise<TrackingCode[]> {
    const { data } = await apiClient.get<ApiResponse<TrackingCode[]>>("/tracking-codes", {
      params: position ? { position } : undefined,
    });
    return data.data;
  },
};

export const authApi = {
  async login(payload: { login: string; password: string; device_name?: string }): Promise<{ user: User; token: string }> {
    const { data } = await apiClient.post<ApiResponse<{ user: User; token: string }>>("/auth/login", payload);
    return data.data;
  },

  async socialLogin(payload: { provider: "google" | "apple"; id_token: string; device_name?: string }): Promise<{ user: User; token: string }> {
    const { data } = await apiClient.post<ApiResponse<{ user: User; token: string }>>(`/auth/social/${payload.provider}`, payload);
    return data.data;
  },

  async register(payload: { name: string; email?: string; phone?: string; password: string; password_confirmation: string; referral_code?: string }): Promise<{ user: User; token: string }> {
    const { data } = await apiClient.post<ApiResponse<{ user: User; token: string }>>("/auth/register", payload);
    return data.data;
  },

  async forgotPassword(payload: { email?: string; phone?: string }): Promise<void> {
    await apiClient.post("/auth/forgot-password", payload);
  },

  async resetPassword(payload: { email: string; token: string; password: string; password_confirmation: string }): Promise<void> {
    await apiClient.post("/auth/reset-password", payload);
  },

  async me(): Promise<User> {
    const { data } = await apiClient.get<ApiResponse<User>>("/auth/me");
    return data.data;
  },

  async logout(): Promise<void> {
    await apiClient.post("/auth/logout");
  },
};

export const userApi = {
  async profile(): Promise<User> {
    const { data } = await apiClient.get<ApiResponse<User>>("/profile");
    return data.data;
  },

  async updateProfile(payload: { name: string; email?: string; phone?: string }): Promise<User> {
    const { data } = await apiClient.put<ApiResponse<User>>("/profile", payload);
    return data.data;
  },

  async updateLanguage(payload: { language_id: number }): Promise<User> {
    const { data } = await apiClient.put<ApiResponse<User>>("/profile/language", payload);
    return data.data;
  },

  async updateCountry(payload: { country_id: number }): Promise<User> {
    const { data } = await apiClient.put<ApiResponse<User>>("/profile/country", payload);
    return data.data;
  },

  async updatePassword(payload: { current_password: string; password: string; password_confirmation: string }): Promise<void> {
    await apiClient.put("/profile/password", payload);
  },

  async favorites(): Promise<FavoriteListPayload | FavoriteItem[]> {
    const { data } = await apiClient.get<ApiResponse<FavoriteListPayload | FavoriteItem[]>>("/favorites");
    return data.data;
  },

  async toggleFavorite(payload: { favoritable_type: string; favoritable_id: number }): Promise<{ is_favorited: boolean }> {
    const { data } = await apiClient.post<ApiResponse<{ is_favorited: boolean }>>("/favorites/toggle", payload);
    return data.data;
  },

  async notifications(params?: ListParams): Promise<{ notifications: NotificationItem[]; unread_count: number; meta?: ApiResponse<unknown>["meta"] }> {
    const { data } = await apiClient.get<ApiResponse<{ notifications: NotificationItem[]; unread_count: number }>>("/notifications", { params });
    return {
      notifications: data.data.notifications,
      unread_count: data.data.unread_count,
      meta: data.meta,
    };
  },

  async markNotificationRead(notificationId: number): Promise<void> {
    await apiClient.post(`/notifications/read/${notificationId}`);
  },

  async activateCashback(storeId: number, cashback_offer_id?: number): Promise<{ activation_id: number; redirect_url?: string | null }> {
    const { data } = await apiClient.post<ApiResponse<{ activation_id: number; redirect_url?: string | null }>>(`/cashback/activate/${storeId}`, {
      cashback_offer_id,
    });
    return data.data;
  },

  async cashbackHistory(params?: ListParams): Promise<Paginated<CashbackTransaction>> {
    const { data } = await apiClient.get<ApiResponse<CashbackTransaction[]>>("/cashback/history", { params });
    return normalizePaginated(data);
  },

  async cashbackSummary(): Promise<{
    wallet_balance: number;
    transactions_count: number;
    pending_amount: number;
    approved_amount: number;
    rejected_amount: number;
    paid_amount: number;
  }> {
    const { data } = await apiClient.get<ApiResponse<{
      wallet_balance: number;
      transactions_count: number;
      pending_amount: number;
      approved_amount: number;
      rejected_amount: number;
      paid_amount: number;
    }>>("/cashback/summary");
    return data.data;
  },

  async bankAccounts(): Promise<UserBankAccount[]> {
    const { data } = await apiClient.get<ApiResponse<UserBankAccount[]>>("/bank-accounts");
    return data.data;
  },

  async addBankAccount(payload: {
    bank_name: string;
    account_holder_name: string;
    iban?: string;
    account_number?: string;
    swift_code?: string;
    currency_code?: string;
    is_default?: boolean;
    is_active?: boolean;
  }): Promise<UserBankAccount> {
    const { data } = await apiClient.post<ApiResponse<UserBankAccount>>("/bank-accounts", payload);
    return data.data;
  },

  async updateBankAccount(
    bankAccountId: number,
    payload: {
      bank_name?: string;
      account_holder_name?: string;
      iban?: string;
      account_number?: string;
      swift_code?: string;
      currency_code?: string;
      is_default?: boolean;
      is_active?: boolean;
    },
  ): Promise<UserBankAccount> {
    const { data } = await apiClient.put<ApiResponse<UserBankAccount>>(`/bank-accounts/${bankAccountId}`, payload);
    return data.data;
  },

  async deleteBankAccount(bankAccountId: number): Promise<void> {
    await apiClient.delete(`/bank-accounts/${bankAccountId}`);
  },

  async withdrawals(params?: ListParams): Promise<Paginated<WalletWithdrawal>> {
    const { data } = await apiClient.get<ApiResponse<WalletWithdrawal[]>>("/withdrawals", { params });
    return normalizePaginated(data);
  },

  async requestWithdrawal(payload: {
    user_bank_account_id: number;
    amount: number;
    note?: string;
  }): Promise<WalletWithdrawal> {
    const { data } = await apiClient.post<ApiResponse<WalletWithdrawal>>("/withdrawals", payload);
    return data.data;
  },

  async walletTransactions(params?: ListParams): Promise<Paginated<WalletTransaction>> {
    const { data } = await apiClient.get<ApiResponse<WalletTransaction[]>>("/wallet/transactions", { params });
    return normalizePaginated(data);
  },

  async affiliateSummary(): Promise<AffiliateSummary> {
    const { data } = await apiClient.get<ApiResponse<AffiliateSummary>>("/affiliate/summary");
    return data.data;
  },
};
