<template>
  <div class="invite-accept-page">
    <div class="invite-card">
      <!-- 加载中 -->
      <div v-if="loading" class="invite-loading">
        <a-spin size="large" />
        <p class="loading-text">正在验证邀请...</p>
      </div>

      <!-- 邀请信息 -->
      <div v-else-if="inviteInfo && !accepted" class="invite-content">
        <div class="invite-header">
          <div class="app-icon">
            <img v-if="inviteInfo.appIcon" :src="inviteInfo.appIcon" alt="app icon" />
            <span v-else class="app-icon-text">{{ (inviteInfo.appName || 'A').charAt(0).toUpperCase() }}</span>
          </div>
          <h2 class="invite-title">邀请你加入应用</h2>
          <p class="app-name">{{ inviteInfo.appName }}</p>
        </div>

        <div class="invite-details">
          <div class="detail-item">
            <span class="detail-label">邀请人</span>
            <div class="inviter-info">
              <a-avatar :src="inviteInfo.inviterAvatar" size="small" class="inviter-avatar">
                {{ (inviteInfo.inviterName || '?').charAt(0).toUpperCase() }}
              </a-avatar>
              <span class="inviter-name">{{ inviteInfo.inviterName || '未知' }}</span>
            </div>
          </div>
          <div class="detail-item">
            <span class="detail-label">你的角色</span>
            <a-tag :color="roleColor(inviteInfo.role)">{{ roleText(inviteInfo.role) }}</a-tag>
          </div>
          <div class="detail-item">
            <span class="detail-label">有效期至</span>
            <span class="detail-value">{{ formatExpireTime(inviteInfo.expireTime) }}</span>
          </div>
        </div>

        <!-- 已登录：直接显示接受邀请按钮 -->
        <div v-if="isLoggedIn" class="invite-actions">
          <a-button type="primary" size="large" block :loading="accepting" @click="handleAccept">
            {{ accepting ? '处理中...' : '接受邀请' }}
          </a-button>
          <a-button size="large" block style="margin-top: 12px" @click="goToHome">
            暂不加入
          </a-button>
        </div>

        <!-- 未登录：显示手机号登录表单 -->
        <div v-else class="invite-login-form">
          <div class="login-divider">
            <span>请先登录以接受邀请</span>
          </div>

          <a-form ref="formRef" :model="form" :rules="rules" class="login-form">
            <a-form-item name="phone">
              <a-input
                v-model:value="form.phone"
                size="large"
                allow-clear
                :maxlength="11"
                placeholder="请输入手机号"
                class="form-input"
              >
                <template #prefix>
                  <span class="phone-prefix">+86</span>
                  <span class="phone-prefix-divider" />
                </template>
              </a-input>
            </a-form-item>

            <a-form-item name="smsCode">
              <div class="captcha-row">
                <a-input
                  v-model:value="form.smsCode"
                  size="large"
                  allow-clear
                  :maxlength="6"
                  placeholder="请输入验证码"
                  class="form-input"
                  @press-enter="handleLoginAndAccept"
                />
                <button
                  class="sms-btn"
                  :disabled="countdown > 0"
                  :class="{ disabled: countdown > 0 }"
                  @click.prevent="openImgCodeModal"
                >
                  <span v-if="countdown <= 0">获取验证码</span>
                  <span v-else>{{ countdown }}秒后重发</span>
                </button>
              </div>
            </a-form-item>

            <!-- 注册协议 -->
            <div class="agreement-row">
              <a-checkbox v-model:checked="form.agreement">
                <span class="agreement-text">
                  我已阅读并同意
                  <NuxtLink to="/agreement" target="_blank" class="agreement-link" @click.stop>注册协议</NuxtLink>
                  和
                  <NuxtLink to="/privacy" target="_blank" class="agreement-link" @click.stop>隐私政策</NuxtLink>
                </span>
              </a-checkbox>
            </div>

            <a-form-item>
              <a-button
                block
                size="large"
                type="primary"
                :loading="loginLoading"
                class="submit-btn"
                @click="handleLoginAndAccept"
              >
                {{ loginLoading ? '登录中...' : '登录并加入' }}
              </a-button>
            </a-form-item>
          </a-form>

          <div class="other-login-options">
            <span class="option-text">其他登录方式</span>
            <div class="option-btns">
              <a-button type="link" size="small" @click="goToFullLogin">
                账号密码登录
              </a-button>
            </div>
          </div>
        </div>
      </div>

      <!-- 已接受 -->
      <div v-else-if="accepted" class="invite-success">
        <CheckCircleOutlined class="success-icon" />
        <h2 class="success-title">加入成功！</h2>
        <p class="success-desc">你已成为 {{ inviteInfo?.appName }} 的 {{ roleText(inviteInfo?.role || '') }}</p>
        <a-button type="primary" size="large" @click="goToApp">
          进入应用
        </a-button>
      </div>

      <!-- 错误状态 -->
      <div v-else-if="error" class="invite-error">
        <CloseCircleOutlined class="error-icon" />
        <h2 class="error-title">邀请无效</h2>
        <p class="error-desc">{{ error }}</p>
        <a-button type="primary" @click="goToHome">
          返回首页
        </a-button>
      </div>
    </div>

    <!-- 图形验证码弹窗 -->
    <a-modal v-model:open="imgCodeModalOpen" :width="360" :footer="null" title="安全验证">
      <p class="modal-tip">请先完成图形验证码</p>
      <div class="captcha-row modal-captcha">
        <a-input
          v-model:value="imgCode"
          size="large"
          allow-clear
          :maxlength="5"
          placeholder="请输入验证码"
          @press-enter="sendSmsCode"
        />
        <button class="captcha-img-btn" @click.prevent="changeCaptcha">
          <img v-if="captcha" alt="captcha" :src="captcha" />
          <span v-else class="captcha-placeholder">点击获取</span>
        </button>
      </div>
      <a-button block size="large" type="primary" :loading="sendingSms" @click="sendSmsCode">
        发送短信验证码
      </a-button>
    </a-modal>

    <!-- 选择账号弹窗 -->
    <a-modal v-model:open="selectUserOpen" :width="520" :footer="null" title="选择登录账号">
      <a-list item-layout="horizontal" :data-source="admins">
        <template #renderItem="{ item }">
          <a-list-item class="list-item" @click="selectUser(item)">
            <a-list-item-meta :description="`租户ID: ${item.tenantId}`">
              <template #title>{{ item.tenantName || item.username }}</template>
              <template #avatar>
                <a-avatar :src="item.avatar" />
              </template>
            </a-list-item-meta>
            <template #actions><RightOutlined /></template>
          </a-list-item>
        </template>
      </a-list>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { message, type FormInstance } from 'ant-design-vue'
