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

import { showSuccess } from '@/lib/feedback'
import {
  confirmClaimRole,
  createClaimSession,
  fetchClaimDetail,
  fetchClaimSessionSummary,
  refreshClaimSession,
  removeClaimSession,
  redeemClaim,
} from '@/services/claim'
import type { ClaimDetailData } from '@/types/claim'
import type { TencentLoginType } from '@/types/tencent/session'

import { notifyTencentActionError } from './tencent/session-errors'
import {
  useSessionPolling,
  useSessionQrDisplay,
  useSessionResultFacts,
  buildRedeemBlockedReason,
  resolveTaskStatusLabel,
  syncLoginTypeFromDetail,
  mergeSessionDetail,
  shouldRefreshQrImage,
  shouldKeepPolling,
  DEFAULT_LOGIN_TYPE,
} from './shared'

export function useClaimPage(token: string) {
  const detailLoading = ref(true)
  const sessionLoading = ref(false)
  const redeemLoading = ref(false)
  const roleConfirmLoading = ref(false)
  const loginType = ref<TencentLoginType>(DEFAULT_LOGIN_TYPE)
  const detail = ref<ClaimDetailData | null>(null)
  const roleConfirmed = ref(false)

  // ── Derived state ──────────────────────────────────────────────────
  const session = computed(() => detail.value?.session || null)
  const task = computed(() => detail.value?.task || null)
  const order = computed(() => detail.value?.order || null)
  const orderItem = computed(() => detail.value?.orderItem || null)
  const result = computed(() => detail.value?.result || null)
  const tokenStatus = computed(() => detail.value?.tokenStatus || 'active')
  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'))

  // ── Polling ────────────────────────────────────────────────────────
  const {
    pollWarningMessage,
    startPolling,
    resetPolling,
    resetPollingWarning,
    handleSilentPollingError,
  } = useSessionPolling({
    hasSession,
    shouldKeepPolling: computed(() => shouldKeepPolling(detail.value)),
    onPollTick: async () => { await refreshSessionSummary({ silent: true }) },
    pollWarningPrefix: '领取状态刷新失败',
  })

  const sessionNotice = computed(
    () => pollWarningMessage.value || session.value?.notice || task.value?.lastError || '',
  )

  // ── QR display ─────────────────────────────────────────────────────
  const { qrImage, qrFigureStyle, qrPreviewWidth, handleQrImageLoad } = useSessionQrDisplay({
    session,
  })

  // ── Presentation ───────────────────────────────────────────────────
  const screenshotUrl = computed(() => result.value?.screenshotUrl || '')
  const showScreenshot = computed(() => Boolean(screenshotUrl.value))
  const loginTabs = [
    { value: 'qq' as const, label: 'QQ账号登录' },
    { value: 'wx' as const, label: '微信账号登录' },
  ]

  const statusLabel = computed(() =>
    resolveTaskStatusLabel(task.value?.status, session.value?.status, 'claim'),
  )
  const initButtonLabel = computed(() => `开始初始化 ${loginTypeLabel.value} 登录`)
  const scanInstruction = computed(
    () => `请使用${loginTypeLabel.value}扫描二维码，并在手机上确认登录`,
  )

  // Claim pages show 4 role facts, but original only had 3 (no area).
  // Override roleFacts to match original exactly:
  const claimRoleFacts = computed(() => [
    {
      label: '登录昵称',
      value: activityInfo.value?.nickname || '等待扫码登录',
    },
    {
      label: '当前角色',
      value: activityInfo.value?.role?.roleName || '后端浏览器同步中',
      accent: true,
    },
    {
      label: '角色 ID',
      value: activityInfo.value?.role?.roleId || '未识别',
    },
    {
      label: '任务状态',
      value: statusLabel.value,
    },
  ])

  const { resultFacts } = useSessionResultFacts({
    order,
    orderItem,
    result,
  })

  const canConfirmRole = computed(() =>
    Boolean(
      task.value &&
        !task.value.requiresSupportReview &&
        hasSession.value &&
        roleReady.value &&
        task.value.status === 'claimed',
    ),
  )
  const canRedeem = computed(() =>
    Boolean(
      task.value &&
        !task.value.requiresSupportReview &&
        hasSession.value &&
        roleConfirmed.value &&
        !redeemLoading.value &&
        (task.value.status === 'role_confirmed' || task.value.status === 'redeeming'),
    ),
  )
  const redeemBlockedReason = computed(() =>
    buildRedeemBlockedReason({
      detail,
      hasSession,
      loginTypeLabel,
      redeemLoading,
      roleReady,
      roleConfirmed,
      sessionNotice,
      context: 'claim',
      tokenStatus,
      requiresSupportReview: computed(() => Boolean(task.value?.requiresSupportReview)),
    }),
  )
  const redeemButtonLabel = computed(() =>
    task.value?.requiresSupportReview ? '等待客服兑换' : '开始兑换',
  )
  const screenshotEmptyTitle = computed(() =>
    task.value?.status === 'redeemed' ? '本次没有可展示的截图' : '等待截图',
  )
  const screenshotEmptyMessage = computed(() =>
    task.value?.status === 'redeemed'
      ? '本次兑换可能未生成截图，或截图产物还未同步完成。'
      : '领取完成后，如本次生成了结果截图，这里会展示。',
  )

  // ── Watchers ───────────────────────────────────────────────────────
  watch(
    () =>
      [
        task.value?.taskId || '',
        activityInfo.value?.nickname || '',
        activityInfo.value?.role?.roleId || '',
        activityInfo.value?.role?.roleName || '',
        activityInfo.value?.role?.area || '',
        activityInfo.value?.role?.partition || '',
      ].join('|'),
    () => {
      roleConfirmed.value = Boolean(
        task.value?.status === 'role_confirmed' ||
          task.value?.status === 'redeeming' ||
          task.value?.status === 'redeemed',
      )
    },
    { immediate: true },
  )

  // ── Helpers ────────────────────────────────────────────────────────
  function applyLoginTypeFromDetail(nextDetail: ClaimDetailData) {
    loginType.value = syncLoginTypeFromDetail(nextDetail, loginType.value)
  }

  function restartPollingIfNeeded(nextDetail = detail.value) {
    resetPolling()

    if (shouldKeepPolling(nextDetail)) {
      startPolling()
    }
  }

  // ── API flows ─────────────────────────────────────────────────────
  async function loadDetail() {
    detailLoading.value = true

    try {
      const response = await fetchClaimDetail(token)

      detail.value = mergeSessionDetail(detail.value, response.data)
      applyLoginTypeFromDetail(response.data)
      restartPollingIfNeeded()
    } catch (error) {
      notifyTencentActionError(error, '领取详情加载失败')
    } finally {
      detailLoading.value = false
    }
  }

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

    try {
      loginType.value = nextLoginType
      const response = await createClaimSession(token, nextLoginType, {
        forceRecreate: hasSession.value,
      })

      detail.value = mergeSessionDetail(detail.value, response.data)
      applyLoginTypeFromDetail(response.data)
      startPolling()
    } catch (error) {
      notifyTencentActionError(error, '创建领取会话失败')
    } finally {
      sessionLoading.value = false
    }
  }

  async function reloadSessionPage() {
    if (!hasSession.value) {
      return false
    }

    sessionLoading.value = true
    resetPolling()
    resetPollingWarning()

    try {
      const response = await refreshClaimSession(token)

      detail.value = mergeSessionDetail(detail.value, response.data)
      applyLoginTypeFromDetail(response.data)
      restartPollingIfNeeded(response.data)
      return true
    } catch (error) {
      notifyTencentActionError(error, '刷新后端页面失败')
      await refreshSessionSummary({ silent: true })
      restartPollingIfNeeded()
      return false
    } finally {
      sessionLoading.value = false
    }
  }

  async function closeSessionFlow({ silent = false } = {}) {
    if (!hasSession.value) {
      return false
    }

    if (!silent) {
      sessionLoading.value = true
    }

    resetPolling()
    resetPollingWarning()

    try {
      const response = await removeClaimSession(token)

      detail.value = mergeSessionDetail(detail.value, response.data)
      applyLoginTypeFromDetail(response.data)

      if (!silent) {
        showSuccess(response.msg || '领取会话已关闭')
      }

      return true
    } catch (error) {
      if (!silent) {
        notifyTencentActionError(error, '关闭领取会话失败')
      }
      return false
    } finally {
      if (!silent) {
        sessionLoading.value = false
      }
    }
  }

  async function refreshSessionSummary({ silent = false } = {}) {
    if (!hasSession.value) {
      return false
    }

    if (!silent) {
      sessionLoading.value = true
      resetPollingWarning()
    }

    try {
      const currentSession = detail.value?.session || null
      const response = await fetchClaimSessionSummary(token)

      let nextDetail = mergeSessionDetail(detail.value, response.data)
      detail.value = nextDetail
      applyLoginTypeFromDetail(nextDetail)

      if (shouldRefreshQrImage(currentSession, response.data.session)) {
        const fullResponse = await fetchClaimDetail(token)

        nextDetail = mergeSessionDetail(nextDetail, fullResponse.data)
        detail.value = nextDetail
        applyLoginTypeFromDetail(nextDetail)
      }

      if (silent) {
        resetPollingWarning()
      }

      return true
    } catch (error) {
      if (silent) {
        handleSilentPollingError(error)
      } else {
        notifyTencentActionError(error, '领取会话状态刷新失败')
      }

      return false
    } finally {
      if (!silent) {
        sessionLoading.value = false
      }
    }
  }

  async function confirmRoleNow() {
    if (!canConfirmRole.value) {
      return
    }

    roleConfirmLoading.value = true

    try {
      const response = await confirmClaimRole(token)

      detail.value = mergeSessionDetail(detail.value, response.data)
      roleConfirmed.value = true
      showSuccess(response.msg || '角色已确认')
      restartPollingIfNeeded(response.data)
    } catch (error) {
      notifyTencentActionError(error, '角色确认失败')
      await refreshSessionSummary({ silent: true })
    } finally {
      roleConfirmLoading.value = false
    }
  }

  async function redeemNow() {
    if (!canRedeem.value) {
      return
    }

    redeemLoading.value = true
    resetPolling()
    resetPollingWarning()

    try {
      const response = await redeemClaim(token)

      detail.value = mergeSessionDetail(detail.value, response.data)
      showSuccess(response.msg || '兑换完成')
      restartPollingIfNeeded(response.data)
    } catch (error) {
      notifyTencentActionError(error, '领取兑换失败')
      await refreshSessionSummary({ silent: true })
      restartPollingIfNeeded()
    } finally {
      redeemLoading.value = false
    }
  }

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

    if (hasSession.value) {
      await createSessionFlow(nextLoginType)
      return
    }

    loginType.value = nextLoginType
  }

  // ── Lifecycle ──────────────────────────────────────────────────────
  loadDetail()

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

  return {
    detailLoading,
    sessionLoading,
    redeemLoading,
    roleConfirmLoading,
    loginType,
    loginTypeLabel,
    loginTabs,
    detail,
    task,
    order,
    orderItem,
    activityInfo,
    hasSession,
    qrImage,
    qrFigureStyle,
    qrPreviewWidth,
    statusLabel,
    session,
    sessionNotice,
    roleFacts: claimRoleFacts,
    resultFacts,
    roleConfirmed,
    roleReady,
    canConfirmRole,
    canRedeem,
    redeemBlockedReason,
    redeemButtonLabel,
    initButtonLabel,
    scanInstruction,
    screenshotEmptyTitle,
    screenshotEmptyMessage,
    screenshotUrl,
    showScreenshot,
    createSessionFlow,
    reloadSessionPage,
    closeSessionFlow,
    refreshSessionSummary,
    switchLoginType,
    confirmRoleNow,
    redeemNow,
    handleQrImageLoad,
  }
}
