<template>
  <view class="mine-page" :style="{ background: themeConfig.bgColor }">
    <view class="page-content">
      <view class="section-header">
        <view class="section-title-row">
          <view class="section-accent" :style="{ background: themeConfig.gradientSoft }"></view>
          <text class="section-title" :style="{ color: themeConfig.textPrimary }">个人资料</text>
          <text class="section-subtitle" :style="{ color: themeConfig.textSecondary }">点击头像可编辑</text>
        </view>
      </view>

      <view class="profile-card" :style="{ background: themeConfig.cardBgColor, boxShadow: `0 8rpx 24rpx ${themeConfig.shadowLight}`, borderColor: themeConfig.borderLight }">
        <view class="profile-row">
          <view class="avatar-wrapper" @click="openProfileEditor">
            <image v-if="userAvatar" class="avatar-img" :src="userAvatar" mode="aspectFill"></image>
            <view v-else class="avatar-placeholder" :style="{ background: themeConfig.gradientSoft }">
              <text class="avatar-init">{{ (userName || '我')[0] }}</text>
            </view>
          </view>
          <view class="profile-info">
            <view class="profile-info-top">
              <text class="user-name" :style="{ color: themeConfig.textPrimary }">{{ userName || '点击设置昵称' }}</text>
              <view class="level-badge" :style="{ background: themeConfig.primaryColor + '15' }">
                <text class="level-text" :style="{ color: themeConfig.primaryColor }" @click="goToGrowth">Lv.{{ growthInfo.level }}</text>
              </view>
            </view>
            <view class="user-stats-row">
              <view class="user-stat">
                <text class="stat-num" :style="{ color: themeConfig.textPrimary }">{{ dayCount }}</text>
                <text class="stat-label" :style="{ color: themeConfig.textSecondary }">天数</text>
              </view>
              <view class="user-stat-divider" :style="{ background: themeConfig.borderColor }"></view>
              <view class="user-stat">
                <text class="stat-num" :style="{ color: themeConfig.textPrimary }">{{ growthInfo.streakDays || 0 }}</text>
                <text class="stat-label" :style="{ color: themeConfig.textSecondary }">连续</text>
              </view>
              <view class="user-stat-divider" :style="{ background: themeConfig.borderColor }"></view>
              <view class="user-stat">
                <text class="stat-num" :style="{ color: themeConfig.textPrimary }">{{ growthInfo.achievements.unlocked || 0 }}</text>
                <text class="stat-label" :style="{ color: themeConfig.textSecondary }">成就</text>
              </view>
            </view>
            <text class="user-signature" v-if="userSignature" :style="{ color: themeConfig.textSecondary }">{{ userSignature }}</text>
          </view>
        </view>
      </view>

      <view class="section-header">
        <view class="section-title-row">
          <view class="section-accent" :style="{ background: themeConfig.gradientSoft }"></view>
          <text class="section-title" :style="{ color: themeConfig.textPrimary }">本月数据</text>
          <text class="section-subtitle" :style="{ color: themeConfig.textSecondary }">收支与完成度</text>
        </view>
      </view>

      <view class="exp-card" :style="{ background: themeConfig.cardBgColor, boxShadow: `0 8rpx 24rpx ${themeConfig.shadowLight}`, borderColor: themeConfig.borderLight }">
        <view class="exp-header">
          <text class="exp-label" :style="{ color: themeConfig.textPrimary }">升级进度</text>
          <text class="exp-text" :style="{ color: themeConfig.textSecondary }">{{ growthInfo.experience }}/{{ growthInfo.nextLevelExp }} EXP</text>
        </view>
        <view class="exp-progress-bar">
          <view class="exp-progress-fill" :style="{ width: expPercent + '%', background: themeConfig.gradientSoft }"></view>
        </view>
      </view>

      <view class="stats-row">
        <view class="stat-card" :style="{ background: themeConfig.cardBgColor, boxShadow: `0 6rpx 20rpx ${themeConfig.shadowLight}`, borderColor: themeConfig.borderLight }">
          <view class="stat-icon-wrap" :style="{ background: themeConfig.dangerColor + '15' }">
            <FaIcon icon="wallet" :size="22" :color="themeConfig.dangerColor" />
          </view>
          <view class="stat-info">
            <text class="stat-val" :style="{ color: themeConfig.textPrimary }">¥{{ formatNumber(totalAmount) }}</text>
            <text class="stat-lbl" :style="{ color: themeConfig.textSecondary }">净收支</text>
          </view>
        </view>
        <view class="stat-card" :style="{ background: themeConfig.cardBgColor, boxShadow: `0 6rpx 20rpx ${themeConfig.shadowLight}`, borderColor: themeConfig.borderLight }">
          <view class="stat-icon-wrap" :style="{ background: themeConfig.primaryColor + '15' }">
            <FaIcon icon="check-circle" :size="22" :color="themeConfig.primaryColor" />
          </view>
          <view class="stat-info">
            <text class="stat-val" :style="{ color: themeConfig.textPrimary }">{{ finishRate }}%</text>
            <text class="stat-lbl" :style="{ color: themeConfig.textSecondary }">完成率</text>
          </view>
        </view>
        <view class="stat-card" :style="{ background: themeConfig.cardBgColor, boxShadow: `0 6rpx 20rpx ${themeConfig.shadowLight}`, borderColor: themeConfig.borderLight }">
          <view class="stat-icon-wrap" :style="{ background: themeConfig.secondaryColor + '15' }">
            <FaIcon icon="calendar" :size="22" :color="themeConfig.secondaryColor" />
          </view>
          <view class="stat-info">
            <text class="stat-val" :style="{ color: themeConfig.textPrimary }">{{ monthBudget > 0 ? '¥' + formatNumber(monthBudget) : '未设' }}</text>
            <text class="stat-lbl" :style="{ color: themeConfig.textSecondary }">月预算</text>
          </view>
        </view>
      </view>

      <view class="section-header">
        <view class="section-title-row">
          <view class="section-accent" :style="{ background: themeConfig.gradientSoft }"></view>
          <text class="section-title" :style="{ color: themeConfig.textPrimary }">更多功能</text>
          <text class="section-subtitle" :style="{ color: themeConfig.textSecondary }">设置与账户</text>
        </view>
      </view>

      <view class="menu-card" :style="{ background: themeConfig.cardBgColor, boxShadow: `0 8rpx 24rpx ${themeConfig.shadowLight}`, borderColor: themeConfig.borderLight }">
        <view class="menu-item" @click="goToGrowth">
          <view class="menu-icon" :style="{ background: themeConfig.primaryColor + '15' }">
            <FaIcon icon="trophy" :size="22" :color="themeConfig.primaryColor" />
          </view>
          <text class="menu-title" :style="{ color: themeConfig.textPrimary }">成长中心</text>
          <text class="menu-arrow" :style="{ color: themeConfig.textDisabled }">
            <FaIcon icon="chevron-right" :size="18" :color="themeConfig.textDisabled" />
          </text>
        </view>
        <view class="menu-divider" :style="{ background: themeConfig.borderColor }"></view>
        <view class="menu-item" @click="handleBudgetSetting">
          <view class="menu-icon" :style="{ background: themeConfig.secondaryColor + '15' }">
            <FaIcon icon="wallet" :size="22" :color="themeConfig.secondaryColor" />
          </view>
          <text class="menu-title" :style="{ color: themeConfig.textPrimary }">月度预算</text>
          <text class="menu-arrow" :style="{ color: themeConfig.textDisabled }">
            <FaIcon icon="chevron-right" :size="18" :color="themeConfig.textDisabled" />
          </text>
        </view>
        <view class="menu-divider" :style="{ background: themeConfig.borderColor }"></view>
        <view class="menu-item" @click="handleThemeSetting">
          <view class="menu-icon" :style="{ background: themeConfig.primaryColor + '15' }">
            <FaIcon icon="palette" :size="22" :color="themeConfig.primaryColor" />
          </view>
          <text class="menu-title" :style="{ color: themeConfig.textPrimary }">主题皮肤</text>
          <text class="menu-desc" :style="{ color: themeConfig.textSecondary }">{{ themeConfig.name || '默认' }}</text>
          <text class="menu-arrow" :style="{ color: themeConfig.textDisabled }">
            <FaIcon icon="chevron-right" :size="18" :color="themeConfig.textDisabled" />
          </text>
        </view>
        <view class="menu-divider" :style="{ background: themeConfig.borderColor }"></view>
        <view class="menu-item" @click="handleEmailSetting">
          <view class="menu-icon" :style="{ background: (themeConfig.warningColor || '#ffaa33') + '20' }">
            <FaIcon icon="envelope" :size="22" :color="themeConfig.warningColor || '#ffaa33'" />
          </view>
          <text class="menu-title" :style="{ color: themeConfig.textPrimary }">绑定邮箱</text>
          <text class="menu-desc" :style="{ color: userEmail ? themeConfig.textSecondary : themeConfig.textDisabled }">{{ userEmail || '未绑定' }}</text>
          <text class="menu-arrow" :style="{ color: themeConfig.textDisabled }">
            <FaIcon icon="chevron-right" :size="18" :color="themeConfig.textDisabled" />
          </text>
        </view>
        <view class="menu-divider" :style="{ background: themeConfig.borderColor }"></view>
        <view class="menu-item" :class="{ 'menu-item--disabled': isBindWechat }" @click="handleWechatBind">
          <view class="menu-icon" :style="{ background: themeConfig.secondaryColor + '15' }">
            <FaIcon icon="comment" :size="22" :color="themeConfig.secondaryColor" />
          </view>
          <text class="menu-title" :style="{ color: themeConfig.textPrimary }">绑定微信</text>
          <text class="menu-desc" :style="{ color: isBindWechat ? themeConfig.primaryColor : themeConfig.textDisabled }">{{ isBindWechat ? '已绑定' : '未绑定' }}</text>
          <text v-if="!isBindWechat" class="menu-arrow" :style="{ color: themeConfig.textDisabled }">
            <FaIcon icon="chevron-right" :size="18" :color="themeConfig.textDisabled" />
          </text>
        </view>
        <view class="menu-divider" :style="{ background: themeConfig.borderColor }"></view>
        <view class="menu-item" @click="handleAbout">
          <view class="menu-icon" :style="{ background: themeConfig.textSecondary + '15' }">
            <FaIcon icon="circle-info" :size="22" :color="themeConfig.textSecondary" />
          </view>
          <text class="menu-title" :style="{ color: themeConfig.textPrimary }">关于我们</text>
          <text class="menu-desc" :style="{ color: themeConfig.textSecondary }">v{{ version }}</text>
          <text class="menu-arrow" :style="{ color: themeConfig.textDisabled }">
            <FaIcon icon="chevron-right" :size="18" :color="themeConfig.textDisabled" />
          </text>
        </view>
      </view>
    </view>

    <view class="safe-area-bottom"></view>

    <view class="modal" v-if="showBudgetModal" @click="showBudgetModal = false">
      <view class="modal-box" :style="{ background: themeConfig.cardBgColor }" @click.stop>
        <view class="modal-header">
          <text class="modal-title" :style="{ color: themeConfig.textPrimary }">设置月度预算</text>
          <view class="modal-close" @click="showBudgetModal = false">
            <FaIcon icon="xmark" :size="20" :color="themeConfig.textSecondary" />
          </view>
        </view>
        <view class="modal-form">
          <text class="form-label" :style="{ color: themeConfig.textPrimary }">预算金额（元）</text>
          <input v-model="tempBudget" type="digit" placeholder="请输入月度预算"
            class="form-input"
            :style="{ backgroundColor: themeConfig.bgColor, color: themeConfig.textPrimary, borderColor: themeConfig.borderColor }" />
        </view>
        <view class="modal-actions">
          <view class="modal-btn cancel-btn btn btn--secondary" @click="showBudgetModal = false">取消</view>
          <view class="modal-btn confirm-btn btn btn--primary" @click="saveBudget">确定</view>
        </view>
      </view>
    </view>

    <view class="modal" v-if="showProfileModal" @click="showProfileModal = false">
      <view class="modal-box" :style="{ background: themeConfig.cardBgColor }" @click.stop>
        <view class="modal-header">
          <text class="modal-title" :style="{ color: themeConfig.textPrimary }">编辑资料</text>
          <view class="modal-close" @click="showProfileModal = false">
            <FaIcon icon="xmark" :size="20" :color="themeConfig.textSecondary" />
          </view>
        </view>
        <view class="profile-modal-content">
          <view class="profile-section">
            <view class="avatar-preview-wrapper" @click="showAvatarPicker = !showAvatarPicker">
              <view class="profile-avatar-frame" :style="{ borderColor: themeConfig.primaryColor }">
                <image class="profile-avatar" :src="profileForm.avatar || userAvatar" mode="aspectFill" />
              </view>
              <view class="avatar-edit-badge" :style="{ background: themeConfig.primaryColor }">
                <FaIcon icon="pen" :size="14" color="#fff" />
              </view>
            </view>
            <view class="avatar-picker" v-if="showAvatarPicker">
              <view class="avatar-grid">
                <view class="avatar-option" :class="{ 'is-selected': profileForm.avatar === avatar }"
                  v-for="(avatar, index) in validAvatars" :key="index"
                  @click="selectAvatarForProfile(avatar)">
                  <view class="avatar-frame"
                    :style="{ borderColor: profileForm.avatar === avatar ? themeConfig.primaryColor : themeConfig.borderColor }">
                    <image class="option-avatar" :src="avatar" mode="aspectFill"></image>
                  </view>
                </view>
              </view>
            </view>
          </view>
          <view class="profile-section">
            <text class="form-label" :style="{ color: themeConfig.textPrimary }">昵称</text>
            <input v-model="profileForm.nickname" placeholder="请输入昵称"
              class="form-input" :maxlength="10"
              :style="{ backgroundColor: themeConfig.bgColor, color: themeConfig.textPrimary, borderColor: themeConfig.borderColor }" />
          </view>
          <view class="profile-section">
            <text class="form-label" :style="{ color: themeConfig.textPrimary }">个性签名</text>
            <input v-model="profileForm.signature" placeholder="请输入个性签名"
              class="form-input" :maxlength="20"
              :style="{ backgroundColor: themeConfig.bgColor, color: themeConfig.textPrimary, borderColor: themeConfig.borderColor }" />
          </view>
          <view class="modal-actions">
            <view class="modal-btn cancel-btn btn btn--secondary" @click="showProfileModal = false">取消</view>
            <view class="modal-btn confirm-btn btn btn--primary" @click="saveProfile">保存</view>
          </view>
        </view>
      </view>
    </view>

    <view class="modal" v-if="showEmailModal" @click="showEmailModal = false">
      <view class="modal-box" :style="{ background: themeConfig.cardBgColor }" @click.stop>
        <view class="modal-header">
          <text class="modal-title" :style="{ color: themeConfig.textPrimary }">{{ userEmail ? '邮箱设置' : '绑定邮箱' }}</text>
          <view class="modal-close" @click="showEmailModal = false">
            <FaIcon icon="xmark" :size="20" :color="themeConfig.textSecondary" />
          </view>
        </view>
        <view class="email-modal-content">
          <view class="email-form">
            <view class="form-item">
              <text class="form-label" :style="{ color: themeConfig.textPrimary }">邮箱地址</text>
              <input v-model="emailForm.email" type="email" placeholder="请输入邮箱地址"
                class="form-input"
                :style="{ backgroundColor: themeConfig.bgColor, color: themeConfig.textPrimary, borderColor: themeConfig.borderColor }"
                :disabled="userEmail && !isEditingEmail" />
            </view>

            <view v-if="userEmail && !isEditingEmail && !showChangePassword" class="form-item">
              <view class="change-password-btn btn btn--primary" @click="showChangePassword = true">
                <text class="btn-text" style="color:#fff;">修改密码</text>
              </view>
              <view class="change-password-btn secondary btn btn--secondary" @click="handleEditEmail">
                <text class="btn-text" :style="{ color: themeConfig.textPrimary }">修改邮箱</text>
              </view>
            </view>

            <view v-if="!userEmail || showChangePassword || isEditingEmail" class="form-item">
              <view v-if="userEmail && showChangePassword && !isEditingEmail" class="form-item">
                <view class="change-password-btn cancel-change btn btn--secondary" @click="cancelChangePassword">
                  <text class="btn-text" :style="{ color: themeConfig.textPrimary }">收起密码修改</text>
                </view>
              </view>
              <view class="form-item">
                <text class="form-label" :style="{ color: themeConfig.textPrimary }">密码</text>
                <view class="password-input-wrapper">
                  <input v-model="emailForm.password" type="password" :password="!showEmailPassword1" placeholder="请输入密码"
                    class="form-input password-input"
                    :style="{ backgroundColor: themeConfig.bgColor, color: themeConfig.textPrimary, borderColor: themeConfig.borderColor }" />
                  <text class="password-toggle-btn" @tap="showEmailPassword1 = !showEmailPassword1">
                    <FaIcon :icon="showEmailPassword1 ? 'eye-slash' : 'eye'" :size="20" :color="themeConfig.textSecondary" />
                  </text>
                </view>
              </view>
              <view class="form-item">
                <text class="form-label" :style="{ color: themeConfig.textPrimary }">确认密码</text>
                <view class="password-input-wrapper">
                  <input v-model="emailForm.confirmPassword" type="password" :password="!showEmailPassword2" placeholder="请再次输入密码"
                    class="form-input password-input"
                    :style="{ backgroundColor: themeConfig.bgColor, color: themeConfig.textPrimary, borderColor: themeConfig.borderColor }" />
                  <text class="password-toggle-btn" @tap="showEmailPassword2 = !showEmailPassword2">
                    <FaIcon :icon="showEmailPassword2 ? 'eye-slash' : 'eye'" :size="20" :color="themeConfig.textSecondary" />
                  </text>
                </view>
              </view>
              <view class="form-item">
                <text class="form-label" :style="{ color: themeConfig.textPrimary }">图形验证码</text>
                <view class="captcha-row">
                  <input v-model="emailForm.captcha" type="text" placeholder="请输入验证码" maxlength="4"
                    class="form-input captcha-input"
                    :style="{ backgroundColor: themeConfig.bgColor, color: themeConfig.textPrimary, borderColor: themeConfig.borderColor }" />
                  <view class="captcha-img" @click="refreshCaptcha">
                    <image :src="captchaImage" mode="aspectFill" class="captcha-image" />
                  </view>
                </view>
              </view>
              <view v-if="emailForm.email !== userEmail" class="form-item">
                <text class="form-label" :style="{ color: themeConfig.textPrimary }">邮箱验证码</text>
                <view class="code-row">
                  <input v-model="emailForm.emailCode" type="digit" placeholder="请输入邮箱验证码"
                    class="form-input code-input"
                    :style="{ backgroundColor: themeConfig.bgColor, color: themeConfig.textPrimary, borderColor: themeConfig.borderColor }" />
                  <view class="send-code-btn btn btn--primary btn--sm" :class="{ disabled: emailCodeCountdown > 0 }" @click="sendEmailCode">
                    {{ emailCodeCountdown > 0 ? emailCodeCountdown + 's' : '发送验证码' }}
                  </view>
                </view>
              </view>
              <view v-if="emailForm.password && emailForm.confirmPassword && emailForm.password !== emailForm.confirmPassword" class="form-error">两次密码不一致</view>
            </view>
          </view>
          <view class="modal-actions" v-if="!userEmail || showChangePassword || isEditingEmail">
            <view class="modal-btn cancel-btn btn btn--secondary" @click="showEmailModal = false">取消</view>
            <view class="modal-btn confirm-btn btn btn--primary" @click="submitEmail">确定</view>
          </view>
          <view class="modal-actions" v-else>
            <view class="modal-btn confirm-btn full-width btn btn--primary" @click="showEmailModal = false">关闭</view>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
  import {
    getThemeConfigFromStorage,
    THEME_PRESETS
  } from '@/utils/theme'
  import {
    refreshNavBarTheme,
    forceApplyTabBarTheme
  } from '@/utils/themeGlobal'
  import {
    DEFAULT_AVATARS,
    MINE_MENU_ICONS
  } from '@/utils/constants.js'
  import {
    getUserInfo,
    editUserInfo,
    getMonthStat,
    getMonthBudget,
    setMonthBudget,
    getGrowthInfo,
    sendEmailCode,
    setUserEmail,
    bindWechat,
    getCaptcha,
    changePassword
  } from '@/api/index'
  import FaIcon from '@/components/FaIcon.vue'

  export default {
    components: {
      FaIcon
    },
    data() {
      return {
        version: '1.0.0',
        monthIncome: 0,
        monthExpend: 0,
        totalAmount: 0,
        finishTaskCount: 0,
        unfinishTaskCount: 0,
        finishRate: 0,
        monthBudget: 0,
        tempBudget: '',
        showBudgetModal: false,
        DEFAULT_AVATARS: DEFAULT_AVATARS,
        MINE_MENU_ICONS: MINE_MENU_ICONS,
        userName: '',
        userAvatar: '',
        userEmail: '',
        userCode: '',
        isBindWechat: false,
        isBindEmail: false,
        currentMonth: new Date().getMonth() + 1,
        themeConfig: getThemeConfigFromStorage() || THEME_PRESETS['default'],
        dayCount: 0,
        joinDate: '2026-01-01',
        userSignature: '',
        showProfileModal: false,
        showAvatarPicker: false,
        showEmailModal: false,
        showChangePassword: false,
        isEditingEmail: false,
        emailForm: {
          email: '',
          password: '',
          confirmPassword: '',
          captcha: '',
          captchaId: '',
          emailCode: ''
        },
        showPassword: false,
        showConfirmPassword: false,
        showEmailPassword: false,
        showEmailPassword1: false,
        showEmailPassword2: false,
        codeCountdown: 0,
        emailCodeCountdown: 0,
        captchaImage: '',
        profileForm: {
          nickname: '',
          signature: '',
          avatar: ''
        },
        growthInfo: {
          level: 1,
          title: '初出茅庐',
          titleIcon: '',
          experience: 0,
          nextLevelExp: 100,
          totalDays: 0,
          streakDays: 0,
          maxStreakDays: 0,
          avgCompletionRate: 0,
          todayProgress: {
            tasksCompleted: 0,
            taskExp: 0,
            billsRecorded: 0,
            billExp: 0,
            moodRecorded: false,
            moodExp: 0,
            streakBonus: 0,
            protectBonus: 0,
            totalExp: 0,
            maxDailyExp: 120
          },
          achievements: [],
          privileges: []
        }
      }
    },
    computed: {
      validAvatars() {
        return this.DEFAULT_AVATARS.filter((avatar) => !!avatar && avatar.trim() !== '')
      },
      expPercent() {
        if (!this.growthInfo.nextLevelExp || this.growthInfo.nextLevelExp <= 0) return 0
        return Math.min(100, Math.round((this.growthInfo.experience / this.growthInfo.nextLevelExp) * 100))
      }
    },
    onLoad() {
      this.themeChangeHandler = (themeData) => {
        try {
          let newTheme = null
          if (themeData?.key && THEME_PRESETS[themeData.key]) {
            newTheme = THEME_PRESETS[themeData.key]
          } else if (themeData?.config) {
            newTheme = themeData.config
          }
          if (newTheme) {
            this.themeConfig = newTheme
          }
        } catch (e) {
          console.error('主题更新失败:', e)
        }
      }
      uni.$on('themeChanged', this.themeChangeHandler)
      this.loadUserInfo()
      this.calculateDayCount()
      this.initData()
      this.loadGrowthInfo()
    },
    onUnload() {
      uni.$off('themeChanged', this.themeChangeHandler)
    },
    onShow() {
      const latestTheme = getThemeConfigFromStorage() || THEME_PRESETS['default']
      if (JSON.stringify(latestTheme) !== JSON.stringify(this.themeConfig)) {
        this.themeConfig = latestTheme
      }
      refreshNavBarTheme()
      setTimeout(() => {
        forceApplyTabBarTheme(latestTheme)
      }, 100)
      this.loadGrowthInfo()
      this.loadUserInfo()
      this.initData()
    },
    methods: {
      async loadGrowthInfo() {
        try {
          const res = await getGrowthInfo()
          if (res) {
            this.growthInfo = {
              level: res.level || 1,
              title: res.title || '',
              titleIcon: res.titleIcon || '',
              experience: res.experience || 0,
              nextLevelExp: res.nextLevelExp || 100,
              totalDays: res.totalDays || 0,
              streakDays: res.streakDays || 0,
              maxStreakDays: res.maxStreakDays || 0,
              avgCompletionRate: res.avgCompletionRate || 0,
              todayProgress: {
                tasksCompleted: res.todayProgress?.tasksCompleted || 0,
                taskExp: res.todayProgress?.taskExp || 0,
                billsRecorded: res.todayProgress?.billsRecorded || 0,
                billExp: res.todayProgress?.billExp || 0,
                moodRecorded: res.todayProgress?.moodRecorded || false,
                moodExp: res.todayProgress?.moodExp || 0,
                streakBonus: res.todayProgress?.streakBonus || 0,
                protectBonus: res.todayProgress?.protectBonus || 0,
                totalExp: res.todayProgress?.totalExp || 0,
                maxDailyExp: res.todayProgress?.maxDailyExp || 120
              },
              achievements: res.achievements || [],
              privileges: res.privileges || []
            }
          }
        } catch (e) {
          console.log('加载成长信息失败:', e)
        }
      },
      goToGrowth() {
        uni.navigateTo({ url: '/pages/growth/growth' })
      },
      formatNumber(num) {
        if (num === null || num === undefined || isNaN(num) || num === '') return '0'
        const number = Number(num)
        const formatted = number.toFixed(2)
        return formatted.replace(/\.00$/, '')
      },
      async loadUserInfo() {
        try {
          const token = uni.getStorageSync('user_token')
          if (!token) return
          const res = await getUserInfo()
          this.userName = res.nickname || ''
          this.userAvatar = res.avatar || this.validAvatars[0] || ''
          this.userSignature = res.signature || ''
          this.userEmail = res.email || ''
          this.userCode = res.user_code || ''
          this.isBindWechat = res.is_bind_wechat || false
          this.isBindEmail = res.is_bind_email || false
          uni.setStorageSync('userName', this.userName)
          uni.setStorageSync('userAvatar', this.userAvatar)
          uni.setStorageSync('userSignature', this.userSignature)
          uni.setStorageSync('userEmail', this.userEmail)
          uni.setStorageSync('userCode', this.userCode)
        } catch (e) {
          console.error('加载用户信息失败:', e)
        }
      },
      calculateDayCount() {
        const joinDate = new Date(this.joinDate)
        const today = new Date()
        const diffTime = today.getTime() - joinDate.getTime()
        const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))
        this.dayCount = Math.max(0, diffDays)
      },
      async copyUserCode() {
        if (!this.userCode) return
        try {
          await uni.setClipboardData({ data: this.userCode })
          uni.showToast({ title: '复制成功', icon: 'success' })
        } catch (e) {
          uni.showToast({ title: '复制失败', icon: 'none' })
        }
      },
      openProfileEditor() {
        this.profileForm = {
          nickname: this.userName || '',
          signature: this.userSignature || '',
          avatar: this.userAvatar || ''
        }
        this.showAvatarPicker = false
        this.showProfileModal = true
      },
      selectAvatarForProfile(avatar) {
        this.profileForm.avatar = avatar
      },
      async saveProfile() {
        try {
          const avatar = this.profileForm.avatar?.trim()
          if (!avatar) {
            uni.showToast({ title: '请选择头像', icon: 'none' })
            return
          }
          const nickname = this.profileForm.nickname?.trim()
          if (!nickname) {
            uni.showToast({ title: '昵称不能为空', icon: 'none' })
            return
          }
          const signature = this.profileForm.signature?.trim()
          if (!signature) {
            uni.showToast({ title: '个性签名不能为空', icon: 'none' })
            return
          }
          const params = {}
          if (nickname !== this.userName) params.nickname = nickname
          if (signature !== this.userSignature) params.signature = signature
          if (avatar !== this.userAvatar) params.avatar = avatar
          if (Object.keys(params).length === 0) {
            uni.showToast({ title: '未修改任何内容', icon: 'none' })
            return
          }
          const res = await editUserInfo(params)
          if (res) {
            if (params.nickname) {
              this.userName = params.nickname
              uni.setStorageSync('userName', this.userName)
            }
            if (params.signature) this.userSignature = params.signature
            if (params.avatar) {
              this.userAvatar = params.avatar
              uni.setStorageSync('userAvatar', this.userAvatar)
            }
            uni.showToast({ title: '保存成功', icon: 'success' })
            this.showProfileModal = false
          }
        } catch (e) {
          console.error('保存资料失败:', e)
          uni.showToast({ title: '保存失败', icon: 'none' })
        }
      },
      async initData() {
        try {
          const now = new Date()
          const month = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`
          const res = await getMonthStat({ month })
          this.monthIncome = res.income || 0
          this.monthExpend = res.expend || 0
          this.finishTaskCount = res.finishTask || 0
          const totalTask = res.totalTask || 0
          this.unfinishTaskCount = totalTask - this.finishTaskCount
          this.totalAmount = this.monthIncome - this.monthExpend
          this.finishRate = totalTask > 0 ? Math.round(this.finishTaskCount / totalTask * 100) : 0
        } catch (e) {
          this.totalAmount = 0
          this.finishRate = 0
        }
        try {
          const res = await getMonthBudget()
          this.monthBudget = res.amount || 0
        } catch (e) {}
      },
      handleThemeSetting() {
        uni.navigateTo({ url: '/pages/themeSetting/themeSetting' })
      },
      handleBudgetSetting() {
        this.tempBudget = this.formatNumber(this.monthBudget)
        this.showBudgetModal = true
      },
      async saveBudget() {
        const num = Number(this.tempBudget)
        if (!this.tempBudget || isNaN(num) || num < 0.01) {
          uni.showToast({ title: '请输入大于0的有效预算', icon: 'none' })
          return
        }
        try {
          await setMonthBudget({ amount: num })
          this.monthBudget = num
          this.showBudgetModal = false
          uni.showToast({ title: '设置成功', icon: 'success' })
        } catch (err) {
          uni.showToast({ title: '设置预算失败', icon: 'none' })
        }
      },
      handleAbout() {
        uni.navigateTo({ url: '/pages/about/about' })
      },
		async handleWechatBind() {
			if (this.isBindWechat) {
				return
			}
        try {
          const loginRes = await uni.login().catch(() => { throw new Error('获取微信登录凭证失败') })
          const code = loginRes.code
          if (!code) throw new Error('微信登录凭证为空')
          const result = await bindWechat({ code })
          if (result) {
            this.isBindWechat = true
            uni.showToast({ title: '绑定成功', icon: 'success' })
          } else {
            uni.showToast({ title: '绑定失败', icon: 'none' })
          }
        } catch (err) {
          uni.showToast({ title: err.message || '绑定失败', icon: 'none' })
        }
      },
      handleEmailSetting() {
        this.emailForm = {
          email: this.userEmail || '',
          password: '',
          confirmPassword: '',
          captcha: '',
          captchaId: '',
          emailCode: ''
        }
        this.showPassword = false
        this.showConfirmPassword = false
        this.showEmailPassword1 = false
        this.showEmailPassword2 = false
        this.showChangePassword = false
        this.isEditingEmail = false
        this.codeCountdown = 0
        this.showEmailModal = true
        this.refreshCaptcha()
      },
      handleEditEmail() {
        this.isEditingEmail = true
        this.showChangePassword = false
        this.emailForm.email = ''
        this.emailForm.password = ''
        this.emailForm.confirmPassword = ''
        this.emailForm.captcha = ''
        this.emailForm.emailCode = ''
        this.refreshCaptcha()
      },
      cancelChangePassword() {
        this.showChangePassword = false
        this.emailForm.password = ''
        this.emailForm.confirmPassword = ''
        this.emailForm.captcha = ''
        this.emailForm.emailCode = ''
        this.refreshCaptcha()
      },
      async refreshCaptcha() {
        try {
          const res = await getCaptcha()
          if (res?.image) {
            this.captchaImage = res.image
            this.emailForm.captchaId = res.captchaId
          }
        } catch (e) {
          console.error('获取验证码失败:', e)
        }
      },
      async sendEmailCode() {
        if (this.emailCodeCountdown > 0) return
        const captcha = this.emailForm.captcha?.trim()
        if (!captcha) {
          uni.showToast({ title: '请输入图形验证码', icon: 'none' })
          return
        }
        const email = this.emailForm.email?.trim()
        if (!email) {
          uni.showToast({ title: '请输入邮箱地址', icon: 'none' })
          return
        }
        const emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
        if (!emailReg.test(email)) {
          uni.showToast({ title: '请输入正确的邮箱格式', icon: 'none' })
          return
        }
        if (email === this.userEmail) {
          uni.showToast({ title: '邮箱未更改，无需验证', icon: 'none' })
          return
        }
        try {
          await sendEmailCode({ email, captcha, captchaId: this.emailForm.captchaId })
          uni.showToast({ title: '验证码已发送', icon: 'success' })
          this.emailCodeCountdown = 60
          const timer = setInterval(() => {
            this.emailCodeCountdown--
            if (this.emailCodeCountdown <= 0) clearInterval(timer)
          }, 1000)
          this.emailForm.captcha = ''
          this.refreshCaptcha()
        } catch (e) {
          uni.showToast({ title: '发送失败，请重试', icon: 'none' })
          this.refreshCaptcha()
        }
      },
      async submitEmail() {
        const email = this.emailForm.email?.trim()
        const emailCode = this.emailForm.emailCode?.trim()
        const password = this.emailForm.password?.trim()
        const confirmPassword = this.emailForm.confirmPassword?.trim()
        const captcha = this.emailForm.captcha?.trim()
        const isEmailChanged = email !== this.userEmail
        const isChangePasswordOnly = this.userEmail && !isEmailChanged && this.showChangePassword

        if (!email) {
          uni.showToast({ title: '请输入邮箱地址', icon: 'none' })
          return
        }
        const emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
        if (!emailReg.test(email)) {
          uni.showToast({ title: '请输入正确的邮箱格式', icon: 'none' })
          return
        }
        if (!password) {
          uni.showToast({ title: '请输入密码', icon: 'none' })
          return
        }
        if (password.length < 6) {
          uni.showToast({ title: '密码长度不能少于6位', icon: 'none' })
          return
        }
        if (!confirmPassword) {
          uni.showToast({ title: '请确认密码', icon: 'none' })
          return
        }
        if (password !== confirmPassword) {
          uni.showToast({ title: '两次密码不一致', icon: 'none' })
          return
        }
        if (!captcha) {
          uni.showToast({ title: '请输入图形验证码', icon: 'none' })
          return
        }
        if (isEmailChanged && !emailCode) {
          uni.showToast({ title: '请输入邮箱验证码', icon: 'none' })
          return
        }
        if (isEmailChanged && emailCode.length < 4) {
          uni.showToast({ title: '验证码格式不正确', icon: 'none' })
          return
        }
        try {
          if (isChangePasswordOnly) {
            await changePassword({ email, password, confirmPassword, captcha, captchaId: this.emailForm.captchaId })
            uni.showToast({ title: '密码修改成功', icon: 'success' })
            this.showEmailModal = false
          } else {
            const submitData = { email, password, captcha, captchaId: this.emailForm.captchaId }
            if (isEmailChanged) submitData.code = emailCode
            const res = await setUserEmail(submitData)
            if (res) {
              this.userEmail = email
              uni.setStorageSync('userEmail', email)
              uni.showToast({ title: this.userEmail ? '修改成功' : '绑定成功', icon: 'success' })
            }
            this.showEmailModal = false
          }
        } catch (e) {
          uni.showToast({ title: e.message || '操作失败', icon: 'none' })
          this.refreshCaptcha()
          this.emailForm.captcha = ''
        }
      }
    }
  }
</script>

<style lang="scss" scoped>
.mine-page {
  min-height: 100vh;
  padding-bottom: calc(40rpx + env(safe-area-inset-bottom));
}

.page-content {
  padding: calc(20rpx + env(safe-area-inset-top)) 32rpx 0;
}

/* ========== 区域标题 ========== */
.section-header {
  padding: 24rpx 4rpx 16rpx;
}

.section-title-row {
  display: flex;
  align-items: center;
  gap: 12rpx;
}

.section-accent {
  width: 8rpx;
  height: 28rpx;
  border-radius: 4rpx;
  flex-shrink: 0;
}

.section-title {
  font-size: 30rpx;
  font-weight: 800;
  letter-spacing: 1rpx;
}

.section-subtitle {
  font-size: 22rpx;
  font-weight: 500;
  margin-left: auto;
}

/* ========== 个人资料卡片 ========== */
.profile-card {
  border-radius: 20rpx;
  padding: 24rpx;
  margin-bottom: 8rpx;
  border: 2rpx solid transparent;
}

.profile-row {
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.avatar-wrapper {
  position: relative;
  width: 108rpx;
  height: 108rpx;
  flex-shrink: 0;
}

.avatar-img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
}

.avatar-placeholder {
  width: 100%;
  height: 100%;
  border-radius: 16rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.avatar-init {
  font-size: 40rpx;
  font-weight: 700;
  color: #fff;
}

.profile-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 10rpx;
  min-width: 0;
}

.profile-info-top {
  display: flex;
  align-items: center;
  gap: 10rpx;
}

.user-name {
  font-size: 32rpx;
  font-weight: 700;
}

.level-badge {
  padding: 4rpx 12rpx;
  border-radius: 8rpx;
}

.level-text {
  font-size: 22rpx;
  font-weight: 700;
}

.user-stats-row {
  display: flex;
  align-items: center;
  gap: 16rpx;
}

.user-stat {
  display: flex;
  align-items: baseline;
  gap: 6rpx;
}

.stat-num {
  font-size: 28rpx;
  font-weight: 700;
}

.stat-label {
  font-size: 20rpx;
  font-weight: 500;
}

.user-stat-divider {
  width: 2rpx;
  height: 28rpx;
}

.user-signature {
  font-size: 22rpx;
  font-weight: 500;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ========== 升级进度卡片 ========== */
.exp-card {
  border-radius: 20rpx;
  padding: 20rpx 24rpx;
  margin-bottom: 12rpx;
  border: 2rpx solid transparent;
}

.exp-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12rpx;
}

.exp-label {
  font-size: 24rpx;
  font-weight: 700;
}

.exp-text {
  font-size: 22rpx;
  font-weight: 500;
}

.exp-progress-bar {
  height: 12rpx;
  background: rgba(0, 0, 0, 0.06);
  border-radius: 6rpx;
  overflow: hidden;
}

.exp-progress-fill {
  height: 100%;
  border-radius: 6rpx;
}

/* ========== 数据统计卡片 ========== */
.stats-row {
  display: flex;
  gap: 14rpx;
  margin-bottom: 8rpx;
}

.stat-card {
  flex: 1;
  border-radius: 16rpx;
  padding: 18rpx 12rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10rpx;
  border: 2rpx solid transparent;
}

.stat-icon-wrap {
  width: 56rpx;
  height: 56rpx;
  border-radius: 12rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.stat-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4rpx;
}

.stat-val {
  font-size: 26rpx;
  font-weight: 800;
}

.stat-lbl {
  font-size: 20rpx;
  font-weight: 500;
}

/* ========== 菜单卡片 ========== */
.menu-card {
  border-radius: 20rpx;
  padding: 0 20rpx;
  border: 2rpx solid transparent;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 16rpx;
  padding: 20rpx 0;
}

.menu-icon {
  width: 56rpx;
  height: 56rpx;
  border-radius: 12rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.menu-title {
  flex: 1;
  font-size: 26rpx;
  font-weight: 600;
}

.menu-desc {
  font-size: 22rpx;
  font-weight: 500;
  margin-right: 8rpx;
}

.menu-item--disabled {
  opacity: 0.7;
}

.menu-arrow {
  flex-shrink: 0;
}

.menu-divider {
  height: 2rpx;
  opacity: 0.5;
}

.safe-area-bottom {
  height: env(safe-area-inset-bottom);
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.modal-box {
  width: 600rpx;
  border-radius: 20rpx;
  padding: 28rpx;
  max-height: 80vh;
  overflow-y: auto;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24rpx;
}

.modal-title {
  font-size: 32rpx;
  font-weight: 700;
}

.modal-close {
  width: 48rpx;
  height: 48rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-form {
  margin-bottom: 24rpx;
}

.form-label {
  font-size: 26rpx;
  font-weight: 600;
  margin-bottom: 10rpx;
  display: block;
}

.form-input {
  width: 100%;
  height: 80rpx;
  padding: 0 20rpx;
  font-size: 28rpx;
  border: 2rpx solid;
  border-radius: 12rpx;
  box-sizing: border-box;
}

.modal-actions {
  display: flex;
  gap: 16rpx;
  margin-top: 16rpx;
}

.modal-btn {
  flex: 1;
}

.modal-btn.full-width {
  flex: 1;
}

.profile-modal-content {
  display: flex;
  flex-direction: column;
  gap: 20rpx;
}

.profile-section {
  display: flex;
  flex-direction: column;
  gap: 10rpx;
}

.avatar-preview-wrapper {
  position: relative;
  width: 140rpx;
  height: 140rpx;
  align-self: center;
}

.profile-avatar-frame {
  width: 100%;
  height: 100%;
  border: 4rpx solid;
  border-radius: 16rpx;
  overflow: hidden;
}

.profile-avatar {
  width: 100%;
  height: 100%;
}

.avatar-edit-badge {
  position: absolute;
  bottom: -4rpx;
  right: -4rpx;
  width: 40rpx;
  height: 40rpx;
  border-radius: 10rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.avatar-picker {
  margin-top: 16rpx;
}

.avatar-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12rpx;
}

.avatar-option {
  display: flex;
  justify-content: center;
}

.avatar-frame {
  width: 80rpx;
  height: 80rpx;
  border: 3rpx solid;
  border-radius: 12rpx;
  overflow: hidden;
}

.avatar-option.is-selected .avatar-frame {
  border-width: 4rpx;
}

.option-avatar {
  width: 100%;
  height: 100%;
}

.email-modal-content {
  display: flex;
  flex-direction: column;
  gap: 16rpx;
}

.email-form {
  display: flex;
  flex-direction: column;
  gap: 16rpx;
}

.form-item {
  display: flex;
  flex-direction: column;
  gap: 8rpx;
}

.password-input-wrapper {
  position: relative;
}

.password-toggle-btn {
  position: absolute;
  right: 16rpx;
  top: 50%;
  transform: translateY(-50%);
  padding: 8rpx;
}

.captcha-row {
  display: flex;
  gap: 12rpx;
}

.captcha-input {
  flex: 1;
}

.captcha-img {
  width: 200rpx;
  height: 80rpx;
  border-radius: 12rpx;
  overflow: hidden;
}

.captcha-image {
  width: 100%;
  height: 100%;
}

.code-row {
  display: flex;
  gap: 12rpx;
}

.code-input {
  flex: 1;
}

.send-code-btn {
  padding: 0 20rpx;
  white-space: nowrap;
}

.change-password-btn {
  margin-bottom: 12rpx;
}

.btn-text {
  color: #fff;
}

.form-error {
  font-size: 22rpx;
  color: #e74c3c;
}
</style>