import { CheckCircleOutlined, CloseCircleOutlined, RightOutlined } from '@ant-design/icons-vue'
import { verifyInvite, acceptInvite } from '@/api/app/invite'
import { getCaptcha, loginBySms, sendSmsCaptcha } from '@/api/passport/login'
import { listAdminsByPhoneAll } from '@/api/system/user'
import { getUserInfo } from '@/api/layout'
import { getToken } from '@/utils/token-util'
import { TEMPLATE_ID } from '@/config/setting'
import type { User } from '@/api/system/user/model'

interface InviteInfo {
  appId: number
  appName: string
  appIcon?: string
  inviterName: string
  inviterAvatar?: string
  role: string
  expireTime: string
}

const route = useRoute()
const router = useRouter()

const loading = ref(true)
const accepting = ref(false)
const accepted = ref(false)
const error = ref('')
const inviteInfo = ref<InviteInfo | null>(null)

const token = computed(() => route.query.token as string)
const appId = computed(() => Number(route.query.appId))
const role = computed(() => route.query.role as string)

const isLoggedIn = computed(() => {
  if (import.meta.client) {
    return !!getToken()
  }
  return false
})

// 登录表单相关
const formRef = ref<FormInstance>()
const form = reactive({
  phone: '',
  smsCode: '',
  agreement: false,
  tenantId: undefined as number | undefined
})

const phoneReg = /^1[3-9]\d{9}$/
const rules = reactive({
  phone: [
    { required: true, message: '请输入手机号', type: 'string' },
    { pattern: phoneReg, message: '手机号格式不正确', trigger: 'blur' }
  ],
  smsCode: [{ required: true, message: '请输入验证码', type: 'string' }]
})

const loginLoading = ref(false)
const captcha = ref('')
const captchaText = ref('')
const imgCodeModalOpen = ref(false)
const imgCode = ref('')
const sendingSms = ref(false)
const countdown = ref(0)
let countdownTimer: ReturnType<typeof setInterval> | null = null

