<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { computed, onMounted, ref } from 'vue'
import { toast } from 'vue-sonner'

import api from '@/services/api'

interface UserProfile {
  id: number
  username: string
  email: string
  phone: string
  avatar: string
  role: string
  status: string
  api_token: string
  created_at: string
  last_login_at: string
}

interface Subscription {
  plan: string
  status: string
  expire_date: string
  api_quota: number
  api_used: number
  storage_quota: number
  storage_used: number
}

interface Transaction {
  id: number
  type: string
  amount: number
  description: string
  created_at: string
}

const loading = ref(true)
const saving = ref(false)
const changingPassword = ref(false)
const user = ref<UserProfile | null>(null)
const subscription = ref<Subscription | null>(null)
const transactions = ref<Transaction[]>([])

const profileForm = ref({
  username: '',
  email: '',
  phone: '',
})

const passwordForm = ref({
  currentPassword: '',
  newPassword: '',
  confirmPassword: '',
})

const avatarInputRef = ref<HTMLInputElement | null>(null)
const avatarPreview = ref<string | null>(null)
const uploadingAvatar = ref(false)
const showPasswordDialog = ref(false)
const showApiToken = ref(false)
const regeneratingToken = ref(false)

const isProfileFormValid = computed(() => {
  return profileForm.value.username && profileForm.value.email
})

const isPasswordFormValid = computed(() => {
  return passwordForm.value.currentPassword
    && passwordForm.value.newPassword
    && passwordForm.value.confirmPassword
    && passwordForm.value.newPassword === passwordForm.value.confirmPassword
})

const apiUsagePercent = computed(() => {
  if (!subscription.value)
    return 0
  return Math.min((subscription.value.api_used / subscription.value.api_quota) * 100, 100)
})

const storageUsagePercent = computed(() => {
  if (!subscription.value)
    return 0
  return Math.min((subscription.value.storage_used / subscription.value.storage_quota) * 100, 100)
})

async function fetchProfile() {
  loading.value = true
  try {
    const data = await api.get<{ user: UserProfile, subscription: Subscription, transactions: Transaction[] }>('/dev/profile')
    user.value = data?.user || data
    subscription.value = data?.subscription || null
    transactions.value = data?.transactions || []

    if (user.value) {
      profileForm.value = {
        username: user.value.username,
        email: user.value.email || '',
        phone: user.value.phone || '',
      }
      if (user.value.avatar) {
        avatarPreview.value = user.value.avatar
      }
    }
  }
  catch (error) {
    console.error('获取用户信息失败:', error)
    toast.error('获取用户信息失败')
  }
  finally {
    loading.value = false
  }
}

async function handleUpdateProfile() {
  if (!isProfileFormValid.value) {
    toast.error('请填写完整信息')
    return
  }

  saving.value = true
  try {
    await api.put('/dev/profile', {
      username: profileForm.value.username,
      email: profileForm.value.email,
      phone: profileForm.value.phone,
    })
    toast.success('个人信息更新成功')

    if (user.value) {
      user.value.username = profileForm.value.username
      user.value.email = profileForm.value.email
      user.value.phone = profileForm.value.phone
      localStorage.setItem('user', JSON.stringify(user.value))
    }
  }
  catch (error: any) {
    console.error('更新个人信息失败:', error)
    toast.error(error.message || '更新失败')
  }
  finally {
    saving.value = false
  }
}

async function handleChangePassword() {
  if (!passwordForm.value.currentPassword) {
    toast.error('请输入当前密码')
    return
  }
  if (!passwordForm.value.newPassword) {
    toast.error('请输入新密码')
    return
  }
  if (passwordForm.value.newPassword !== passwordForm.value.confirmPassword) {
    toast.error('两次输入的密码不一致')
    return
  }
  if (passwordForm.value.newPassword.length < 6) {
    toast.error('密码长度至少6位')
    return
  }

  changingPassword.value = true
  try {
    await api.put('/dev/profile/password', {
      current_password: passwordForm.value.currentPassword,
      new_password: passwordForm.value.newPassword,
    })
    toast.success('密码修改成功')
    showPasswordDialog.value = false
    passwordForm.value = {
      currentPassword: '',
      newPassword: '',
      confirmPassword: '',
    }
  }
  catch (error: any) {
    console.error('修改密码失败:', error)
    toast.error(error.message || '修改密码失败')
  }
  finally {
    changingPassword.value = false
  }
}

function handleAvatarClick() {
  avatarInputRef.value?.click()
}

