import { api } from './http';

const unwrapData = <T>(payload: any, hasExpectedShape: (v: any) => boolean): T => {
  if (hasExpectedShape(payload)) return payload as T;
  if (payload && typeof payload === 'object' && 'data' in payload && hasExpectedShape((payload as any).data)) return (payload as any).data as T;
  return payload as T;
};

export interface PointsMallMe {
  points: number;
  level?: string;
  totalSpentUSD?: number;
}

export interface PointsExchangeRequest {
  productId: string;
  recipientName: string;
  phone: string;
  province: string;
  city: string;
  district: string;
  address: string;
  zipCode?: string;
}

export interface PointsExchangePrepareResponse {
  orderId: string;
  pointsDeducted?: number;
  remainingPoints?: number;
  expiresAt?: string;
}

export type PointsExchangeShippingRequest = Omit<PointsExchangeRequest, 'productId'>;

export interface PointsExchangeResponse {
  orderId: string;
  pointsDeducted?: number;
  remainingPoints?: number;
}

export interface PointsMallCategory {
  id: string;
  name: string;
  sort: number;
}

export interface PointsMallAnnouncement {
  id: string;
  title: string;
  content: string;
  linkUrl?: string;
}

export interface PointsMallBanner {
  id: string;
  title: string;
  subtitle?: string;
  imageUrl: string;
  linkUrl?: string;
}

export interface PointsMallPromoEntry {
  id: string;
  title: string;
  subtitle?: string;
  iconUrl?: string;
  linkUrl?: string;
}

export interface PointsMallProduct {
  id: string;
  categoryId: string;
  name: string;
  subtitle?: string;
  coverUrl: string;
  pointsPrice: number;
  stock: number;
  sold: number;
  tags?: string[];
}

export interface PointsMallOverview {
  me: PointsMallMe;
  categories: PointsMallCategory[];
  announcements: PointsMallAnnouncement[];
  banners: PointsMallBanner[];
  promoEntries: PointsMallPromoEntry[];
}

export interface PointsMallProductsResponse {
  page: number;
  pageSize: number;
  total: number;
  items: PointsMallProduct[];
}

export const PointsMallAPI = {
  me: () =>
    api
      .get('/points-mall/me')
      .then((r) => unwrapData<PointsMallMe>(r.data, (v) => !!v && typeof v === 'object' && 'points' in v)),
  categories: () =>
    api.get('/points-mall/categories').then((r) => unwrapData<PointsMallCategory[]>(r.data, (v) => Array.isArray(v))),
  announcements: () =>
    api.get('/points-mall/announcements').then((r) => unwrapData<PointsMallAnnouncement[]>(r.data, (v) => Array.isArray(v))),
  banners: () => api.get('/points-mall/banners').then((r) => unwrapData<PointsMallBanner[]>(r.data, (v) => Array.isArray(v))),
  promoEntries: () =>
    api.get('/points-mall/promo-entries').then((r) => unwrapData<PointsMallPromoEntry[]>(r.data, (v) => Array.isArray(v))),
  products: (opts: { categoryId?: string; q?: string; sort?: string; page?: number; pageSize?: number } = {}) =>
    api
      .get<PointsMallProductsResponse>('/points-mall/products', {
        params: {
          categoryId: opts.categoryId,
          q: opts.q ?? '',
          sort: opts.sort ?? 'popular',
          page: opts.page ?? 1,
          pageSize: opts.pageSize ?? 24
        }
      })
      .then((r) => unwrapData<PointsMallProductsResponse>(r.data, (v) => !!v && typeof v === 'object' && 'items' in v)),
  exchangePrepare: (productId: string, quantity: number) =>
    api
      .post('/points-mall/exchange/prepare', { productId, quantity })
      .then((r) => unwrapData<PointsExchangePrepareResponse>(r.data, (v) => !!v && typeof v === 'object' && 'orderId' in v)),
  exchangeSubmitShipping: (orderId: string, shippingInfo: PointsExchangeShippingRequest) =>
    api
      .post(`/points-mall/exchange/${orderId}/shipping`, shippingInfo)
      .then((r) => unwrapData<PointsExchangeResponse>(r.data, (v) => !!v && typeof v === 'object' && 'orderId' in v)),
  exchange: (productId: string, quantity: number, shippingInfo: Omit<PointsExchangeRequest, 'productId'>) =>
    api
      .post('/points-mall/exchange', { productId, quantity, ...shippingInfo })
      .then((r) => unwrapData<PointsExchangeResponse>(r.data, (v) => !!v && typeof v === 'object' && 'orderId' in v))
};
