import { apiClient } from '@/shared/api/client'
import type { ApiResponse } from '@/shared/types/types'

export type ChargeMode = '赠送' | '收费'

export type QuantityKey = string

export type ScreenshotKey = string

export type SkinCategoryKey = string

export interface PublishOptionGroup {
  key: SkinCategoryKey | string
  title: string
  options: string[]
}

export interface PublishQuantityItem {
  key: QuantityKey
  label: string
  price: string
  placeholder?: string
}

export interface PublishScreenshotSlot {
  key: ScreenshotKey
  label: string
  required: boolean
  hint: string
}

export interface PublishPriceConfig {
  deposit_placeholder: string
  price_placeholder: string
  ratio_description: string
}

export interface PublishDepositSkinGroupRule {
  group_key: string
  label: string
  amount_per_item: number
}

export interface PublishDepositRecommendConfig {
  base_amount: number
  skin_group_rules: PublishDepositSkinGroupRule[]
}

export interface PublishInsuranceBaseRatio {
  insurance: string
  ratio: number
}

export interface PublishRatioConfigItem {
  key: string
  label: string
  kind: string
  group_key?: string
  missing_penalty: number
}

export interface PublishCoinCorrection {
  threshold_m: number
  correction: number
}

export interface PublishSaleFixedMarkupRule {
  min_m: number
  max_m: number
  markup_amount: number
}

export interface PublishSaleRatioAdjustmentRule {
  min_m: number
  max_m: number
  ratio_subtract: number
}

export interface PublishRatioConfig {
  insurance_base_ratios: PublishInsuranceBaseRatio[]
  config_items: PublishRatioConfigItem[]
  coin_corrections: PublishCoinCorrection[]
}

export interface PublishSalePriceConfig {
  fixed_markup_rules: PublishSaleFixedMarkupRule[]
  ratio_adjustment_rules: PublishSaleRatioAdjustmentRule[]
}

export interface ListingPublishOptions {
  server_options: string[]
  face_options: string[]
  rank_options: string[]
  insurance_options: string[]
  level_options: string[]
  login_method_options: string[]
  region_options: string[]
  skin_groups: PublishOptionGroup[]
  quantity_items: PublishQuantityItem[]
  screenshot_slots: PublishScreenshotSlot[]
  ban_record_options: string[]
  ban_evidence_options: string[]
  fire_level_min: number
  price_config: PublishPriceConfig
  deposit_recommend_config: PublishDepositRecommendConfig
  ratio_config: PublishRatioConfig
}

export const emptyListingPublishOptions: ListingPublishOptions = {
  server_options: [],
  face_options: [],
  rank_options: [],
  insurance_options: [],
  level_options: [],
  login_method_options: [],
  region_options: [],
  skin_groups: [],
  quantity_items: [],
  screenshot_slots: [],
  ban_record_options: [],
  ban_evidence_options: [],
  fire_level_min: 38,
  price_config: {
    deposit_placeholder: '',
    price_placeholder: '',
    ratio_description: '',
  },
  deposit_recommend_config: {
    base_amount: 50,
    skin_group_rules: [
      { group_key: 'melee', label: '刀皮', amount_per_item: 5 },
      { group_key: 'operatorGold', label: '干员金皮', amount_per_item: 10 },
      { group_key: 'operatorRed', label: '干员红皮', amount_per_item: 30 },
    ],
  },
  ratio_config: {
    insurance_base_ratios: [],
    config_items: [],
    coin_corrections: [],
  },
}

export const emptyListingSalePriceConfig: PublishSalePriceConfig = {
  fixed_markup_rules: [
    { min_m: 10, max_m: 30, markup_amount: 28 },
    { min_m: 30, max_m: 50, markup_amount: 31 },
    { min_m: 50, max_m: 70, markup_amount: 34 },
    { min_m: 70, max_m: 90, markup_amount: 38 },
  ],
  ratio_adjustment_rules: [
    { min_m: 90, max_m: 150, ratio_subtract: 5 },
    { min_m: 150, max_m: 230, ratio_subtract: 4 },
    { min_m: 230, max_m: 310, ratio_subtract: 3.5 },
    { min_m: 310, max_m: 390, ratio_subtract: 3 },
    { min_m: 390, max_m: 470, ratio_subtract: 0 },
    { min_m: 470, max_m: 550, ratio_subtract: 0 },
    { min_m: 550, max_m: 0, ratio_subtract: 0 },
  ],
}

export async function fetchListingPublishOptions() {
  const { data } = await apiClient.get<ApiResponse<ListingPublishOptions>>('/listing-publish-options')
  return mergeListingPublishOptions(data.data)
}