async function handleAvatarChange(event: Event) {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]
  if (!file)
    return

  if (!file.type.startsWith('image/')) {
    toast.error('请选择图片文件')
    return
  }

  if (file.size > 2 * 1024 * 1024) {
    toast.error('图片大小不能超过2MB')
    return
  }

  const reader = new FileReader()
  reader.onload = (e) => {
    avatarPreview.value = e.target?.result as string
  }
  reader.readAsDataURL(file)

  uploadingAvatar.value = true
  try {
    const formData = new FormData()
    formData.append('avatar', file)

    const data = await api.postFormData<{ avatar: string }>('/dev/profile/avatar', formData)

    if (data?.avatar) {
      avatarPreview.value = data.avatar
      if (user.value) {
        user.value.avatar = data.avatar
        localStorage.setItem('user', JSON.stringify(user.value))
      }
      toast.success('头像更新成功')
    }
  }
  catch (error: any) {
    console.error('上传头像失败:', error)
    toast.error(error.message || '上传头像失败')
  }
  finally {
    uploadingAvatar.value = false
  }
}

function formatDate(dateStr: string) {
  if (!dateStr)
    return '-'
  return new Date(dateStr).toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  })
}

function formatDateShort(dateStr: string) {
  if (!dateStr)
    return '-'
  return new Date(dateStr).toLocaleDateString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
  })
}

function formatBytes(bytes: number) {
  if (!bytes || bytes === 0)
    return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return `${(bytes / k ** i).toFixed(2)} ${sizes[i]}`
}

function formatNumber(num: number) {
  return (num || 0).toLocaleString()
}

function getRoleName(role: string) {
  const roles: Record<string, string> = {
    admin: '管理员',
    agent: '代理商',
  }
  return roles[role] || role
}

function getStatusName(status: string) {
  const statuses: Record<string, string> = {
    active: '正常',
    inactive: '未激活',
    banned: '已封禁',
  }
  return statuses[status] || status
}

function getTransactionType(type: string) {
  const types: Record<string, string> = {
    recharge: '充值',
    consume: '消费',
    refund: '退款',
  }
  return types[type] || type
}

function getTransactionTypeColor(type: string) {
  const colors: Record<string, string> = {
    recharge: 'text-green-500',
    consume: 'text-red-500',
    refund: 'text-blue-500',
  }
  return colors[type] || 'text-gray-500'
}

async function handleRegenerateApiToken() {
  regeneratingToken.value = true
  try {
    const data = await api.post<{ api_token: string }>('/dev/profile/api-token')
    if (data?.api_token && user.value) {
      user.value.api_token = data.api_token
      toast.success('API Token 已重新生成')
    }
  }
  catch (error: any) {
    console.error('重新生成API Token失败:', error)
    toast.error(error.message || '重新生成失败')
  }
  finally {
    regeneratingToken.value = false
  }
}

function copyApiToken() {
  if (user.value?.api_token) {
    navigator.clipboard.writeText(user.value.api_token)
    toast.success('API Token 已复制到剪贴板')
  }
}

function maskToken(token: string) {
  if (!token || token.length < 16)
    return token
  return `${token.slice(0, 8)}${'•'.repeat(24)}${token.slice(-8)}`
}

onMounted(() => {
  fetchProfile()
})
</script>

