import adminClient from "./client"
import type { ApiResponse } from "../../types"

export type PromoCodeType = "percent" | "fixed" | "override"
export type PromoCodeScope = "all" | "category" | "group" | "product"
export type PromoCodeDiscountLevel = "order" | "product"

export interface AdminPromoCode {
  id: number
  row_key?: string
  code: string
  description: string | null
  type: PromoCodeType
  value: number
  discount_level: PromoCodeDiscountLevel
  scope: PromoCodeScope
  scope_ids: number[]
  starts_at: string | null
  expires_at: string | null
  max_uses: number
  max_uses_per_user: number
  used_count: number
  applicable_cycles: string[]
  min_order_amount: number
  min_quantity: number
  max_discount_amount: number
  required_product_ids: number[]
  required_group_ids: number[]
  required_category_ids: number[]
  allowed_user_ids: number[]
  new_users_only: boolean
  applies_to_renewals: boolean
  is_stackable: boolean
  is_enabled: boolean
  created_at: string
  updated_at: string
}

export interface AdminPromoCodePayload {
  code?: string
  description?: string | null
  type?: PromoCodeType
  value?: number
  discount_level?: PromoCodeDiscountLevel
  scope?: PromoCodeScope
  scope_ids?: number[]
  starts_at?: string | null
  expires_at?: string | null
  max_uses?: number
  max_uses_per_user?: number
  applicable_cycles?: string[]
  min_order_amount?: number
  min_quantity?: number
  max_discount_amount?: number
  required_product_ids?: number[]
  required_group_ids?: number[]
  required_category_ids?: number[]
  allowed_user_ids?: number[]
  new_users_only?: boolean
  applies_to_renewals?: boolean
  is_stackable?: boolean
  is_enabled?: boolean
}

export interface AdminPromoCodeList {
  items: AdminPromoCode[]
  total: number
}

const BASE = "/v1/admin/promo-codes"

function arrayValue<T>(value: unknown): T[] {
  return Array.isArray(value) ? value as T[] : []
}

function normalizePromoCode(item: AdminPromoCode, index = 0): AdminPromoCode {
  const partial = item as Partial<AdminPromoCode>
  const id = Number(partial.id ?? 0)
  const code = partial.code ?? ""
  return {
    ...item,
    id,
    row_key: id > 0 ? String(id) : code || `promo-${index}`,
    code,
    description: partial.description ?? null,
    type: partial.type ?? "fixed",
    value: Number(partial.value ?? 0),
    discount_level: partial.discount_level ?? "order",
    scope: partial.scope ?? "all",
    scope_ids: arrayValue<number>(partial.scope_ids),
    starts_at: partial.starts_at ?? null,
    expires_at: partial.expires_at ?? null,
    max_uses: Number(partial.max_uses ?? 0),
    max_uses_per_user: Number(partial.max_uses_per_user ?? 0),
    used_count: Number(partial.used_count ?? 0),
    applicable_cycles: arrayValue<string>(partial.applicable_cycles),
    min_order_amount: Number(partial.min_order_amount ?? 0),
    min_quantity: Number(partial.min_quantity ?? 0),
    max_discount_amount: Number(partial.max_discount_amount ?? 0),
    required_product_ids: arrayValue<number>(partial.required_product_ids),
    required_group_ids: arrayValue<number>(partial.required_group_ids),
    required_category_ids: arrayValue<number>(partial.required_category_ids),
    allowed_user_ids: arrayValue<number>(partial.allowed_user_ids),
    new_users_only: Boolean(partial.new_users_only),
    applies_to_renewals: Boolean(partial.applies_to_renewals),
    is_stackable: Boolean(partial.is_stackable),
    is_enabled: partial.is_enabled ?? true,
    created_at: partial.created_at ?? "",
    updated_at: partial.updated_at ?? "",
  }
}

export async function listPromoCodes(params?: {
  keyword?: string
  discount_level?: PromoCodeDiscountLevel | "all"
  enabled?: boolean | "all"
  offset?: number
  limit?: number
}) {
  const query = new URLSearchParams()
  if (params?.keyword) query.set("keyword", params.keyword)
  if (params?.discount_level && params.discount_level !== "all") query.set("discount_level", params.discount_level)
  if (params?.enabled !== undefined && params.enabled !== "all") query.set("enabled", String(params.enabled))
  query.set("offset", String(params?.offset ?? 0))
  query.set("limit", String(params?.limit ?? 20))
  const { data } = await adminClient.get<ApiResponse<AdminPromoCodeList>>(`${BASE}?${query.toString()}`)
  const payload = data.data
  return {
    ...data,
    data: payload ? { ...payload, items: arrayValue<AdminPromoCode>(payload.items).map((item, index) => normalizePromoCode(item, index)) } : payload,
  }
}

export async function createPromoCode(payload: AdminPromoCodePayload) {
  const { data } = await adminClient.post<ApiResponse<AdminPromoCode>>(BASE, payload)
  return { ...data, data: data.data ? normalizePromoCode(data.data) : data.data }
}

export async function updatePromoCode(id: number, payload: AdminPromoCodePayload) {
  const { data } = await adminClient.put<ApiResponse<AdminPromoCode>>(`${BASE}/${id}`, payload)
  return { ...data, data: data.data ? normalizePromoCode(data.data) : data.data }
}

export async function deletePromoCode(id: number) {
  const { data } = await adminClient.delete<ApiResponse<null>>(`${BASE}/${id}`)
  return data
}
