import { computed, onBeforeUnmount, ref, watch } from 'vue'

import { showError, showSuccess } from '@/lib/feedback'
import {
  createTencentBrowserSession,
  refreshTencentBrowserSessionPage,
  removeTencentBrowserSession,
} from '@/services/tencent/session'
import { redeemTencentBrowserSession } from '@/services/tencent/redeem'
import type { TencentBrowserSessionData, TencentLoginType } from '@/types/tencent/session'

import { notifyTencentActionError } from './tencent/session-errors'
import { useTencentBrowserSessionPolling } from './tencent/useTencentBrowserSessionPolling'
import { useTencentBrowserSessionPresentation } from './tencent/useTencentBrowserSessionPresentation'

const DEFAULT_LOGIN_TYPE: TencentLoginType = 'qq'

export function useTencentBrowserSessionPage() {
  const sessionLoading = ref(false)
  const redeemLoading = ref(false)
  const loginType = ref<TencentLoginType>(DEFAULT_LOGIN_TYPE)
  const session = ref<TencentBrowserSessionData | null>(null)
  const redeemCode = ref('')
  const maxAttempts = ref(6)
  const roleConfirmed = ref(false)

  const activityInfo = computed(() => session.value?.activityInfo || null)
  const roleReady = computed(() => Boolean(activityInfo.value?.role?.ready))
  const hasSession = computed(() => Boolean(session.value?.sessionId))
  const loginTypeLabel = computed(() => (loginType.value === 'wx' ? '微信' : 'QQ'))

  const loginTabs = [
    { value: 'qq' as const, label: 'QQ账号登录' },
    { value: 'wx' as const, label: '微信账号登录' },
  ]

  const {
    refreshSession,
    resetPolling,
    resetPollingWarning,
    restartPollingIfActive,
    sessionNotice,
    startPolling,
  } = useTencentBrowserSessionPolling({
    session,
    sessionLoading,
    notifyActionError: notifyTencentActionError,
  })

  const {
    canRedeem,
    initButtonLabel,
    qrImage,
    redeemBlockedReason,
    redeemButtonLabel,
    resultFacts,
    roleFacts,
    scanInstruction,
    screenshotEmptyMessage,
    screenshotEmptyTitle,
    screenshotUrl,
    statusLabel,
  } = useTencentBrowserSessionPresentation({
    activityInfo,
    hasSession,
    loginTypeLabel,
    redeemLoading,
    roleConfirmed,
    roleReady,
    session,
    sessionLoading,
    sessionNotice,
  })

  watch(
    () =>
      [
        session.value?.sessionId || '',
        activityInfo.value?.nickname || '',
        activityInfo.value?.role?.roleId || '',
        activityInfo.value?.role?.roleName || '',
        activityInfo.value?.role?.area || '',
        activityInfo.value?.role?.partition || '',
      ].join('|'),
    () => {
      roleConfirmed.value = false
    },
  )

  async function createSessionFlow(nextLoginType = loginType.value) {
    resetPolling()
    resetPollingWarning()
    sessionLoading.value = true

    try {
      loginType.value = nextLoginType
      await teardownSession()

      const response = await createTencentBrowserSession({
        loginType: nextLoginType,
      })

      session.value = response.data
      startPolling()
    } catch (error) {
      notifyTencentActionError(error, '创建浏览器会话失败')
    } finally {
      sessionLoading.value = false
    }
  }

  async function reloadSessionPage() {
    if (!session.value?.sessionId) {
      return
    }

    resetPolling()
    resetPollingWarning()
    sessionLoading.value = true

    try {
      const response = await refreshTencentBrowserSessionPage(session.value.sessionId)

      session.value = response.data
      restartPollingIfActive(response.data)
    } catch (error) {
      notifyTencentActionError(error, '刷新后端页面失败')
      await refreshSession({ silent: true })
      restartPollingIfActive()
    } finally {
      sessionLoading.value = false
    }
  }

  async function switchLoginType(nextLoginType: TencentLoginType) {
    if (nextLoginType === loginType.value) {
      return
    }

    loginType.value = nextLoginType

    if (session.value?.sessionId) {
      await createSessionFlow(nextLoginType)
    }
  }

  async function redeemNow() {
    if (!session.value?.sessionId) {
      showError('请先创建浏览器会话')
      return
    }

    if (!redeemCode.value.trim()) {
      showError('请输入兑换码')
      return
    }

    redeemLoading.value = true
    resetPolling()
    resetPollingWarning()

    try {
      const response = await redeemTencentBrowserSession(session.value.sessionId, {
        code: redeemCode.value.trim(),
        maxAttempts: maxAttempts.value,
      })

      session.value = response.data
      showSuccess(response.msg || '兑换完成')
    } catch (error) {
      notifyTencentActionError(error, '浏览器兑换失败')
      await refreshSession({ silent: true })
    } finally {
      redeemLoading.value = false
    }
  }

  async function teardownSession() {
    if (!session.value?.sessionId) {
      return
    }

    const sessionId = session.value.sessionId
    session.value = null

    try {
      await removeTencentBrowserSession(sessionId)
    } catch {
      // ignore close failures on local teardown
    }
  }

  onBeforeUnmount(() => {
    resetPolling()
    void teardownSession()
  })

  return {
    activityInfo,
    canRedeem,
    teardownSession,
    createSessionFlow,
    hasSession,
    initButtonLabel,
    loginTabs,
    loginType,
    loginTypeLabel,
    maxAttempts,
    qrImage,
    redeemBlockedReason,
    redeemButtonLabel,
    redeemCode,
    redeemLoading,
    redeemNow,
    reloadSessionPage,
    resultFacts,
    roleConfirmed,
    roleFacts,
    scanInstruction,
    screenshotEmptyMessage,
    screenshotEmptyTitle,
    screenshotUrl,
    session,
    sessionLoading,
    sessionNotice,
    statusLabel,
    switchLoginType,
  }
}
