import { useEffect, useMemo, useState } from 'react'
import Taro from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import { Button, Checkbox } from '@nutui/nutui-react-taro'
import { TenantId } from '@/config/app'
import { getUserInfo, getWxOpenId } from '@/api/layout'
import { saveStorageByLoginUser } from '@/utils/server'
import {
  getStoredInviteParams,
  parseInviteParams,
  saveInviteParams,
  trackInviteSource,
  checkAndHandleInviteRelation,
} from '@/utils/invite'

interface GetPhoneNumberDetail {
  code?: string
  encryptedData?: string
  iv?: string
  errMsg?: string
}

interface GetPhoneNumberEvent {
  detail: GetPhoneNumberDetail
}

interface LoginResponse {
  data: {
    code?: number
    message?: string
    data?: {
      access_token: string
      user: any
    }
  }
}

async function getWeappLoginCode(): Promise<string | undefined> {
  try {
    const res = await new Promise<{ code?: string }>((resolve, reject) => {
      Taro.login({
        success: (r) => resolve(r as any),
        fail: (e) => reject(e),
      })
    })
    return res?.code
  } catch (_e) {
    return undefined
  }
}

async function ensureWxOpenIdSaved(opts: { user?: any; wxLoginCode?: string }) {
  // JSAPI 微信支付必须有 openid；注册/登录后立刻补齐，避免后续创建支付单失败。
  try {
    if (Taro.getEnv() !== Taro.ENV_TYPE.WEAPP) return
  } catch (_e) {
    if (process.env.TARO_ENV !== 'weapp') return
  }

  if (opts.user?.openid) return

  const code = opts.wxLoginCode || (await getWeappLoginCode())
  if (!code) return

  // 该接口一般会在服务端把 openid 绑定到当前登录用户；返回值并不一定包含 openid。
  await getWxOpenId({ code })

  // 同步本地 User（让后续页面/逻辑能直接读到 openid）
  try {
    const fresh = await getUserInfo()
    if (fresh) Taro.setStorageSync('User', fresh)
  } catch (_e) {
    // ignore: openid 已在服务端绑定，本地不同步也不影响后端创建支付订单
  }
}

function safeDecodeMaybeEncoded(input?: string): string {
  if (!input) return ''
  try {
    // Taro 路由参数通常是 URL 编码过的字符串
    return decodeURIComponent(input)
  } catch (_e) {
    return input
  }
}

function isTabBarUrl(url: string) {
  const pure = url.split('?')[0]
  return (
    pure === '/pages/index/index' ||
    pure === '/pages/cart/cart' ||
    pure === '/pages/user/user' ||
    pure === '/pages/category/index'
  )
}

