import { ExclamationCircleOutlined, LoadingOutlined } from '@ant-design/icons'
import { Card, Empty, Spin } from 'antd'
import QRCode from 'qrcode'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useParams } from 'react-router'

import { isFeedbackDismissed, showConfirm, showError, showSuccess } from '@/lib/feedback'
import {
  confirmKuaishouCloudClaimRole,
  fetchClaimDetail,
  rebindKuaishouCloudClaimRole,
  redeemKuaishouCloudClaim,
  submitAffiliateDashClaim,
  submitClaimUid,
} from '@/services/claim'
import type { ClaimDetailData } from '@/types/claim'

import { AffiliateDashClaimPanel, AffiliateDashResultStep } from './ClaimAffiliateDashSteps'
import { FeifeiClaimPanel, FeifeiResultStep } from './ClaimFeifeiSteps'
import { ClaimHeaderCard } from './ClaimHeaderCard'
import { ClaimResultStep, KuaishouCloudClaimSteps } from './ClaimLewanSteps'
import { ClaimUidStep } from './ClaimUidStep'
import { resolveNextPollDelayMs, resolveRolePollDelayMs } from './claim-poll'
import { createClaimSnapshot, type ClaimSnapshot } from './claim-snapshot'

export default function ClaimPage() {
  const { token: routeToken } = useParams<{ token: string }>()
  const token = String(routeToken || '').trim()

  const [loading, setLoading] = useState(true)
  const [submittingUid, setSubmittingUid] = useState(false)
  const [uidInput, setUidInput] = useState('')
  const [refreshingRole, setRefreshingRole] = useState(false)
  const [confirmingRole, setConfirmingRole] = useState(false)
  const [rebindingRole, setRebindingRole] = useState(false)
  const [redeeming, setRedeeming] = useState(false)
  const [submittingSubmit, setSubmittingSubmit] = useState(false)
  const [errorMessage, setErrorMessage] = useState('')
  const [detail, setDetail] = useState<ClaimDetailData | null>(null)
  const [qrCodeDataUrl, setQrCodeDataUrl] = useState('')

  const pollTimerRef = useRef(0)
  const rolePollBaselineRef = useRef({ roleKey: '', at: 0 })

  const snapshot = useMemo(
    () => createClaimSnapshot(detail, { rebindingRole }),
    [detail, rebindingRole],
  )

  const stopPolling = useCallback(() => {
    if (pollTimerRef.current) {
      window.clearTimeout(pollTimerRef.current)
      pollTimerRef.current = 0
    }
  }, [])

  const generateQRCode = useCallback(async (url: string) => {
    if (!url) {
      setQrCodeDataUrl('')
      return
    }

    try {
      const dataUrl = await QRCode.toDataURL(url, {
        width: 280,
        margin: 2,
        color: {
          dark: '#0f172a',
          light: '#ffffff',
        },
      })
      setQrCodeDataUrl(dataUrl)
    } catch (error) {
      setQrCodeDataUrl('')
      console.error('生成二维码失败:', error)
    }
  }, [])

  const applyDetail = useCallback(
    async (nextDetail: ClaimDetailData) => {
      setDetail(nextDetail)
      const expectedUid = String(nextDetail.claimIdentity?.expectedUid || '').trim()
      if (expectedUid) {
        setUidInput(expectedUid)
      }
      await generateQRCode(
        String(
          nextDetail.kuaishouCloudFulfillment?.binding.bindUrl ||
            nextDetail.affiliateDash?.bindUrl ||
            '',
        ).trim(),
      )
    },
    [generateQRCode],
  )

  const loadDetail = useCallback(
    async (options: { silent?: boolean } = {}) => {
      if (!token) {
        setLoading(false)
        setErrorMessage('领取链接无效，请检查链接是否完整')
        stopPolling()
        return null
      }

      if (!options.silent) {
        setLoading(true)
      }
      setErrorMessage('')

      try {
        const response = await fetchClaimDetail(token)
        await applyDetail(response.data)
        return response.data
      } catch (error) {
        setErrorMessage(error instanceof Error ? error.message : '读取领取信息失败')
        stopPolling()
        return null
      } finally {
        if (!options.silent) {
          setLoading(false)
        }
      }
    },
    [applyDetail, stopPolling, token],
  )

  const resolveNextPollDelay = useCallback((nextSnapshot: ClaimSnapshot) => {
    const rolePoll = resolveRolePollDelayMs(nextSnapshot, rolePollBaselineRef.current)
    rolePollBaselineRef.current = rolePoll.baseline
    return resolveNextPollDelayMs(nextSnapshot, rolePoll.delay)
  }, [])

  useEffect(() => {
    rolePollBaselineRef.current = { roleKey: '', at: 0 }
    setDetail(null)
    setQrCodeDataUrl('')
    setUidInput('')
    void loadDetail()

    return () => {
      stopPolling()
    }
  }, [loadDetail, stopPolling])

  useEffect(() => {
    stopPolling()
    const delay = resolveNextPollDelay(snapshot)
    if (!delay) {
      return undefined
    }

    pollTimerRef.current = window.setTimeout(() => {
      pollTimerRef.current = 0
      void loadDetail({ silent: true })
    }, delay)

    return () => {
      stopPolling()
    }
  }, [loadDetail, resolveNextPollDelay, snapshot, stopPolling])

  async function handleSubmitUid() {
    const uid = uidInput.trim()
    if (!uid) {
      showError('请输入游戏 UID')
      return
    }

    setSubmittingUid(true)
    try {
      const response = await submitClaimUid(token, uid)
      await applyDetail(response.data)
      showSuccess('UID 已提交')
    } catch (error) {
      showError(error instanceof Error ? error.message : '提交 UID 失败')
    } finally {
      setSubmittingUid(false)
    }
  }

  async function handleSubmitAffiliateDash() {
    const affiliateDash = snapshot.affiliateDash
    const uid = uidInput.trim() || affiliateDash?.gameAccount || ''
    const bindUuid = affiliateDash?.bindUuid || ''

    if (!uid || !bindUuid) {
      showError('绑定尚未完成，请先绑定账号')
      return
    }

    setSubmittingSubmit(true)
    try {
      const response = await submitAffiliateDashClaim(token, { gameAccount: uid, bindUuid })
      await applyDetail(response.data)
      showSuccess('发货已提交')
    } catch (error) {
      showError(error instanceof Error ? error.message : '提交发货失败')
    } finally {
      setSubmittingSubmit(false)
    }
  }

  async function refreshRole() {
    setRefreshingRole(true)
    try {
      const nextDetail = await loadDetail({ silent: true })
      const nextSnapshot = createClaimSnapshot(nextDetail, { rebindingRole })

      if (nextSnapshot.isUidMatched) {
        showSuccess('角色信息已匹配，可确认兑换')
      } else if (nextSnapshot.roleId) {
        showError(
          `当前绑定角色 ID（${nextSnapshot.roleId}）与填写 UID（${nextSnapshot.expectedUid || '-'}）不一致`,
        )
      } else if (nextDetail) {
        showError(
          nextSnapshot.flow?.role.errorMessage ||
            '暂时还没有识别到角色信息，请完成绑定后稍等片刻再试',
        )
      }
    } finally {
      setRefreshingRole(false)
    }
  }

  async function confirmRole() {
    setConfirmingRole(true)
    try {
      const response = await confirmKuaishouCloudClaimRole(token)
      await applyDetail(response.data)
      showSuccess('角色已确认，进入下一步')
    } catch (error) {
      showError(error instanceof Error ? error.message : '确认角色失败')
    } finally {
      setConfirmingRole(false)
    }
  }

  async function confirmRedeem() {
    try {
      await showConfirm('兑换后不可取消，也不可退货。请确认 UID 与商品信息完全正确。', '确认兑换', {
        okText: '确认兑换',
        okButtonProps: { danger: true },
      })
    } catch (error) {
      if (!isFeedbackDismissed(error)) {
        showError('确认弹窗已关闭')
      }
      return
    }

    setRedeeming(true)
    try {
      const response = await redeemKuaishouCloudClaim(token)
      await applyDetail(response.data)
      showSuccess('兑换请求已提交')
    } catch (error) {
      showError(error instanceof Error ? error.message : '兑换失败')
    } finally {
      setRedeeming(false)
    }
  }

  async function rebindRole() {
    try {
      await showConfirm(
        '换绑后当前绑定链接会失效，系统会退还当前虚拟号并生成新的绑定二维码。请使用你填写的 UID 对应角色重新绑定。',
        '确认换绑角色',
        {
          okText: '确认换绑',
          okButtonProps: { danger: true },
        },
      )
    } catch (error) {
      if (!isFeedbackDismissed(error)) {
        showError('确认弹窗已关闭')
      }
      return
    }

    setRebindingRole(true)
    try {
      const response = await rebindKuaishouCloudClaimRole(token)
      await applyDetail(response.data)
      showSuccess('新的绑定二维码已生成，请重新绑定角色')
    } catch (error) {
      showError(error instanceof Error ? error.message : '换绑角色失败')
    } finally {
      setRebindingRole(false)
    }
  }

  function openBindUrl(useCurrentPage = false) {
    const bindUrl = String(
      snapshot.flow?.binding.bindUrl || snapshot.affiliateDash?.bindUrl || '',
    ).trim()
    if (!bindUrl) {
      showError('绑定链接还没准备好，请稍后刷新')
      return
    }

    if (useCurrentPage) {
      window.location.assign(bindUrl)
      return
    }

    window.open(bindUrl, '_blank', 'noopener,noreferrer')
  }

  function openFeifeiUrl(useCurrentPage = false) {
    const url = String(
      snapshot.feifei?.h5UrlWithUid ||
        snapshot.feifei?.h5.rechargeUrl ||
        snapshot.feifei?.h5.entryUrl ||
        '',
    ).trim()

    if (!snapshot.hasExpectedUid) {
      showError('请先填写游戏 UID')
      return
    }

    if (!url) {
      showError('领取链接还没准备好，请稍后刷新')
      return
    }

    if (useCurrentPage) {
      window.location.assign(url)
      return
    }

    window.open(url, '_blank', 'noopener,noreferrer')
  }

  return (
    <main className="claim-page">
      <ClaimHeaderCard
        order={snapshot.order}
        product={snapshot.product}
        currentStep={snapshot.currentStep}
        progressText={snapshot.progressText}
        expectedUid={snapshot.expectedUid}
      />

      {loading ? (
        <Card className="claim-content-card claim-state-card">
          <Spin indicator={<LoadingOutlined spin />} size="large" />
          <p>正在读取当前领取进度...</p>
        </Card>
      ) : errorMessage ? (
        <Card className="claim-content-card claim-state-card">
          <ExclamationCircleOutlined className="claim-large-icon claim-icon-error" />
          <p>{errorMessage}</p>
        </Card>
      ) : !detail ? (
        <Card className="claim-content-card claim-state-card">
          <Empty description="流程数据不完整，请联系客服处理" />
        </Card>
      ) : snapshot.currentStep === 1 ? (
        <ClaimUidStep
          uidInput={uidInput}
          submitting={submittingUid}
          onChange={setUidInput}
          onSubmit={() => void handleSubmitUid()}
        />
      ) : snapshot.hasRedeemResult ? (
        snapshot.isFeifeiFlow ? (
          <FeifeiResultStep snapshot={snapshot} />
        ) : snapshot.isAffiliateDashFlow ? (
          <AffiliateDashResultStep snapshot={snapshot} />
        ) : (
          <ClaimResultStep snapshot={snapshot} />
        )
      ) : snapshot.isAffiliateDashFlow && snapshot.affiliateDash ? (
        <AffiliateDashClaimPanel
          affiliateDash={snapshot.affiliateDash}
          expectedUid={snapshot.expectedUid}
          order={snapshot.order}
          product={snapshot.product}
          taskLastError={snapshot.task?.lastError}
          qrCodeDataUrl={qrCodeDataUrl}
          submittingUid={submittingUid}
          submittingSubmit={submittingSubmit}
          uidInput={uidInput}
          onUidChange={setUidInput}
          onResubmitUid={() => void handleSubmitUid()}
          onSubmit={() => void handleSubmitAffiliateDash()}
          onOpenBindUrl={openBindUrl}
        />
      ) : snapshot.isFeifeiFlow && snapshot.feifei ? (
        <FeifeiClaimPanel
          feifei={snapshot.feifei}
          expectedUid={snapshot.expectedUid}
          order={snapshot.order}
          product={snapshot.product}
          taskLastError={snapshot.task?.lastError}
          onOpen={() => openFeifeiUrl(false)}
          uidInput={uidInput}
          submittingUid={submittingUid}
          onUidChange={setUidInput}
          onResubmitUid={() => void handleSubmitUid()}
        />
      ) : snapshot.flow ? (
        <KuaishouCloudClaimSteps
          snapshot={snapshot}
          qrCodeDataUrl={qrCodeDataUrl}
          refreshingRole={refreshingRole}
          confirmingRole={confirmingRole}
          rebindingRole={rebindingRole}
          redeeming={redeeming}
          onOpenBindUrl={openBindUrl}
          onRefreshRole={refreshRole}
          onRebindRole={rebindRole}
          onConfirmRole={confirmRole}
          onConfirmRedeem={confirmRedeem}
          uidInput={uidInput}
          submittingUid={submittingUid}
          onUidChange={setUidInput}
          onResubmitUid={() => void handleSubmitUid()}
        />
      ) : (
        <Card className="claim-content-card claim-state-card">
          <Empty description="流程数据不完整，请联系客服处理" />
        </Card>
      )}
    </main>
  )
}
