import { computed, reactive, ref, shallowRef, watch } from 'vue'
import { ApiError, api } from '../lib/api'
import { todayIso } from '../lib/format'
import type {
  Account,
  ClsNewsDocument,
  DailyInputAccount,
  DailyInputDocument,
  DashboardSection,
  ReportDocument,
  ReportListItem,
} from '../types'

function buildEmptyDailyInput(date: string, accounts: Account[]): DailyInputDocument {
  return {
    date,
    updated_at: '',
    accounts: accounts.map((account) => ({
      account_id: account.id,
      account_name: account.name,
      links: [],
    })),
  }
}

function formatError(error: unknown): string {
  if (error instanceof ApiError) {
    return `接口请求失败：${error.message}`
  }
  if (error instanceof Error) {
    return error.message
  }
  return '出现未预期错误，请稍后再试。'
}

function isFulfilled<T>(result: PromiseSettledResult<T>): result is PromiseFulfilledResult<T> {
  return result.status === 'fulfilled'
}

export function useFinanceDashboard() {
  const activeSection = shallowRef<DashboardSection>('cls')
  const selectedDate = shallowRef(todayIso())
  const statusMessage = shallowRef('系统已加载，可直接查看资讯、切换日期或录入当日链接。')
  const initialized = shallowRef(false)

  const accounts = ref<Account[]>([])
  const clsNews = ref<ClsNewsDocument | null>(null)
  const reportList = ref<ReportListItem[]>([])
  const opinionReport = ref<ReportDocument | null>(null)
  const dailyInput = ref<DailyInputDocument | null>(null)

  const loading = reactive({
    boot: false,
    news: false,
    report: false,
    input: false,
    save: false,
    generate: false,
  })

  const availableDates = computed(() => {
    const dateSet = new Set(reportList.value.map((item) => item.date))
    dateSet.add(selectedDate.value)
    return [...dateSet].sort((left, right) => right.localeCompare(left))
  })

  const inputAccounts = computed<DailyInputAccount[]>(() => {
    if (dailyInput.value) {
      return dailyInput.value.accounts
    }
    return buildEmptyDailyInput(selectedDate.value, accounts.value).accounts
  })

  async function refreshStaticResources() {
    const [accountData, reportData] = await Promise.all([
      api.getAccounts(),
      api.getReportList(),
    ])

    accounts.value = accountData
    reportList.value = reportData
  }

  async function refreshDateBundle(date: string) {
    const [inputResult, reportResult, newsResult] = await Promise.allSettled([
      api.getDailyInput(date),
      api.getOpinionReport(date),
      api.getClsNews(date),
    ])

    if (isFulfilled(inputResult)) {
      dailyInput.value = inputResult.value
    }
    if (isFulfilled(reportResult)) {
      opinionReport.value = reportResult.value
    }
    if (isFulfilled(newsResult)) {
      clsNews.value = newsResult.value
    }

    const failures = [inputResult, reportResult, newsResult].filter((result) => result.status === 'rejected')
    if (failures.length > 0) {
      throw failures[0].reason
    }
  }

  async function initializeDashboard() {
    loading.boot = true
    try {
      await refreshStaticResources()
      await refreshDateBundle(selectedDate.value)
      initialized.value = true
      statusMessage.value = '系统已就绪，支持查看财联社 7x24、浏览大V日报和录入链接。'
    } catch (error) {
      statusMessage.value = formatError(error)
    } finally {
      loading.boot = false
    }
  }

  watch(
    selectedDate,
    async (date, _previous, onCleanup) => {
      if (!initialized.value) {
        return
      }

      let cancelled = false
      onCleanup(() => {
        cancelled = true
      })

      dailyInput.value = null
      opinionReport.value = null
      clsNews.value = null
      loading.input = true
      loading.report = true
      loading.news = true
      try {
        const [inputResult, reportResult, newsResult] = await Promise.allSettled([
          api.getDailyInput(date),
          api.getOpinionReport(date),
          api.getClsNews(date),
        ])

        if (cancelled) {
          return
        }

        if (isFulfilled(inputResult)) {
          dailyInput.value = inputResult.value
        }
        if (isFulfilled(reportResult)) {
          opinionReport.value = reportResult.value
        }
        if (isFulfilled(newsResult)) {
          clsNews.value = newsResult.value
        }

        const failures = [inputResult, reportResult, newsResult].filter((result) => result.status === 'rejected')
        if (failures.length > 0) {
          statusMessage.value = formatError(failures[0].reason)
        }
      } catch (error) {
        if (!cancelled) {
          statusMessage.value = formatError(error)
        }
      } finally {
        if (!cancelled) {
          loading.input = false
          loading.report = false
          loading.news = false
        }
      }
    },
    { flush: 'post' }
  )

  function setSection(section: DashboardSection) {
    activeSection.value = section
  }

  function setSelectedDate(date: string) {
    selectedDate.value = date
  }

  function updateAccountLinks(accountId: string, links: string[]) {
    const current = dailyInput.value ?? buildEmptyDailyInput(selectedDate.value, accounts.value)
    dailyInput.value = {
      ...current,
      accounts: current.accounts.map((account) =>
        account.account_id === accountId
          ? { ...account, links }
          : account
      ),
    }
  }

  async function saveInput(): Promise<boolean> {
    loading.save = true
    try {
      const payload = {
        accounts: inputAccounts.value.map((account) => ({
          account_id: account.account_id,
          links: account.links,
        })),
      }
      dailyInput.value = await api.saveDailyInput(selectedDate.value, payload)
      statusMessage.value = `已保存 ${selectedDate.value} 的录入内容。`
      return true
    } catch (error) {
      statusMessage.value = formatError(error)
      return false
    } finally {
      loading.save = false
    }
  }

  async function generateReport() {
    loading.generate = true
    try {
      const saved = await saveInput()
      if (!saved) {
        return
      }
      opinionReport.value = await api.generateOpinionReport(selectedDate.value)
      reportList.value = await api.getReportList()
      activeSection.value = 'opinions'
      statusMessage.value = `已生成 ${selectedDate.value} 的日报，可直接查看。`
    } catch (error) {
      statusMessage.value = formatError(error)
    } finally {
      loading.generate = false
    }
  }

  async function refreshNews() {
    loading.news = true
    try {
      clsNews.value = await api.refreshClsNews(selectedDate.value)
      statusMessage.value = `财联社资讯已按 ${selectedDate.value} 刷新。`
    } catch (error) {
      statusMessage.value = formatError(error)
    } finally {
      loading.news = false
    }
  }

  return {
    activeSection,
    selectedDate,
    statusMessage,
    accounts,
    clsNews,
    reportList,
    opinionReport,
    dailyInput,
    inputAccounts,
    availableDates,
    loading,
    initializeDashboard,
    setSection,
    setSelectedDate,
    updateAccountLinks,
    saveInput,
    generateReport,
    refreshNews,
  }
}
