import { useCallback, useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { api, ApiError } from '../api/client'
import {
  TOPIC_CHANGED_EVENT,
  getActiveTopicId,
  rememberTopicId,
} from '../lib/brandContext'
import { topicIdFromSearch } from '../lib/placementFlow'
import { topicTitle } from '../lib/placementTopics'
import type { BrandData } from '../types/brand'
import type { ListPlacementTopicsData, PlacementTopicData } from '../types/placementTopic'

export function useActiveTopic() {
  const [searchParams, setSearchParams] = useSearchParams()
  const [topicId, setTopicIdState] = useState('')
  const [topics, setTopics] = useState<PlacementTopicData[]>([])
  const [topic, setTopic] = useState<PlacementTopicData | null>(null)
  const [brand, setBrand] = useState<BrandData | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')

  const resolveTopicId = useCallback(
    (list: PlacementTopicData[]) => {
      const fromQuery = topicIdFromSearch(searchParams.toString())
      if (fromQuery) return fromQuery
      const stored = getActiveTopicId()
      if (stored && list.some((item) => item.id === stored)) return stored
      return list[0]?.id ?? ''
    },
    [searchParams],
  )

  const loadTopicDetail = useCallback(async (id: string, list: PlacementTopicData[]) => {
    const found = list.find((item) => item.id === id)
    if (found) {
      setTopic(found)
      return found
    }
    const detail = await api.get<PlacementTopicData>(
      `/api/v1/placement/topics/${encodeURIComponent(id)}`,
      { auth: true },
    )
    setTopic(detail)
    return detail
  }, [])

  const load = useCallback(async () => {
    setLoading(true)
    setError('')
    try {
      const data = await api.get<ListPlacementTopicsData>('/api/v1/placement/topics/', { auth: true })
      const list = data.list ?? []
      setTopics(list)
      const resolved = resolveTopicId(list)
      setTopicIdState(resolved)
      if (resolved) {
        rememberTopicId(resolved)
        await loadTopicDetail(resolved, list)
      } else {
        setTopic(null)
        setBrand(null)
      }
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '載入主題失敗')
      setTopics([])
      setTopic(null)
      setBrand(null)
      setTopicIdState('')
    } finally {
      setLoading(false)
    }
  }, [loadTopicDetail, resolveTopicId])

  useEffect(() => {
    void load()
  }, [load])

  useEffect(() => {
    const onTopicChanged = (event: Event) => {
      const id = (event as CustomEvent<{ id: string }>).detail?.id?.trim() ?? ''
      if (id) setTopicIdState(id)
    }
    window.addEventListener(TOPIC_CHANGED_EVENT, onTopicChanged)
    return () => window.removeEventListener(TOPIC_CHANGED_EVENT, onTopicChanged)
  }, [])

  useEffect(() => {
    if (!topicId) {
      setTopic(null)
      return
    }
    const found = topics.find((item) => item.id === topicId)
    if (found) {
      setTopic(found)
      return
    }
    void loadTopicDetail(topicId, topics).catch(() => setTopic(null))
  }, [topicId, topics, loadTopicDetail])

  useEffect(() => {
    const brandId = topic?.brand_id?.trim()
    if (!brandId) {
      setBrand(null)
      return
    }
    void api
      .get<BrandData>(`/api/v1/brands/${encodeURIComponent(brandId)}`, { auth: true })
      .then(setBrand)
      .catch(() => setBrand(null))
  }, [topic?.brand_id])

  const setTopicId = useCallback(
    (id: string) => {
      const next = id.trim()
      if (!next) return
      rememberTopicId(next)
      setTopicIdState(next)
      const found = topics.find((item) => item.id === next)
      if (found) setTopic(found)
      const params = new URLSearchParams(searchParams)
      params.set('topic', next)
      params.delete('brand')
      setSearchParams(params, { replace: true })
    },
    [topics, searchParams, setSearchParams],
  )

  return {
    topicId,
    topic,
    topics,
    brand,
    topicLabel: topic ? topicTitle(topic) : '',
    setTopicId,
    loading,
    error,
    reload: load,
  }
}