const selectUserOpen = ref(false)
const admins = ref<User[]>([])

// 自动加入标记（防止重复触发）
const autoJoined = ref(false)

onMounted(async () => {
  if (!token.value || !appId.value) {
    error.value = '邀请链接不完整，请确认链接是否正确'
    loading.value = false
    return
  }

  try {
    const res = await verifyInvite({ token: token.value, appId: appId.value })
    if (res.data?.code === 0 && res.data.data) {
      inviteInfo.value = res.data.data

      // 已登录用户：验证通过后自动加入，不用再点按钮
      if (isLoggedIn.value && !autoJoined.value) {
        autoJoined.value = true
        await handleAccept()
      }
    } else {
      error.value = res.data?.message || '邀请已过期或无效'
    }
  } catch (e: any) {
    localVerifyInvite()
  } finally {
    loading.value = false
  }
})

onUnmounted(() => {
  stopCountdown()
})

function localVerifyInvite() {
  const localInvite = localStorage.getItem(`invite_token_${token.value}`)
  if (localInvite) {
    try {
      const data = JSON.parse(localInvite)
      if (data.appId === appId.value && data.expireTime > Date.now()) {
        inviteInfo.value = {
          appId: data.appId,
          appName: '应用',
          inviterName: '邀请人',
          role: data.role,
          expireTime: new Date(data.expireTime).toISOString(),
        }
      } else {
        error.value = '邀请已过期'
      }
    } catch {
      error.value = '邀请验证失败'
    }
  } else {
    error.value = '邀请验证失败'
  }
}

function roleText(role?: string): string {
  const map: Record<string, string> = { owner: '所有者', admin: '管理员', developer: '开发者', viewer: '只读成员' }
  return role ? (map[role] || role) : ''
}

function roleColor(role?: string): string {
  const map: Record<string, string> = { owner: 'red', admin: 'orange', developer: 'blue', viewer: 'default' }
  return role ? (map[role] || 'default') : 'default'
}

function formatExpireTime(time?: string): string {
  if (!time) return ''
  const date = new Date(time)
  return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
}

function goToHome() {
  router.push('/')
}

function goToApp() {
  router.push('/console/apps')
}

function goToFullLogin() {
  const returnUrl = encodeURIComponent(window.location.href)
  router.push(`/login?from=${returnUrl}`)
}

async function handleAccept() {
  if (!token.value || !appId.value) return
  accepting.value = true
  try {
    const res = await acceptInvite({ token: token.value, appId: appId.value, role: role.value })
    if (res.data?.code === 0) {
      accepted.value = true
      message.success('已成功加入应用')
    } else {
      message.error(res.data?.message || '接受邀请失败')
    }
  } catch (e: any) {
    localSimulateAccept()
  } finally {
    accepting.value = false
  }
}

function localSimulateAccept() {
  const localInvite = localStorage.getItem(`invite_token_${token.value}`)
  if (localInvite) {
    accepted.value = true
    message.success('已成功加入应用（本地模式）')
  } else {
    message.error('接受邀请失败')
  }
}

// 登录相关方法
function stopCountdown() {
  if (countdownTimer) clearInterval(countdownTimer)
  countdownTimer = null
  countdown.value = 0
}

async function changeCaptcha() {
  try {
    const data = await getCaptcha()
    captcha.value = data.base64
    captchaText.value = data.text
  } catch (e: unknown) {
    message.error(e instanceof Error ? e.message : '获取验证码失败')
  }
}

function openImgCodeModal() {
  if (!form.phone) return message.error('请输入手机号')
  imgCode.value = ''
  changeCaptcha()
  imgCodeModalOpen.value = true
}

async function sendSmsCode() {
  if (!imgCode.value) return message.error('请输入图形验证码')
  if (captchaText.value && imgCode.value.toLowerCase() !== captchaText.value.toLowerCase()) {
    return message.error('图形验证码不正确')
  }

  sendingSms.value = true
  try {
    await sendSmsCaptcha({ phone: form.phone })
    message.success('验证码已发送')
    imgCodeModalOpen.value = false
    countdown.value = 60
    stopCountdown()
    countdownTimer = setInterval(() => {
      countdown.value -= 1
      if (countdown.value <= 0) stopCountdown()
    }, 1000)
  } catch (e: unknown) {
    message.error(e instanceof Error ? e.message : '发送失败')
  } finally {
    sendingSms.value = false
  }
}