export async function fetchListingSalePriceConfig() {
  const { data } = await apiClient.get<ApiResponse<PublishSalePriceConfig>>('/listing-sale-price-config')
  return mergeListingSalePriceConfig(data.data)
}

export function mergeListingPublishOptions(options?: Partial<ListingPublishOptions>): ListingPublishOptions {
  return {
    server_options: normalizeStringList(options?.server_options),
    face_options: normalizeStringList(options?.face_options),
    rank_options: normalizeStringList(options?.rank_options),
    insurance_options: normalizeStringList(options?.insurance_options),
    level_options: normalizeStringList(options?.level_options),
    login_method_options: normalizeStringList(options?.login_method_options),
    region_options: normalizeStringList(options?.region_options),
    skin_groups: normalizeOptionGroups(options?.skin_groups),
    quantity_items: normalizeQuantityItems(options?.quantity_items),
    screenshot_slots: normalizeScreenshotSlots(options?.screenshot_slots),
    ban_record_options: normalizeStringList(options?.ban_record_options),
    ban_evidence_options: normalizeStringList(options?.ban_evidence_options),
    fire_level_min: readPositiveInteger(options?.fire_level_min, 38),
    price_config: normalizePriceConfig(options?.price_config),
    deposit_recommend_config: normalizeDepositRecommendConfig(options?.deposit_recommend_config),
    ratio_config: normalizeRatioConfig(options?.ratio_config),
  }
}

export function mergeListingSalePriceConfig(options?: Partial<PublishSalePriceConfig>): PublishSalePriceConfig {
  return normalizeSalePriceConfig(options)
}

function normalizeStringList(values?: unknown[]) {
  return Array.isArray(values)
    ? values.map((item) => (typeof item === 'string' ? item.trim() : '')).filter(Boolean)
    : []
}

function normalizeOptionGroups(values?: unknown[]): PublishOptionGroup[] {
  if (!Array.isArray(values)) return []
  return values
    .map((item) => {
      const group = isRecord(item) ? item : {}
      return {
        key: typeof group.key === 'string' ? group.key.trim() : '',
        title: typeof group.title === 'string' ? group.title.trim() : '',
        options: normalizeStringList(Array.isArray(group.options) ? group.options : []),
      }
    })
    .filter((item) => item.key && item.title)
}

function normalizeQuantityItems(values?: unknown[]): PublishQuantityItem[] {
  if (!Array.isArray(values)) return []
  return values
    .map((item) => {
      const row = isRecord(item) ? item : {}
      return {
        key: typeof row.key === 'string' ? row.key.trim() : '',
        label: typeof row.label === 'string' ? row.label.trim() : '',
        price: typeof row.price === 'string' ? row.price.trim() : '',
        placeholder: typeof row.placeholder === 'string' ? row.placeholder.trim() : undefined,
      }
    })
    .filter((item) => item.key && item.label)
}

function normalizeScreenshotSlots(values?: unknown[]): PublishScreenshotSlot[] {
  if (!Array.isArray(values)) return []
  return values
    .map((item) => {
      const row = isRecord(item) ? item : {}
      return {
        key: typeof row.key === 'string' ? row.key.trim() : '',
        label: typeof row.label === 'string' ? row.label.trim() : '',
        required: row.required === true,
        hint: typeof row.hint === 'string' ? row.hint.trim() : '',
      }
    })
    .filter((item) => item.key && item.label)
}

function normalizePriceConfig(value?: unknown): PublishPriceConfig {
  const row = isRecord(value) ? value : {}
  return {
    deposit_placeholder: typeof row.deposit_placeholder === 'string' ? row.deposit_placeholder.trim() : '',
    price_placeholder: typeof row.price_placeholder === 'string' ? row.price_placeholder.trim() : '',
    ratio_description: typeof row.ratio_description === 'string' ? row.ratio_description.trim() : '',
  }
}

function normalizeDepositRecommendConfig(value?: unknown): PublishDepositRecommendConfig {
  const row = isRecord(value) ? value : {}
  const config = {
    base_amount: readNumber(row.base_amount),
    skin_group_rules: normalizeDepositSkinGroupRules(
      Array.isArray(row.skin_group_rules) ? row.skin_group_rules : [],
    ),
  }
  if (config.base_amount <= 0) {
    config.base_amount = emptyListingPublishOptions.deposit_recommend_config.base_amount
  }
  if (config.skin_group_rules.length === 0) {
    config.skin_group_rules = [...emptyListingPublishOptions.deposit_recommend_config.skin_group_rules]
  }
  return config
}

