import type { StickerCatalog, StickerCatalogRaw, StickerItem, StickerRaw } from './types'

export const STICKER_CATALOG_URL = '/lotties/sticker/index.json'

/** 禮物網格 4 欄 × 3 列 */
export const STICKER_PAGE_SIZE = 12

/** 分類標籤優先順序（其餘依數量排序） */
const CATEGORY_TAB_PRIORITY = ['basic', 'basic supuni', 'text', 'vip', 'event', 'seasonal', 'korean']

/** 多個 category 值合併為同一分頁 key */
const CATEGORY_TAB_ALIASES: Record<string, string> = {
    message: 'text',
}

export function normalizeGiftTabCategory(category: string): string {
    const key = String(category).trim()
    if (!key) return 'other'
    return CATEGORY_TAB_ALIASES[key.toLowerCase()] ?? key
}

export function toAssetUrl(url: string | undefined | null): string {
    if (!url) return ''
    const u = String(url).trim()
    if (!u) return ''
    if (u.startsWith('http://') || u.startsWith('https://') || u.startsWith('//')) {
        return u
    }
    return u.startsWith('/') ? u : `/${u}`
}

export function getStickerCategoryKey(raw: StickerRaw, categoryName: string): string {
    const key = String(raw.category ?? categoryName).trim()
    if (!key) return 'other'
    return normalizeGiftTabCategory(key)
}

export function hasLottieJson(raw: StickerRaw): boolean {
    const url = String(raw.lottie_url ?? '').trim()
    return url.length > 0 && /\.json(\?.*)?$/i.test(url)
}

export function isLottieJsonUrl(url: string | null | undefined): boolean {
    const u = String(url ?? '').trim()
    return u.length > 0 && /\.json(\?.*)?$/i.test(u)
}

function parseCatalogDate(value: string | undefined | null): number | null {
    const trimmed = String(value ?? '').trim()
    if (!trimmed) return null
    const normalized = trimmed.includes('T') ? trimmed : trimmed.replace(' ', 'T')
    const ms = Date.parse(normalized)
    return Number.isFinite(ms) ? ms : null
}

/** 依 start_date / end_date 判斷目前是否應顯示；兩者皆空則一律顯示 */
export function isStickerWithinSchedule(raw: StickerRaw, nowMs: number = Date.now()): boolean {
    const startMs = parseCatalogDate(raw.start_date)
    const endMs = parseCatalogDate(raw.end_date)
    if (startMs == null && endMs == null) return true
    if (startMs != null && nowMs < startMs) return false
    if (endMs != null && nowMs > endMs) return false
    return true
}

function sortCategoryKeys(keys: string[], buckets: Map<string, StickerItem[]>): string[] {
    const priorityIndex = (key: string) => {
        const lower = key.toLowerCase()
        const idx = CATEGORY_TAB_PRIORITY.indexOf(lower)
        return idx === -1 ? CATEGORY_TAB_PRIORITY.length : idx
    }

    return [...keys].sort((a, b) => {
        const pa = priorityIndex(a)
        const pb = priorityIndex(b)
        if (pa !== pb) return pa - pb
        const countDiff = (buckets.get(b)?.length ?? 0) - (buckets.get(a)?.length ?? 0)
        if (countDiff !== 0) return countDiff
        return a.localeCompare(b, undefined, { sensitivity: 'base' })
    })
}

function normalizeSticker(raw: StickerRaw, categoryName: string, nowMs: number): StickerItem | null {
    if (!raw.is_used || !raw.display) return null
    if (!isStickerWithinSchedule(raw, nowMs)) return null

    const category = getStickerCategoryKey(raw, categoryName)
    const images = (raw.image_urls || []).map(toAssetUrl).filter(Boolean)
    const preview = toAssetUrl(raw.image_thumbnail_web || raw.image_url_web || '')
    const lottieUrl = hasLottieJson(raw) ? toAssetUrl(raw.lottie_url) : null

    return {
        name: raw.name,
        tag: raw.tag || '',
        price: raw.price ?? 0,
        thumb: preview,
        image: preview,
        images,
        lottieUrl,
        category,
    }
}

export function parseStickerCatalog(raw: StickerCatalogRaw, nowMs: number = Date.now()): StickerCatalog {
    const stickerByName = new Map<string, StickerItem>()
    const buckets = new Map<string, StickerItem[]>()

    for (const cat of raw.categories || []) {
        for (const s of cat.stickers || []) {
            const item = normalizeSticker(s, cat.name, nowMs)
            if (!item) continue

            const list = buckets.get(item.category) ?? []
            list.push(item)
            buckets.set(item.category, list)
            stickerByName.set(item.name, item)
        }
    }

    const sortedKeys = sortCategoryKeys([...buckets.keys()], buckets)
    const tabs = sortedKeys.map((kind) => ({
        kind,
        title: kind,
        stickers: buckets.get(kind) ?? [],
    }))

    return { tabs, stickerByName }
}

/** category 值對應 i18n key；無對應則直接顯示 category 原文 */
/** 相對於 room.giftModal 的 i18n key（搭配 keyPrefix 使用） */
export const CATEGORY_TAB_I18N_KEYS: Record<string, string> = {
    basic: 'tabs.general',
    'basic supuni': 'tabs.basicSupuni',
    text: 'tabs.text',
    vip: 'tabs.vip',
}

export function formatCategoryTabLabel(category: string, t: (key: string) => string): string {
    const i18nKey = CATEGORY_TAB_I18N_KEYS[category.toLowerCase()]
    if (i18nKey) {
        const label = t(i18nKey)
        if (label !== i18nKey) return label
    }
    return category
}

export async function fetchStickerCatalog(): Promise<StickerCatalog> {
    const res = await fetch(`${STICKER_CATALOG_URL}?t=${Date.now()}`)
    if (!res.ok) {
        throw new Error(`Failed to load sticker catalog: ${res.status}`)
    }
    const raw = (await res.json()) as StickerCatalogRaw
    return parseStickerCatalog(raw)
}