async function handleLoginAndAccept() {
  if (!formRef.value) return
  if (!form.agreement) {
    return message.error('请先同意注册协议和隐私政策')
  }

  loginLoading.value = true
  try {
    await formRef.value.validate()

    // 1. 先登录
    const msg = await loginBySms({
      phone: form.phone,
      code: String(form.smsCode || '').toLowerCase(),
      tenantId: form.tenantId,
      remember: true
    })

    // 需要选择账号
    if (msg === '请选择登录用户') {
      selectUserOpen.value = true
      admins.value = await listAdminsByPhoneAll({
        phone: form.phone,
        templateId: Number(TEMPLATE_ID)
      })
      loginLoading.value = false
      return
    }

    message.success('登录成功')

    // 2. 保存用户信息
    await ensureUserIdPersisted()

    // 3. 自动接受邀请
    await autoAcceptAfterLogin()

  } catch (e: unknown) {
    message.error(e instanceof Error ? e.message : '登录失败')
  } finally {
    loginLoading.value = false
  }
}

async function selectUser(user: User) {
  form.tenantId = user.tenantId
  selectUserOpen.value = false
  loginLoading.value = true
  try {
    await loginBySms({
      phone: form.phone,
      code: String(form.smsCode || '').toLowerCase(),
      tenantId: user.tenantId,
      remember: true
    })
    message.success('登录成功')
    await ensureUserIdPersisted()
    await autoAcceptAfterLogin()
  } catch (e: unknown) {
    message.error(e instanceof Error ? e.message : '登录失败')
  } finally {
    loginLoading.value = false
  }
}

async function autoAcceptAfterLogin() {
  if (!token.value || !appId.value) {
    message.error('邀请信息已失效')
    return
  }

  accepting.value = true
  try {
    const res = await acceptInvite({ token: token.value, appId: appId.value, role: role.value })
    if (res.data?.code === 0) {
      accepted.value = true
      message.success('已成功加入应用')
    } else {
      message.error(res.data?.message || '接受邀请失败')
    }
  } catch (e: any) {
    message.error('接受邀请失败，请手动重试')
  } finally {
    accepting.value = false
  }
}

function persistUserId(userId: unknown) {
  if (!import.meta.client) return
  const n = typeof userId === 'number' ? userId : Number(userId)
  if (Number.isFinite(n) && n > 0) localStorage.setItem('UserId', String(n))
}

async function ensureUserIdPersisted(seed?: unknown) {
  if (!import.meta.client) return
  persistUserId(seed)
  try {
    if (localStorage.getItem('UserId')) return
  } catch {
    // ignore
  }

  try {
    const me = await getUserInfo()
    persistUserId(me.userId)
  } catch {
    // ignore
  }
}
</script>

