import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'

import { showConfirm, showSuccess } from '@/lib/feedback'
import {
  closeAdminManualRedeemTask,
  confirmAdminManualRedeemRole,
  createAdminManualRedeemSession,
  createAdminManualRedeemTask,
  fetchAdminManualRedeemDetail,
  fetchAdminManualRedeemSessionSummary,
  fetchAdminManualRedeemSkuSuggestions,
  fetchAdminTaskScreenshot,
  refreshAdminManualRedeemSession,
  redeemAdminManualRedeem,
  removeAdminManualRedeemSession,
} from '@/services/admin'
import type { AdminInventorySkuSuggestion, AdminManualRedeemDetail } from '@/types/admin'
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 useAdminManualRedeemPage() {
  const route = useRoute()
  const router = useRouter()

  // ── Form state (admin-only) ────────────────────────────────────────
  const form = reactive({
    proofValue: '',
    skuCode: '',
    remark: '',
  })
  const suggestions = ref<AdminInventorySkuSuggestion[]>([])

  // ── Core state ────────────────────────────────────────────────────
  const detail = ref<AdminManualRedeemDetail | null>(null)
  const detailLoading = ref(false)
  const createLoading = ref(false)
  const sessionLoading = ref(false)
  const roleConfirmLoading = ref(false)
  const redeemLoading = ref(false)
  const closeLoading = ref(false)
  const loginType = ref<TencentLoginType>(DEFAULT_LOGIN_TYPE)

  // ── Screenshot state (admin-only) ──────────────────────────────────
  const screenshotBlob = ref<Blob | null>(null)
  const screenshotUrl = ref('')
  const screenshotLoading = 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 manualRequest = computed(() => detail.value?.manualRequest || null)
  const activityInfo = computed(() => session.value?.activityInfo || null)
  const roleReady = computed(() => Boolean(activityInfo.value?.role?.ready))
  const roleConfirmed = computed(() =>
    Boolean(task.value && ['role_confirmed', 'redeeming', 'redeemed'].includes(task.value.status)),
  )
  const hasSession = computed(() => Boolean(session.value?.sessionId))
  const loginTypeLabel = computed(() => (loginType.value === 'wx' ? '微信' : 'QQ'))
  const currentTaskId = computed(() => Number(task.value?.taskId || route.query.taskId || 0) || 0)
  const reviewReady = computed(
    () => Boolean(session.value?.review?.capturedAt) && task.value?.status !== 'redeemed',
  )
  const resultReady = computed(
    () => Boolean(result.value?.screenshotReady) && task.value?.status === 'redeemed',
  )

  // ── Polling ────────────────────────────────────────────────────────
  const {
    pollWarningMessage,
    startPolling,
    resetPolling,
    resetPollingWarning,
    handleSilentPollingError,
  } = useSessionPolling({
    hasSession: computed(() => Boolean(task.value?.taskId && hasSession.value)),
    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 loginTabs = [
    { value: 'qq' as const, label: 'QQ账号登录' },
    { value: 'wx' as const, label: '微信账号登录' },
  ]

  const statusLabel = computed(() =>
    resolveTaskStatusLabel(task.value?.status, session.value?.status, 'admin'),
  )
  const initButtonLabel = computed(() => `生成${loginTypeLabel.value}二维码`)
  const scanInstruction = computed(
    () => `请让客户使用${loginTypeLabel.value}扫码，并在手机上确认登录`,
  )

  const proofValue = computed(() => manualRequest.value?.proofValue || order.value?.platformOrderId || '-')

  const { resultFacts } = useSessionResultFacts({
    order,
    orderItem,
    result,
    resultFactOverrides: {
      firstLabel: '唯一凭据',
      firstValue: proofValue,
    },
  })

  // Admin overrides roleFacts to include "所在大区" and exclude "任务状态"
  const adminRoleFacts = computed(() => [
    {
      label: '登录昵称',
      value: activityInfo.value?.nickname || '等待客户登录',
    },
    {
      label: '当前角色',
      value: activityInfo.value?.role?.roleName || '后端浏览器同步中',
      accent: true,
    },
    {
      label: '角色 ID',
      value: activityInfo.value?.role?.roleId || '未识别',
    },
    {
      label: '所在大区',
      value: activityInfo.value?.role?.area || '未识别',
    },
  ])

  const canConfirmRole = computed(() =>
    Boolean(
      task.value &&
      task.value.status === 'claimed' &&
      hasSession.value &&
      roleReady.value &&
      !roleConfirmLoading.value,
    ),
  )
  const canRedeem = computed(() =>
    Boolean(
      task.value &&
      ['role_confirmed', 'redeeming'].includes(task.value.status) &&
      !redeemLoading.value,
    ),
  )
  const redeemBlockedReason = computed(() =>
    buildRedeemBlockedReason({
      detail,
      hasSession,
      loginTypeLabel,
      redeemLoading,
      roleReady,
      roleConfirmed,
      sessionNotice,
      context: 'admin',
    }),
  )
  const redeemButtonLabel = computed(() => (redeemLoading.value ? '兑换中...' : '开始兑换'))
  const screenshotEmptyTitle = computed(() =>
    task.value?.status === 'redeemed' ? '未获取到结果图' : '等待角色截图',
  )
  const screenshotEmptyMessage = computed(() =>
    task.value?.status === 'redeemed'
      ? '本次兑换可能未生成最终截图，或截图仍在同步中。'
      : '客户登录并识别到角色后，这里会展示给客服复核的角色截图。',
  )
  const canCreateTask = computed(
    () => Boolean(form.proofValue.trim() && form.skuCode.trim()) && !createLoading.value,
  )
  const hasActiveTask = computed(() => Boolean(task.value?.taskId))

  // ── Watchers ───────────────────────────────────────────────────────
  watch(qrImage, () => {
    // QR image natural width reset handled by useSessionQrDisplay
  })

  watch(
    () => currentTaskId.value,
    (taskId, previousTaskId) => {
      if (!taskId || taskId === previousTaskId) {
        return
      }

      void loadDetail(taskId)
    },
    { immediate: true },
  )

  onMounted(() => {
    void loadSkuSuggestions()
  })

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

  // ── Helpers ────────────────────────────────────────────────────────
  function restartPollingIfNeeded(nextDetail = detail.value) {
    resetPolling()

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

  function resolveSkuName(skuCode: string) {
    const normalized = String(skuCode || '').trim()
    const matched = suggestions.value.find(
      (item) => String(item.skuCode || '').trim() === normalized,
    )
    return matched?.skuCode || normalized
  }

  // ── Screenshot helpers (admin-only) ───────────────────────────────
  async function loadScreenshotPreview(nextDetail = detail.value) {
    const taskId = Number(nextDetail?.task?.taskId || 0)
    const shouldFetch = Boolean(
      taskId && (nextDetail?.session?.review?.capturedAt || nextDetail?.result?.screenshotReady),
    )

    if (!shouldFetch) {
      clearScreenshotPreview()
      return
    }

    screenshotLoading.value = true

    try {
      const blob = await fetchAdminTaskScreenshot(taskId)
      clearScreenshotPreview()
      screenshotBlob.value = blob
      screenshotUrl.value = URL.createObjectURL(blob)
    } catch {
      clearScreenshotPreview()
    } finally {
      screenshotLoading.value = false
    }
  }

  function clearScreenshotPreview() {
    screenshotBlob.value = null

    if (screenshotUrl.value) {
      URL.revokeObjectURL(screenshotUrl.value)
      screenshotUrl.value = ''
    }
  }

  async function writeImageBlobToClipboard(blob: Blob, fallbackMessage: string) {
    if (
      typeof navigator === 'undefined' ||
      !navigator.clipboard ||
      typeof window === 'undefined' ||
      !('ClipboardItem' in window)
    ) {
      throw new Error('当前浏览器不支持直接复制图片，请改用截图发送或下载')
    }

    try {
      const ClipboardItemCtor = window.ClipboardItem as typeof ClipboardItem
      await navigator.clipboard.write([
        new ClipboardItemCtor({
          [blob.type || 'image/png']: blob,
        }),
      ])
    } catch (error) {
      throw error instanceof Error ? error : new Error(fallbackMessage)
    }
  }

  // ── API flows ─────────────────────────────────────────────────────
  async function loadSkuSuggestions(keyword = '') {
    try {
      const response = await fetchAdminManualRedeemSkuSuggestions({
        credentialType: 'tencent_code',
        keyword: keyword.trim(),
      })
      suggestions.value = response.data.items
    } catch (error) {
      notifyTencentActionError(error, '读取人工兑换 SKU 建议失败')
    }
  }

  async function loadDetail(taskId = currentTaskId.value) {
    if (!taskId) {
      detail.value = null
      clearScreenshotPreview()
      return false
    }

    detailLoading.value = true

    try {
      const response = await fetchAdminManualRedeemDetail(taskId)
      detail.value = response.data
      loginType.value = syncLoginTypeFromDetail(response.data, loginType.value)
      await loadScreenshotPreview(response.data)
      restartPollingIfNeeded()
      return true
    } catch (error) {
      notifyTencentActionError(error, '读取人工兑换详情失败')
      return false
    } finally {
      detailLoading.value = false
    }
  }

  async function createTaskNow() {
    if (!canCreateTask.value) {
      return
    }

    createLoading.value = true

    try {
      const response = await createAdminManualRedeemTask({
        proofValue: form.proofValue.trim(),
        skuCode: form.skuCode.trim(),
        skuName: resolveSkuName(form.skuCode),
        remark: form.remark.trim(),
      })

      detail.value = response.data
      loginType.value = syncLoginTypeFromDetail(response.data, loginType.value)
      await loadScreenshotPreview(response.data)
      await router.replace({
        path: route.path,
        query: {
          taskId: String(response.data.task.taskId),
        },
      })
      showSuccess(response.msg || '人工兑换任务已创建')
    } catch (error) {
      notifyTencentActionError(error, '创建人工兑换任务失败')
    } finally {
      createLoading.value = false
    }
  }

  async function createSessionFlow(nextLoginType = loginType.value) {
    if (!task.value?.taskId) {
      return
    }

    sessionLoading.value = true
    resetPolling()
    resetPollingWarning()

    try {
      loginType.value = nextLoginType
      const response = await createAdminManualRedeemSession(task.value.taskId, {
        loginType: nextLoginType,
        forceRecreate: hasSession.value,
      })

      detail.value = response.data
      loginType.value = syncLoginTypeFromDetail(response.data, nextLoginType)
      await loadScreenshotPreview(response.data)
      startPolling()
    } catch (error) {
      notifyTencentActionError(error, '创建人工兑换登录会话失败')
    } finally {
      sessionLoading.value = false
    }
  }

  async function refreshSessionFlow() {
    if (!task.value?.taskId) {
      return false
    }

    sessionLoading.value = true
    resetPolling()
    resetPollingWarning()

    try {
      const response = await refreshAdminManualRedeemSession(task.value.taskId)
      detail.value = response.data
      loginType.value = syncLoginTypeFromDetail(response.data, loginType.value)
      await loadScreenshotPreview(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 (!task.value?.taskId) {
      return false
    }

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

    resetPolling()
    resetPollingWarning()

    try {
      const response = await removeAdminManualRedeemSession(task.value.taskId)
      detail.value = response.data
      loginType.value = syncLoginTypeFromDetail(response.data, loginType.value)
      await loadScreenshotPreview(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 (!task.value?.taskId) {
      return false
    }

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

    try {
      const currentSession = detail.value?.session || null
      const response = await fetchAdminManualRedeemSessionSummary(task.value.taskId)
      detail.value = mergeSessionDetail(
        detail.value,
        response.data,
        (currentSession, nextSession) => ({
          review: nextSession.review ?? currentSession.review ?? null,
        }),
      )
      loginType.value = syncLoginTypeFromDetail(response.data, loginType.value)

      if (shouldRefreshQrImage(currentSession, response.data.session)) {
        const fullResponse = await fetchAdminManualRedeemDetail(task.value.taskId!)
        detail.value = mergeSessionDetail(
          detail.value,
          fullResponse.data,
          (currentSession, nextSession) => ({
            review: nextSession.review ?? currentSession.review ?? null,
          }),
        )
        loginType.value = syncLoginTypeFromDetail(fullResponse.data, loginType.value)
      }

      await loadScreenshotPreview(detail.value)

      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 (!task.value?.taskId || !canConfirmRole.value) {
      return
    }

    roleConfirmLoading.value = true

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

  async function redeemNow() {
    if (!task.value?.taskId || !canRedeem.value) {
      return
    }

    redeemLoading.value = true
    resetPolling()
    resetPollingWarning()

    try {
      const response = await redeemAdminManualRedeem(task.value.taskId)
      detail.value = response.data
      await loadScreenshotPreview(response.data)
      showSuccess(response.msg || '兑换完成')
      restartPollingIfNeeded(response.data)
    } catch (error) {
      notifyTencentActionError(error, '人工兑换失败')
      await refreshSessionSummary({ silent: true })
      restartPollingIfNeeded()
    } finally {
      redeemLoading.value = false
    }
  }

  async function closeTaskNow() {
    if (!task.value?.taskId) {
      return
    }

    try {
      await showConfirm(
        `确认关闭任务 ${task.value.taskNo} 吗？关闭后会释放未消耗的资源，并结束当前人工兑换流程。`,
        '关闭人工兑换',
      )
    } catch {
      return
    }

    closeLoading.value = true

    try {
      const response = await closeAdminManualRedeemTask(task.value.taskId)
      detail.value = response.data
      await loadScreenshotPreview(response.data)
      resetPolling()
      showSuccess(response.msg || '人工兑换任务已关闭')
    } catch (error) {
      notifyTencentActionError(error, '关闭人工兑换任务失败')
    } finally {
      closeLoading.value = false
    }
  }

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

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

    loginType.value = nextLoginType
  }

  function resetCurrentTask() {
    resetPolling()
    detail.value = null
    clearScreenshotPreview()
    void router.replace({
      path: route.path,
      query: {},
    })
  }

  async function copyQrImage() {
    if (!qrImage.value) {
      return false
    }

    try {
      const response = await fetch(qrImage.value)
      const blob = await response.blob()
      await writeImageBlobToClipboard(blob, '复制二维码失败')
      showSuccess('二维码已复制到剪贴板')
      return true
    } catch (error) {
      notifyTencentActionError(error, '复制二维码失败')
      return false
    }
  }

  async function copyScreenshot() {
    if (!screenshotBlob.value) {
      return false
    }

    try {
      await writeImageBlobToClipboard(screenshotBlob.value, '复制截图失败')
      showSuccess('截图已复制到剪贴板')
      return true
    } catch (error) {
      notifyTencentActionError(error, '复制截图失败')
      return false
    }
  }

  function downloadScreenshot() {
    if (!screenshotBlob.value || !screenshotUrl.value) {
      return false
    }

    const anchor = document.createElement('a')
    anchor.href = screenshotUrl.value
    anchor.download =
      task.value?.status === 'redeemed'
        ? `manual-redeem-result-${task.value?.taskNo || 'task'}.png`
        : `manual-redeem-review-${task.value?.taskNo || 'task'}.png`
    anchor.click()
    return true
  }

  return {
    form,
    suggestions,
    detail,
    detailLoading,
    createLoading,
    sessionLoading,
    roleConfirmLoading,
    redeemLoading,
    closeLoading,
    loginType,
    loginTypeLabel,
    loginTabs,
    session,
    task,
    order,
    orderItem,
    manualRequest,
    activityInfo,
    roleReady,
    roleConfirmed,
    hasSession,
    qrImage,
    qrFigureStyle,
    qrPreviewWidth,
    statusLabel,
    sessionNotice,
    roleFacts: adminRoleFacts,
    resultFacts,
    canConfirmRole,
    canRedeem,
    redeemBlockedReason,
    redeemButtonLabel,
    initButtonLabel,
    scanInstruction,
    screenshotEmptyTitle,
    screenshotEmptyMessage,
    screenshotUrl,
    screenshotLoading,
    reviewReady,
    resultReady,
    canCreateTask,
    hasActiveTask,
    createTaskNow,
    loadSkuSuggestions,
    createSessionFlow,
    refreshSessionFlow,
    closeSessionFlow,
    switchLoginType,
    confirmRoleNow,
    redeemNow,
    closeTaskNow,
    resetCurrentTask,
    handleQrImageLoad,
    copyQrImage,
    copyScreenshot,
    downloadScreenshot,
  }
}