const Register = () => {
  const [isAgree, setIsAgree] = useState(false)
  const [loading, setLoading] = useState(false)

  // 短信验证码登录仅在非微信小程序端展示
  const isWeapp = useMemo(() => {
    try {
      return Taro.getEnv() === Taro.ENV_TYPE.WEAPP
    } catch (_e) {
      return process.env.TARO_ENV === 'weapp'
    }
  }, [])

  const router = Taro.getCurrentInstance().router

  useEffect(() => {
    // register 页面不是 tabBar 页面，无需调用 hideTabBar
  }, [])

  const redirectUrl = useMemo(() => {
    const raw = (router?.params as any)?.redirect as string | undefined
    const decoded = safeDecodeMaybeEncoded(raw)
    if (!decoded) return ''
    return decoded.startsWith('/') ? decoded : `/${decoded}`
  }, [router?.params])

  // 如果从分享/二维码直接进入注册页（携带 inviter/source/t），先暂存邀请信息
  useEffect(() => {
    try {
      const inviteParams = parseInviteParams({ query: router?.params })
      if (inviteParams?.inviter) {
        saveInviteParams(inviteParams)
        trackInviteSource(inviteParams.source || 'qrcode', parseInt(inviteParams.inviter, 10))
      }
    } catch (e) {
      console.error('注册页处理邀请参数失败:', e)
    }
  }, [router?.params])

  const navigateAfterLogin = async () => {
    if (!redirectUrl) {
      await Taro.reLaunch({ url: '/pages/index/index' })
      return
    }

    if (isTabBarUrl(redirectUrl)) {
      // switchTab 不支持携带 query，这里按纯路径跳转
      await Taro.switchTab({ url: redirectUrl.split('?')[0] })
      return
    }

    // 替换当前注册页，避免返回栈里再回到注册页
    await Taro.redirectTo({ url: redirectUrl })
  }

  const handleGetPhoneNumber = async ({ detail }: GetPhoneNumberEvent) => {
    if (!isAgree) {
      Taro.showToast({ title: '请先勾选同意协议', icon: 'none' })
      return
    }
    if (loading) return

    const { code: phoneCode, encryptedData, iv, errMsg } = detail || {}
    if (!phoneCode || (errMsg && errMsg.includes('fail'))) {
      Taro.showToast({ title: '未授权手机号', icon: 'none' })
      return
    }

    try {
      setLoading(true)

      // 获取存储的邀请参数（推荐人ID）
      const inviteParams = getStoredInviteParams()
      const refereeId = inviteParams?.inviter ? parseInt(inviteParams.inviter, 10) : 0

      // 获取小程序登录 code（用于后续绑定 openid）
      const wxLoginCode = await getWeappLoginCode()

      const res = (await Taro.request({
        url: 'https://shop-api.websoft.top/api/wx-login/loginByMpWxPhone',
        method: 'POST',
        data: {
          code: phoneCode,
          encryptedData,
          iv,
          notVerifyPhone: true,
          refereeId: refereeId,
          sceneType: 'save_referee',
          tenantId: TenantId,
        },
        header: {
          'content-type': 'application/json',
          TenantId,
        },
      })) as unknown as LoginResponse

      if ((res as any)?.data?.code === 1) {
        Taro.showToast({ title: res.data.message || '登录失败', icon: 'none' })
        return
      }

      const token = res?.data?.data?.access_token
      const user = res?.data?.data?.user
      if (!token || !user?.userId) {
        Taro.showToast({ title: '登录失败，请重试', icon: 'none' })
        return
      }

      saveStorageByLoginUser(token, user)

      // 注册/登录成功后，立即补齐 openid（JSAPI 支付必需）
      try {
        await ensureWxOpenIdSaved({ user, wxLoginCode })
      } catch (e) {
        console.error('注册页绑定 openid 失败:', e)
      }

      // 登录成功后尝试绑定推荐关系（如果有待处理 inviter，会自动处理并清理参数）
      try {
        await checkAndHandleInviteRelation()
      } catch (e) {
        console.error('注册页登录后处理邀请关系失败:', e)
      }

      Taro.showToast({ title: '登录成功', icon: 'success' })
      setTimeout(() => {
        navigateAfterLogin().catch((e) => console.error('登录后跳转失败:', e))
      }, 800)
    } catch (e: any) {
      console.error('注册/登录失败:', e)
      Taro.showToast({ title: e?.message || '登录失败', icon: 'none' })
    } finally {
      setLoading(false)
    }
  }

  const goSmsLogin = () => {
    const inviteParams = getStoredInviteParams()
    const inviter = inviteParams?.inviter
    const source = inviteParams?.source
    const t = inviteParams?.t

    const params: Record<string, any> = {}
    if (redirectUrl) params.redirect = redirectUrl
    // 兜底：把 inviter 带过去，避免“先点注册再进入”时丢失
    if (inviter) params.inviter = inviter
    if (source) params.source = source
    if (t) params.t = t

    const qs = Object.entries(params)
      .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
      .join('&')
    Taro.navigateTo({ url: `/passport/sms-login${qs ? `?${qs}` : ''}` })
  }

  return (
    <>
      <View className='flex flex-col justify-center px-5 pt-5'>
        <View className='text-3xl text-center py-5 font-normal my-6'>注册/登录</View>

        <View className='flex flex-col gap-3 bg-green-600 py-1' style={{ borderRadius: '100px' }}>
          <Button
            type='primary'
            fill='solid'
            color='#07c160'
            block
            loading={loading}
            disabled={!isAgree || loading}
            open-type='getPhoneNumber'
            onGetPhoneNumber={handleGetPhoneNumber}
          >
            手机号一键注册/登录
          </Button>

          {!isWeapp && (
            <Button type='default' block disabled={!isAgree || loading} onClick={goSmsLogin}>
              短信验证码注册/登录
            </Button>
          )}
        </View>

        <View className='mt-6 flex text-sm items-center px-1'>
          <Checkbox checked={isAgree} onChange={(val) => setIsAgree(val)} />
          <Text className='text-gray-400' onClick={() => setIsAgree(!isAgree)}>
            勾选表示您已阅读并同意
          </Text>
          <Text
            onClick={() => Taro.navigateTo({ url: '/passport/agreement' })}
            className='text-blue-600'
          >
            《服务协议及隐私政策》
          </Text>
        </View>
      </View>
    </>
  )
}

export default Register