<template>
  <div class="min-h-screen bg-background">
    <div class="mx-auto max-w-5xl px-4 sm:px-6 lg:px-8 py-8">
      <div v-if="loading" class="flex items-center justify-center py-20">
        <Icon icon="lucide:loader-2" class="size-10 animate-spin text-muted-foreground" />
      </div>

      <template v-else>
        <div class="relative mb-8">
          <div class="h-32 rounded-xl bg-gradient-to-r from-primary/20 via-primary/10 to-primary/5" />
          <div class="absolute -bottom-12 left-8 flex items-end gap-5">
            <div class="relative">
              <div
                class="size-28 rounded-2xl bg-background border-4 border-background shadow-xl flex items-center justify-center overflow-hidden cursor-pointer group"
                @click="handleAvatarClick"
              >
                <img
                  v-if="avatarPreview"
                  :src="avatarPreview"
                  alt="Avatar"
                  class="size-full object-cover"
                >
                <Icon v-else icon="lucide:user" class="size-12 text-muted-foreground" />
                <div class="absolute inset-0 bg-black/50 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
                  <Icon icon="lucide:camera" class="size-8 text-white" />
                </div>
              </div>
              <div
                v-if="uploadingAvatar"
                class="absolute inset-0 rounded-2xl bg-black/50 flex items-center justify-center"
              >
                <Icon icon="lucide:loader-2" class="size-8 animate-spin text-white" />
              </div>
            </div>
          </div>
          <div class="absolute -bottom-12 right-8 flex items-center gap-2">
            <UiButton variant="outline" size="sm" @click="showPasswordDialog = true">
              <Icon icon="lucide:key" class="mr-2 h-4 w-4" />
              修改密码
            </UiButton>
          </div>
          <input
            ref="avatarInputRef"
            type="file"
            accept="image/*"
            class="hidden"
            @change="handleAvatarChange"
          >
        </div>

        <div class="pt-16 pb-6 px-8">
          <div class="flex items-center gap-3">
            <h1 class="text-2xl font-bold">
              {{ user?.username }}
            </h1>
            <UiBadge :class="user?.status === 'active' ? 'bg-green-500/10 text-green-500 border-green-500/20' : ''" variant="outline">
              {{ getStatusName(user?.status || '') }}
            </UiBadge>
          </div>
          <div class="flex items-center gap-4 mt-2 text-sm text-muted-foreground">
            <span class="flex items-center gap-1">
              <Icon icon="lucide:shield" class="size-4" />
              {{ getRoleName(user?.role || '') }}
            </span>
            <span class="flex items-center gap-1">
              <Icon icon="lucide:mail" class="size-4" />
              {{ user?.email || '-' }}
            </span>
            <span class="flex items-center gap-1">
              <Icon icon="lucide:calendar" class="size-4" />
              加入于 {{ formatDateShort(user?.created_at || '') }}
            </span>
          </div>
        </div>

        <div class="grid gap-6 lg:grid-cols-3">
          <div class="lg:col-span-2 space-y-6">
            <UiCard class="overflow-hidden">
              <div class="bg-muted/30 px-6 py-4 border-b">
                <h2 class="font-semibold flex items-center gap-2">
                  <Icon icon="lucide:user" class="size-5 text-primary" />
                  基本信息
                </h2>
              </div>
              <UiCardContent class="p-6">
                <div class="grid gap-5 sm:grid-cols-2">
                  <div class="space-y-2">
                    <UiLabel for="username" class="text-muted-foreground">
                      用户名
                    </UiLabel>
                    <UiInput
                      id="username"
                      v-model="profileForm.username"
                      placeholder="请输入用户名"
                      class="bg-background"
                    />
                  </div>

                  <div class="space-y-2">
                    <UiLabel for="email" class="text-muted-foreground">
                      邮箱
                    </UiLabel>
                    <UiInput
                      id="email"
                      v-model="profileForm.email"
                      type="email"
                      placeholder="请输入邮箱"
                      class="bg-background"
                    />
                  </div>

                  <div class="space-y-2 sm:col-span-2">
                    <UiLabel for="phone" class="text-muted-foreground">
                      手机号
                    </UiLabel>
                    <UiInput
                      id="phone"
                      v-model="profileForm.phone"
                      type="tel"
                      placeholder="请输入手机号"
                      class="bg-background"
                    />
                  </div>
                </div>

                <div class="flex justify-end mt-6">
                  <UiButton
                    :disabled="saving || !isProfileFormValid"
                    @click="handleUpdateProfile"
                  >
                    <Icon v-if="saving" icon="lucide:loader-2" class="mr-2 h-4 w-4 animate-spin" />
                    <Icon v-else icon="lucide:save" class="mr-2 h-4 w-4" />
                    保存修改
                  </UiButton>
                </div>
              </UiCardContent>
            </UiCard>

            <UiCard class="overflow-hidden">
              <div class="bg-muted/30 px-6 py-4 border-b">
                <h2 class="font-semibold flex items-center gap-2">
                  <Icon icon="lucide:key" class="size-5 text-primary" />
                  API Token
                </h2>
              </div>
              <UiCardContent class="p-6">
                <div class="space-y-4">
                  <p class="text-sm text-muted-foreground">
                    API Token 用于调用开放 API 接口，请妥善保管，不要泄露给他人。
                  </p>
                  <div class="flex items-center gap-2">
                    <code class="flex-1 p-3 bg-muted rounded-lg text-sm font-mono break-all border">
                      {{ showApiToken ? user?.api_token : maskToken(user?.api_token || '') }}
                    </code>
                    <UiTooltipProvider>
                      <UiTooltip>
                        <UiTooltipTrigger as-child>
                          <UiButton
                            variant="outline"
                            size="icon"
                            @click="showApiToken = !showApiToken"
                          >
                            <Icon :icon="showApiToken ? 'lucide:eye-off' : 'lucide:eye'" class="size-4" />
                          </UiButton>
                        </UiTooltipTrigger>
                        <UiTooltipContent>
                          {{ showApiToken ? '隐藏' : '显示' }}
                        </UiTooltipContent>
                      </UiTooltip>
                    </UiTooltipProvider>
                    <UiTooltipProvider>
                      <UiTooltip>
                        <UiTooltipTrigger as-child>
                          <UiButton
                            variant="outline"
                            size="icon"
                            :disabled="!user?.api_token"
                            @click="copyApiToken"
                          >
                            <Icon icon="lucide:copy" class="size-4" />
                          </UiButton>
                        </UiTooltipTrigger>
                        <UiTooltipContent>
                          复制
                        </UiTooltipContent>
                      </UiTooltip>
                    </UiTooltipProvider>
                  </div>
                  <div class="flex justify-end">
                    <UiButton
                      variant="outline"
                      :disabled="regeneratingToken"
                      @click="handleRegenerateApiToken"
                    >
                      <Icon v-if="regeneratingToken" icon="lucide:loader-2" class="mr-2 h-4 w-4 animate-spin" />
                      <Icon v-else icon="lucide:refresh-cw" class="mr-2 h-4 w-4" />
                      {{ user?.api_token ? '重新生成' : '生成 Token' }}
                    </UiButton>
                  </div>
                </div>
              </UiCardContent>
            </UiCard>

            <UiCard class="overflow-hidden">
              <div class="bg-muted/30 px-6 py-4 border-b flex items-center justify-between">
                <h2 class="font-semibold flex items-center gap-2">
                  <Icon icon="lucide:receipt" class="size-5 text-primary" />
                  最近交易
                </h2>
                <UiButton variant="ghost" size="sm" as-child>
                  <router-link to="/admin/finance" class="text-primary">
                    查看全部
                    <Icon icon="lucide:arrow-right" class="ml-1 h-4 w-4" />
                  </router-link>
                </UiButton>
              </div>
              <UiCardContent class="p-0">
                <div v-if="transactions.length > 0">
                  <div
                    v-for="(tx, index) in transactions.slice(0, 5)"
                    :key="tx.id"
                    class="flex items-center justify-between px-6 py-4 hover:bg-muted/30 transition-colors"
                    :class="{ 'border-t': index > 0 }"
                  >
                    <div class="flex items-center gap-4">
                      <div
                        class="size-10 rounded-xl flex items-center justify-center"
                        :class="tx.type === 'recharge' ? 'bg-green-500/10' : tx.type === 'refund' ? 'bg-blue-500/10' : 'bg-red-500/10'"
                      >
                        <Icon
                          :icon="tx.type === 'recharge' ? 'lucide:arrow-down-left' : tx.type === 'refund' ? 'lucide:rotate-ccw' : 'lucide:arrow-up-right'"
                          :class="getTransactionTypeColor(tx.type)"
                          class="size-5"
                        />
                      </div>
                      <div>
                        <p class="font-medium">
                          {{ tx.description || getTransactionType(tx.type) }}
                        </p>
                        <p class="text-xs text-muted-foreground mt-0.5">
                          {{ formatDate(tx.created_at) }}
                        </p>
                      </div>
                    </div>
                    <span :class="getTransactionTypeColor(tx.type)" class="font-semibold text-lg">
                      {{ tx.type === 'recharge' || tx.type === 'refund' ? '+' : '-' }}¥{{ tx.amount.toFixed(2) }}
                    </span>
                  </div>
                </div>
                <div v-else class="text-center py-12 text-muted-foreground">
                  <Icon icon="lucide:receipt" class="size-16 mx-auto mb-3 opacity-30" />
                  <p>暂无交易记录</p>
                </div>
              </UiCardContent>
            </UiCard>
          </div>

          <div class="space-y-6">
            <UiCard class="overflow-hidden">
              <div class="bg-gradient-to-br from-primary/10 to-primary/5 px-6 py-5">
                <div class="flex items-center justify-between">
                  <div>
                    <p class="text-sm text-muted-foreground">
                      当前套餐
                    </p>
                    <p class="text-2xl font-bold mt-1">
                      {{ subscription?.plan || '基础版' }}
                    </p>
                  </div>
                  <div class="size-12 rounded-xl bg-primary/10 flex items-center justify-center">
                    <Icon icon="lucide:crown" class="size-6 text-primary" />
                  </div>
                </div>
                <p class="text-sm text-muted-foreground mt-2">
                  有效期至 {{ formatDateShort(subscription?.expire_date || '') }}
                </p>
                <UiButton class="w-full mt-4" as-child>
                  <router-link to="/billing">
                    升级套餐
                  </router-link>
                </UiButton>
              </div>
              <UiCardContent class="p-6 space-y-5">
                <div class="space-y-2">
                  <div class="flex justify-between text-sm">
                    <span class="text-muted-foreground flex items-center gap-1">
                      <Icon icon="lucide:zap" class="size-4" />
                      API 调用
                    </span>
                    <span class="font-medium">{{ formatNumber(subscription?.api_used || 0) }} / {{ formatNumber(subscription?.api_quota || 10000) }}</span>
                  </div>
                  <div class="w-full bg-muted rounded-full h-2 overflow-hidden">
                    <div
                      class="h-2 rounded-full transition-all"
                      :class="apiUsagePercent > 80 ? 'bg-amber-500' : 'bg-primary'"
                      :style="{ width: `${apiUsagePercent}%` }"
                    />
                  </div>
                </div>

                <div class="space-y-2">
                  <div class="flex justify-between text-sm">
                    <span class="text-muted-foreground flex items-center gap-1">
                      <Icon icon="lucide:hard-drive" class="size-4" />
                      存储空间
                    </span>
                    <span class="font-medium">{{ formatBytes(subscription?.storage_used || 0) }} / {{ formatBytes(subscription?.storage_quota || 100 * 1024 * 1024) }}</span>
                  </div>
                  <div class="w-full bg-muted rounded-full h-2 overflow-hidden">
                    <div
                      class="h-2 rounded-full transition-all"
                      :class="storageUsagePercent > 80 ? 'bg-amber-500' : 'bg-primary'"
                      :style="{ width: `${storageUsagePercent}%` }"
                    />
                  </div>
                </div>
              </UiCardContent>
            </UiCard>

            <UiCard class="overflow-hidden">
              <div class="bg-muted/30 px-6 py-4 border-b">
                <h2 class="font-semibold flex items-center gap-2">
                  <Icon icon="lucide:activity" class="size-5 text-primary" />
                  账户统计
                </h2>
              </div>
              <UiCardContent class="p-6">
                <div class="space-y-4">
                  <div class="flex items-center justify-between py-2">
                    <span class="text-muted-foreground text-sm">上次登录</span>
                    <span class="text-sm font-medium">{{ formatDate(user?.last_login_at || '') }}</span>
                  </div>
                  <div class="flex items-center justify-between py-2 border-t">
                    <span class="text-muted-foreground text-sm">账户状态</span>
                    <UiBadge :class="user?.status === 'active' ? 'bg-green-500/10 text-green-500' : ''" variant="outline">
                      {{ getStatusName(user?.status || '') }}
                    </UiBadge>
                  </div>
                  <div class="flex items-center justify-between py-2 border-t">
                    <span class="text-muted-foreground text-sm">账户类型</span>
                    <UiBadge variant="outline">
                      {{ getRoleName(user?.role || '') }}
                    </UiBadge>
                  </div>
                </div>
              </UiCardContent>
            </UiCard>
          </div>
        </div>
      </template>
    </div>

    <UiDialog v-model:open="showPasswordDialog">
      <UiDialogContent class="sm:max-w-md">
        <UiDialogHeader>
          <UiDialogTitle>修改密码</UiDialogTitle>
          <UiDialogDescription>
            请输入当前密码和新密码，密码长度至少6位
          </UiDialogDescription>
        </UiDialogHeader>
        <div class="space-y-4 py-4">
          <div class="space-y-2">
            <UiLabel for="currentPassword">
              当前密码
            </UiLabel>
            <UiInput
              id="currentPassword"
              v-model="passwordForm.currentPassword"
              type="password"
              placeholder="请输入当前密码"
            />
          </div>
          <div class="space-y-2">
            <UiLabel for="newPassword">
              新密码
            </UiLabel>
            <UiInput
              id="newPassword"
              v-model="passwordForm.newPassword"
              type="password"
              placeholder="请输入新密码"
            />
          </div>
          <div class="space-y-2">
            <UiLabel for="confirmPassword">
              确认密码
            </UiLabel>
            <UiInput
              id="confirmPassword"
              v-model="passwordForm.confirmPassword"
              type="password"
              placeholder="请再次输入新密码"
            />
          </div>
        </div>
        <UiDialogFooter>
          <UiButton variant="outline" @click="showPasswordDialog = false">
            取消
          </UiButton>
          <UiButton
            :disabled="changingPassword || !isPasswordFormValid"
            @click="handleChangePassword"
          >
            <Icon v-if="changingPassword" icon="lucide:loader-2" class="mr-2 h-4 w-4 animate-spin" />
            确认修改
          </UiButton>
        </UiDialogFooter>
      </UiDialogContent>
    </UiDialog>
  </div>
</template>