import { reactive, ref, computed, type Ref } from 'vue'
import type { ListingPublishOptions } from '../api/listingOptions'
import type { Listing } from '../api/listings'
import { assetRegions } from '@/shared/utils/listingDisplay'

export type FilterPopoverKey =
  | 'insurance'
  | 'stamina'
  | 'load'
  | 'region'
  | 'coin'
  | 'price'
  | 'deposit'
  | 'total'
  | 'skin'
  | 'rank'
  | 'fireLevel'
  | 'loginMethod'

export type StringFilterKey =
  | 'insurance'
  | 'stamina'
  | 'load'
  | 'region'
  | 'rank'
  | 'loginMethod'

export interface HomeFilters {
  keyword: string
  server: string
  region: string
  loginMethod: string
  rank: string
  insurance: string
  stamina: string
  load: string
  skinGroup: string
  skinName: string
  minCoin: number | undefined
  maxCoin: number | undefined
  minPrice: number | undefined
  maxPrice: number | undefined
  minDeposit: number | undefined
  maxDeposit: number | undefined
  minTotal: number | undefined
  maxTotal: number | undefined
  minFireLevel: number | undefined
  maxFireLevel: number | undefined
}

export function useHomeFilters(
  publishOptions: Ref<ListingPublishOptions>,
  listings: Ref<Listing[]>
) {
  const filters = reactive<HomeFilters>({
    keyword: '',
    server: '',
    region: '',
    loginMethod: '',
    rank: '',
    insurance: '',
    stamina: '',
    load: '',
    skinGroup: '',
    skinName: '',
    minCoin: undefined,
    maxCoin: undefined,
    minPrice: undefined,
    maxPrice: undefined,
    minDeposit: undefined,
    maxDeposit: undefined,
    minTotal: undefined,
    maxTotal: undefined,
    minFireLevel: undefined,
    maxFireLevel: undefined,
  })

  const activeFilterPopover = ref<FilterPopoverKey | ''>('')

  const regionOptions = computed(() =>
    uniqueOptions([
      ...publishOptions.value.region_options,
      ...listings.value.flatMap((item) => assetRegions(item)),
    ])
  )

  const loginMethodOptions = computed(() =>
    uniqueOptions(
      publishOptions.value.login_method_options
        .map((item) => item.trim())
        .filter(Boolean)
    )
  )

  const skinFilterGroups = computed(() => {
    const preferred = ['operatorRed', 'operatorGold']
    return preferred
      .map((key) => publishOptions.value.skin_groups.find((group) => group.key === key))
      .filter((group): group is ListingPublishOptions['skin_groups'][number] => Boolean(group))
  })

  const skinChipLabel = computed(() => {
    if (filters.skinName) return filters.skinName
    if (filters.skinGroup) {
      return skinFilterGroups.value.find((group) => group.key === filters.skinGroup)?.title || '皮肤'
    }
    return '皮肤'
  })

  function uniqueOptions(values: string[]) {
    return [...new Set(values.map((item) => item.trim()).filter(Boolean))]
  }

  function resetFilters() {
    filters.keyword = ''
    filters.server = ''
    filters.region = ''
    filters.loginMethod = ''
    filters.rank = ''
    filters.insurance = ''
    filters.stamina = ''
    filters.load = ''
    filters.skinGroup = ''
    filters.skinName = ''
    filters.minCoin = undefined
    filters.maxCoin = undefined
    filters.minPrice = undefined
    filters.maxPrice = undefined
    filters.minDeposit = undefined
    filters.maxDeposit = undefined
    filters.minTotal = undefined
    filters.maxTotal = undefined
    filters.minFireLevel = undefined
    filters.maxFireLevel = undefined
  }

  function setStringFilter(key: StringFilterKey, value: string) {
    filters[key] = value
    closeFilterPopover()
  }

  function setCoinRange(min: number | undefined, max: number | undefined) {
    filters.minCoin = min
    filters.maxCoin = max
  }

  function setPriceRange(min: number | undefined, max: number | undefined) {
    filters.minPrice = min
    filters.maxPrice = max
  }

  function setDepositRange(min: number | undefined, max: number | undefined) {
    filters.minDeposit = min
    filters.maxDeposit = max
  }

  function setTotalRange(min: number | undefined, max: number | undefined) {
    filters.minTotal = min
    filters.maxTotal = max
  }

  function setFireLevelRange(min: number | undefined, max: number | undefined) {
    filters.minFireLevel = min
    filters.maxFireLevel = max
  }

  function setSkinFilter(group: string, name = '') {
    filters.skinGroup = group
    filters.skinName = name
  }

  function resetSkinFilter() {
    filters.skinGroup = ''
    filters.skinName = ''
  }

  function setFilterPopover(key: FilterPopoverKey, visible: boolean) {
    if (visible) {
      activeFilterPopover.value = key
      return
    }
    if (activeFilterPopover.value === key) activeFilterPopover.value = ''
  }

  function closeFilterPopover() {
    activeFilterPopover.value = ''
  }

  return {
    filters,
    activeFilterPopover,
    regionOptions,
    loginMethodOptions,
    skinFilterGroups,
    skinChipLabel,
    resetFilters,
    setStringFilter,
    setCoinRange,
    setPriceRange,
    setDepositRange,
    setTotalRange,
    setFireLevelRange,
    setSkinFilter,
    resetSkinFilter,
    setFilterPopover,
    closeFilterPopover,
  }
}