function normalizeDepositSkinGroupRules(values: unknown[]): PublishDepositSkinGroupRule[] {
  return values
    .map((item) => {
      const row = isRecord(item) ? item : {}
      return {
        group_key: typeof row.group_key === 'string' ? row.group_key.trim() : '',
        label: typeof row.label === 'string' ? row.label.trim() : '',
        amount_per_item: readNumber(row.amount_per_item),
      }
    })
    .filter((item) => item.group_key && item.label && item.amount_per_item >= 0)
}

function normalizeRatioConfig(value?: unknown): PublishRatioConfig {
  const row = isRecord(value) ? value : {}
  return {
    insurance_base_ratios: normalizeInsuranceBaseRatios(
      Array.isArray(row.insurance_base_ratios) ? row.insurance_base_ratios : [],
    ),
    config_items: normalizeRatioConfigItems(
      Array.isArray(row.config_items) ? row.config_items : [],
    ),
    coin_corrections: normalizeCoinCorrections(
      Array.isArray(row.coin_corrections) ? row.coin_corrections : [],
    ),
  }
}

function normalizeSalePriceConfig(value?: unknown): PublishSalePriceConfig {
  const row = isRecord(value) ? value : {}
  const config = {
    fixed_markup_rules: normalizeSaleFixedMarkupRules(
      Array.isArray(row.fixed_markup_rules) ? row.fixed_markup_rules : [],
    ),
    ratio_adjustment_rules: normalizeSaleRatioAdjustmentRules(
      Array.isArray(row.ratio_adjustment_rules) ? row.ratio_adjustment_rules : [],
    ),
  }
  if (config.fixed_markup_rules.length === 0 && config.ratio_adjustment_rules.length === 0) {
    return JSON.parse(JSON.stringify(emptyListingSalePriceConfig)) as PublishSalePriceConfig
  }
  return config
}

function normalizeInsuranceBaseRatios(values: unknown[]): PublishInsuranceBaseRatio[] {
  return values
    .map((item) => {
      const row = isRecord(item) ? item : {}
      return {
        insurance: typeof row.insurance === 'string' ? row.insurance.trim() : '',
        ratio: readNumber(row.ratio),
      }
    })
    .filter((item) => item.insurance && item.ratio > 0)
}

function normalizeRatioConfigItems(values: unknown[]): PublishRatioConfigItem[] {
  return values
    .map((item) => {
      const row = isRecord(item) ? item : {}
      return {
        key: typeof row.key === 'string' ? row.key.trim() : '',
        label: typeof row.label === 'string' ? row.label.trim() : '',
        kind: typeof row.kind === 'string' ? row.kind.trim() : '',
        group_key: typeof row.group_key === 'string' ? row.group_key.trim() : '',
        missing_penalty: readNumber(row.missing_penalty),
      }
    })
    .filter((item) => item.key && item.label && item.kind)
}

function normalizeCoinCorrections(values: unknown[]): PublishCoinCorrection[] {
  return values
    .map((item) => {
      const row = isRecord(item) ? item : {}
      return {
        threshold_m: readNumber(row.threshold_m),
        correction: readNumber(row.correction),
      }
    })
    .filter((item) => item.threshold_m >= 0 && item.correction > 0)
}

function normalizeSaleFixedMarkupRules(values: unknown[]): PublishSaleFixedMarkupRule[] {
  return values
    .map((item) => {
      const row = isRecord(item) ? item : {}
      return {
        min_m: readNumber(row.min_m),
        max_m: readNumber(row.max_m),
        markup_amount: readNumber(row.markup_amount),
      }
    })
    .filter((item) => item.min_m >= 0 && item.max_m >= item.min_m && item.markup_amount >= 0)
}

function normalizeSaleRatioAdjustmentRules(values: unknown[]): PublishSaleRatioAdjustmentRule[] {
  return values
    .map((item) => {
      const row = isRecord(item) ? item : {}
      return {
        min_m: readNumber(row.min_m),
        max_m: readNumber(row.max_m),
        ratio_subtract: readNumber(row.ratio_subtract),
      }
    })
    .filter(
      (item) =>
        item.min_m >= 0 &&
        (item.max_m === 0 || item.max_m >= item.min_m) &&
        item.ratio_subtract >= 0,
    )
}

function readNumber(value: unknown) {
  const parsed = Number(value)
  return Number.isFinite(parsed) ? parsed : 0
}

function readPositiveInteger(value: unknown, fallback: number) {
  const parsed = Math.trunc(readNumber(value))
  return parsed > 0 ? parsed : fallback
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null
}