<style scoped>
.invite-accept-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  padding: 20px;
}
.invite-card {
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
  width: 100%;
  max-width: 420px;
  padding: 40px 32px;
  text-align: center;
}
.invite-loading { padding: 40px 0; }
.loading-text { margin-top: 16px; color: #666; font-size: 14px; }
.invite-header { margin-bottom: 32px; }
.app-icon {
  width: 80px; height: 80px; border-radius: 16px; overflow: hidden;
  margin: 0 auto 16px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  display: flex; align-items: center; justify-content: center;
}
.app-icon img { width: 100%; height: 100%; object-fit: cover; }
.app-icon-text { font-size: 36px; font-weight: 700; color: #fff; }
.invite-title { font-size: 20px; font-weight: 600; color: #1a1a1a; margin-bottom: 8px; }
.app-name { font-size: 16px; color: #666; }
.invite-details {
  background: #f8f9fa; border-radius: 12px; padding: 20px; margin-bottom: 24px;
}
.detail-item {
  display: flex; justify-content: space-between; align-items: center;
  padding: 10px 0; border-bottom: 1px solid #eee;
}
.detail-item:last-child { border-bottom: none; }
.detail-label { color: #999; font-size: 14px; }
.detail-value { color: #333; font-size: 14px; font-weight: 500; }
.inviter-info {
  display: flex;
  align-items: center;
  gap: 8px;
}
.inviter-avatar {
  background: #4e6ef2;
  flex-shrink: 0;
}
.inviter-name {
  color: #333;
  font-size: 14px;
  font-weight: 500;
}
.invite-actions { margin-top: 24px; }

/* 登录表单样式 */
.invite-login-form { margin-top: 24px; }
.login-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
  color: #999;
  font-size: 13px;
}
.login-divider::before,
.login-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: #eee;
}

.login-form :deep(.ant-input-affix-wrapper),
.login-form :deep(.ant-input) {
  border-radius: 10px;
  border-color: #ebebeb;
  background: #fafafa;
  transition: all 0.2s;
  padding-top: 6px;
  padding-bottom: 6px;
  align-items: center;
}
.login-form :deep(.ant-input-affix-wrapper:focus),
.login-form :deep(.ant-input-affix-wrapper-focused) {
  border-color: #6366f1;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
}
.login-form :deep(.ant-form-item) {
  margin-bottom: 16px;
}

.phone-prefix {
  font-size: 14px;
  color: #555;
  font-weight: 500;
  margin-right: 2px;
}
.phone-prefix-divider {
  display: inline-block;
  width: 1px;
  height: 14px;
  background: #d9d9d9;
  margin-left: 8px;
  vertical-align: middle;
}

.captcha-row {
  display: flex;
  gap: 10px;
  align-items: center;
}
.captcha-row :deep(.ant-input) {
  flex: 1;
  min-width: 0;
  border-radius: 10px !important;
}

.sms-btn {
  flex-shrink: 0;
  padding: 0 16px;
  height: 44px;
  border: 1px solid #6366f1;
  border-radius: 10px;
  background: transparent;
  color: #6366f1;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.2s;
  outline: none;
}
.sms-btn:hover:not(.disabled) {
  background: #6366f1;
  color: #fff;
}
.sms-btn.disabled {
  border-color: #e0e0e0;
  color: #bfbfbf;
  cursor: not-allowed;
}

.agreement-row {
  margin-bottom: 16px;
  text-align: left;
}
.agreement-row :deep(.ant-checkbox-wrapper) {
  font-size: 12px;
  color: #666;
  align-items: flex-start;
}
.agreement-row :deep(.ant-checkbox) {
  margin-top: 2px;
}
.agreement-text {
  font-size: 12px;
  color: #666;
  line-height: 1.6;
}
.agreement-link {
  color: #6366f1;
  text-decoration: none;
  font-size: 12px;
}
.agreement-link:hover {
  text-decoration: underline;
}

.submit-btn.ant-btn-primary {
  background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%) !important;
  border: none !important;
  border-radius: 10px !important;
  height: 44px !important;
  font-size: 15px !important;
  font-weight: 600 !important;
  letter-spacing: 0.3px !important;
  box-shadow: 0 4px 16px rgba(99, 102, 241, 0.28) !important;
  transition: all 0.22s !important;
}
.submit-btn.ant-btn-primary:hover:not(:disabled) {
  transform: translateY(-1px) !important;
  box-shadow: 0 8px 24px rgba(99, 102, 241, 0.38) !important;
}

.other-login-options {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid #f0f0f0;
}
.option-text {
  font-size: 12px;
  color: #999;
}
.option-btns {
  margin-top: 8px;
}

/* 弹窗样式 */
.modal-tip {
  font-size: 13px;
  color: #8c8c8c;
  margin-bottom: 16px;
}
.modal-captcha {
  margin-bottom: 16px;
}
.captcha-img-btn {
  width: 120px;
  height: 44px;
  flex-shrink: 0;
  border: 1px solid #ebebeb;
  border-radius: 10px;
  overflow: hidden;
  background: #fafafa;
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.2s;
}
.captcha-img-btn:hover {
  border-color: #6366f1;
}
.captcha-img-btn img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.captcha-placeholder {
  font-size: 12px;
  color: #bfbfbf;
}

/* 账号列表 */
.list-item {
  cursor: pointer;
  transition: background 0.15s;
  padding: 8px 12px;
  border-radius: 8px;
}
.list-item:hover {
  background: #f5f5f5;
}

.invite-success, .invite-error { padding: 20px 0; }
.success-icon { font-size: 64px; color: #52c41a; margin-bottom: 16px; }
.error-icon { font-size: 64px; color: #ff4d4f; margin-bottom: 16px; }
.success-title, .error-title { font-size: 22px; font-weight: 600; color: #1a1a1a; margin-bottom: 8px; }
.success-desc, .error-desc { color: #666; font-size: 14px; margin-bottom: 24px; }
</style>
