<template>
  <view class="page-wrapper">
    <scroll-view scroll-y="true" class="profile-scroll">
      <view class="profile-content-wrap">
        <view v-if="isLoading" class="loading-container">
          <text class="loading-text">加载中...</text>
        </view>

        <view v-else-if="hasLoadError" class="error-container">
          <text class="error-text">加载失败</text>
          <button class="retry-button" @click="loadProfile">重试</button>
        </view>

        <view v-else class="profile-content">
          <view class="profile-card">
            <text class="card-title">基础信息</text>

            <view class="info-row avatar-row" @click="chooseAvatar">
              <text class="info-label">头像</text>
              <view class="info-value-wrap avatar-value-wrap">
                <image class="avatar-image" :src="userAvatar" mode="aspectFill"></image>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row">
              <text class="info-label">账号名</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getAccountName() }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row" @click="openTextEditor('username')">
              <text class="info-label">昵称</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getNicknameText() }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row" @click="showGenderPickerNow">
              <text class="info-label">性别</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getGenderText(profile.gender ?? 'other') }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row" @click="showBirthdayPickernow">
              <text class="info-label">出生日期</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getBirthdayText() }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row">
              <text class="info-label">注册日期</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ registeredDate }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row last-row" @click="openTextEditor('bio')">
              <text class="info-label">个性签名</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getBioText() }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>
          </view>

          <view class="profile-card">
            <text class="card-title">身体信息</text>

            <view class="info-row" @click="openTextEditor('height_cm')">
              <text class="info-label">身高</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getHeightText() }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row" @click="openTextEditor('weight_kg')">
              <text class="info-label">体重</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getWeightText() }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row last-row">
              <text class="info-label">BMI</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getBmiText() }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>
          </view>

          <view class="profile-card">
            <text class="card-title">康养档案</text>

            <view class="info-row" @click="openHealthGoalPicker">
              <text class="info-label">健康目标</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getTextOrPlaceholder(profile.health_goal, '未设置') }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row" @click="openAddressPicker">
              <text class="info-label">常住服务地址</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getServiceAddressText() }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row" @click="openTextEditor('emergency_contact')">
              <text class="info-label">紧急联系人</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getTextOrPlaceholder(profile.emergency_contact, '未填写') }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row" @click="openTextEditor('chronic_notes')">
              <text class="info-label">慢病/过敏备注</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getTextOrPlaceholder(profile.chronic_notes, '无') }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row" @click="openCarePreferencePicker">
              <text class="info-label">护理偏好</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getTextOrPlaceholder(profile.care_preference, '未设置') }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>

            <view class="info-row last-row" @click="openLanguagePicker">
              <text class="info-label">语言偏好</text>
              <view class="info-value-wrap">
                <text class="info-value">{{ getPreferredLanguageText() }}</text>
              </view>
              <text class="info-arrow">›</text>
            </view>
          </view>

          <button class="save-button" :disabled="isSaving" :loading="isSaving" @click="saveProfile(true)">
            保存修改
          </button>
        </view>

        <view v-if="showGenderPicker" class="picker-modal">
          <picker-view class="picker-view" :value="tempGenderIndex" :indicator-style="'height: 50px;'" @change="onGenderPickerViewChange">
            <picker-view-column style="width:750rpx;">
              <view v-for="(g, idx) in genderOptions" :key="g" class="picker-item">
                {{ getGenderText(g) }}
              </view>
            </picker-view-column>
          </picker-view>
          <view class="picker-actions">
            <button class="picker-action-button picker-action-cancel" @click="showGenderPicker = false">取消</button>
            <button class="picker-action-button picker-action-confirm" @click="confirmGenderPicker">确定</button>
          </view>
        </view>

        <view v-if="showBirthdayPicker" class="picker-modal">
          <picker-view class="picker-view" :value="tempBirthdayIndex" :indicator-style="'height: 50px;'" @change="onBirthdayPickerViewChange">
            <picker-view-column style="width:250rpx;">
              <view v-for="(year, idx) in birthdayYearOptions" :key="year" class="picker-item birthday-picker-item">
                {{ year }}年
              </view>
            </picker-view-column>
            <picker-view-column style="width:250rpx;">
              <view v-for="(month, idx) in birthdayMonthOptions" :key="month" class="picker-item birthday-picker-item">
                {{ month }}月
              </view>
            </picker-view-column>
            <picker-view-column style="width:250rpx;">
              <view v-for="(day, idx) in getBirthdayDayOptions()" :key="day" class="picker-item birthday-picker-item">
                {{ day }}日
              </view>
            </picker-view-column>
          </picker-view>
          <view class="picker-actions">
            <button class="picker-action-button picker-action-cancel" @click="showBirthdayPicker = false">取消</button>
            <button class="picker-action-button picker-action-confirm" @click="confirmBirthdayPicker">确定</button>
          </view>
        </view>

        <view v-if="showEditorModal" class="picker-modal">
          <view class="editor-sheet">
            <text class="editor-title">{{ editorTitle }}</text>
            <textarea
              v-if="editorIsTextarea"
              class="editor-textarea"
              :value="editorDraft"
              :placeholder="editorPlaceholder"
              placeholder-style="color: #b8b8b8;"
              @input="onEditorInput"
            ></textarea>
            <input
              v-else
              class="editor-input"
              :type="editorInputType"
              :value="editorDraft"
              :placeholder="editorPlaceholder"
              placeholder-style="color: #b8b8b8;"
              @input="onEditorInput"
            />
            <view class="picker-actions editor-actions">
              <button class="picker-action-button picker-action-cancel" @click="closeEditorModal">取消</button>
              <button class="picker-action-button picker-action-confirm" @click="confirmEditorModal">确定</button>
            </view>
          </view>
        </view>

        <view v-if="showLanguagePicker" class="picker-modal">
          <picker-view class="picker-view" :value="tempLanguageIndex" :indicator-style="'height: 50px;'" @change="onLanguagePickerViewChange">
            <picker-view-column style="width:750rpx;">
              <view v-for="(language, idx) in languageOptions" :key="language.id" class="picker-item">
                {{ language.label }}
              </view>
            </picker-view-column>
          </picker-view>
          <view class="picker-actions">
            <button class="picker-action-button picker-action-cancel" @click="showLanguagePicker = false">取消</button>
            <button class="picker-action-button picker-action-confirm" @click="confirmLanguagePicker">确定</button>
          </view>
        </view>

        <view v-if="showHealthGoalPicker" class="picker-modal">
          <picker-view class="picker-view" :value="tempHealthGoalIndex" :indicator-style="'height: 50px;'" @change="onHealthGoalPickerViewChange">
            <picker-view-column style="width:750rpx;">
              <view v-for="(goal, idx) in healthGoalOptions" :key="goal" class="picker-item">
                {{ goal }}
              </view>
            </picker-view-column>
          </picker-view>
          <view class="picker-actions">
            <button class="picker-action-button picker-action-cancel" @click="showHealthGoalPicker = false">取消</button>
            <button class="picker-action-button picker-action-confirm" @click="confirmHealthGoalPicker">确定</button>
          </view>
        </view>

        <view v-if="showCarePreferencePicker" class="picker-modal">
          <picker-view class="picker-view" :value="tempCarePreferenceIndex" :indicator-style="'height: 50px;'" @change="onCarePreferencePickerViewChange">
            <picker-view-column style="width:750rpx;">
              <view v-for="(preference, idx) in carePreferenceOptions" :key="preference" class="picker-item">
                {{ preference }}
              </view>
            </picker-view-column>
          </picker-view>
          <view class="picker-actions">
            <button class="picker-action-button picker-action-cancel" @click="showCarePreferencePicker = false">取消</button>
            <button class="picker-action-button picker-action-confirm" @click="confirmCarePreferencePicker">确定</button>
          </view>
        </view>

        <view v-if="showAddressPicker" class="picker-modal">
          <view class="address-sheet">
            <text class="editor-title">常住服务地址</text>
            <view v-if="recentAddressSuggestions.length > 0" class="address-suggestion-block">
              <text class="address-suggestion-title">最近使用</text>
              <view class="address-tag-list">
                <view v-for="(item, idx) in recentAddressSuggestions" :key="item" class="address-tag" @click="useAddressSuggestion(item)">
                  <text class="address-tag-text">{{ item }}</text>
                </view>
              </view>
            </view>
            <view class="address-suggestion-block">
              <text class="address-suggestion-title">常用示例</text>
              <view class="address-tag-list">
                <view v-for="(item, idx) in commonAddressSuggestions" :key="item" class="address-tag address-tag-light" @click="useAddressSuggestion(item)">
                  <text class="address-tag-text">{{ item }}</text>
                </view>
              </view>
            </view>
            <picker-view class="address-picker-view" :value="tempAddressRegionIndex" :indicator-style="'height: 50px;'" @change="onAddressPickerViewChange">
              <picker-view-column class="address-picker-column">
                <view v-for="(province, idx) in getProvinceOptions()" :key="province" class="picker-item address-picker-item">
                  {{ province }}
                </view>
              </picker-view-column>
              <picker-view-column class="address-picker-column">
                <view v-for="(city, idx) in getCurrentCityOptions()" :key="city" class="picker-item address-picker-item">
                  {{ city }}
                </view>
              </picker-view-column>
            </picker-view>
            <input
              class="editor-input address-detail-input"
              type="text"
              :value="tempAddressDetail"
              placeholder="请输入详细地址，如街道、门牌号"
              placeholder-style="color: #b8b8b8;"
              @input="onAddressDetailInput"
            />
            <view class="picker-actions editor-actions">
              <button class="picker-action-button picker-action-cancel" @click="closeAddressPicker">取消</button>
              <button class="picker-action-button picker-action-confirm" @click="confirmAddressPicker">确定</button>
            </view>
          </view>
        </view>
      </view>
    </scroll-view>
  </view>
</template>

<script setup lang="uts">
import { ref, onMounted } from 'vue'
import supa from '@/components/supadb/aksupainstance.uts'
import { setUserProfile } from '@/utils/store.uts'
import { PROFILE_REGION_OPTIONS, PROFILE_COMMON_ADDRESS_SUGGESTIONS } from '@/utils/profileRegionData.uts'
import type { UserProfile } from '@/types/mall-types.uts'

type AkLanguageRow = {
  id: string
  code: string
  name: string
  native_name: string
  is_active: boolean
  is_default: boolean
  sort_order: number
  created_at?: string
}

type LanguageOption = {
  id: string
  code: string
  name: string
  nativeName: string
  label: string
  isDefault: boolean
  sortOrder: number
  createdAt: string
}

const isLoading = ref<boolean>(false)
const isSaving = ref<boolean>(false)
const userAvatar = ref<string>('/static/logo.png')
const hasLoadError = ref<boolean>(false)
const registeredDate = ref<string>('暂未记录')
const profileRowId = ref<string>('')
const originalProfile = ref<UserProfile | null>(null)
const genderOptions: Array<string> = ['male', 'female', 'other']
const languageOptions = ref<Array<LanguageOption>>([])
const customOptionLabel = '自定义其他'
const healthGoalOptions: Array<string> = ['改善睡眠', '康复护理', '日常保健', '慢病管理', '营养调理', customOptionLabel]
const carePreferenceOptions: Array<string> = ['上门护理', '陪诊陪护', '康复训练', '定期回访', '电话提醒', customOptionLabel]
const regionOptions = PROFILE_REGION_OPTIONS
const commonAddressSuggestions = PROFILE_COMMON_ADDRESS_SUGGESTIONS
const recentAddressStorageKey = 'medical_profile_recent_addresses'
const tempGenderIndex = ref<Array<number>>([0])
const tempLanguageIndex = ref<Array<number>>([0])
const tempHealthGoalIndex = ref<Array<number>>([0])
const tempCarePreferenceIndex = ref<Array<number>>([0])
const tempAddressRegionIndex = ref<Array<number>>([0, 0])
const showGenderPicker = ref<boolean>(false)
const showBirthdayPicker = ref<boolean>(false)
const showLanguagePicker = ref<boolean>(false)
const showHealthGoalPicker = ref<boolean>(false)
const showCarePreferencePicker = ref<boolean>(false)
const showAddressPicker = ref<boolean>(false)
const showEditorModal = ref<boolean>(false)
const birthdayYearOptions: Array<number> = []
for (let year = 1970; year <= new Date().getFullYear(); year++) {
  birthdayYearOptions.push(year)
}
const birthdayMonthOptions: Array<number> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
const tempBirthdayIndex = ref<Array<number>>([30, 0, 0])
const tempAddressDetail = ref<string>('')
const recentAddressSuggestions = ref<Array<string>>([])
const editorField = ref<string>('')
const editorTitle = ref<string>('')
const editorPlaceholder = ref<string>('')
const editorDraft = ref<string>('')
const editorInputType = ref<string>('text')
const editorIsTextarea = ref<boolean>(false)

const getProvinceOptions = (): Array<string> => {
  const provinces: Array<string> = []
  for (let i = 0; i < regionOptions.length; i++) {
    provinces.push(regionOptions[i].name)
  }
  return provinces
}

const loadRecentAddressSuggestions = (): void => {
  const rawValue = uni.getStorageSync(recentAddressStorageKey) as string | null
  if (rawValue == null || rawValue == '') {
    recentAddressSuggestions.value = []
    return
  }

  const list = rawValue.split('||')
  const normalized: Array<string> = []
  for (let i = 0; i < list.length; i++) {
    const item = list[i].trim()
    if (item != '') {
      normalized.push(item)
    }
  }
  recentAddressSuggestions.value = normalized
}

const saveRecentAddressSuggestion = (addressText: string): void => {
  const normalizedAddress = addressText.trim()
  if (normalizedAddress == '') {
    return
  }

  const updated: Array<string> = [normalizedAddress]
  for (let i = 0; i < recentAddressSuggestions.value.length; i++) {
    const current = recentAddressSuggestions.value[i]
    if (current != normalizedAddress) {
      updated.push(current)
    }
    if (updated.length >= 5) {
      break
    }
  }
  recentAddressSuggestions.value = updated
  uni.setStorageSync(recentAddressStorageKey, updated.join('||'))
}

const profile = ref<UserProfile>({
  id: '',
  username: '',
  email: '',
  gender: 'other',
  birthday: '',
  height_cm: 0,
  weight_kg: 0,
  bio: '',
  avatar_url: '/static/logo.png',
  preferred_language: '',
  health_goal: '',
  service_address: '',
  emergency_contact: '',
  chronic_notes: '',
  care_preference: ''
} as UserProfile)

const goBack = (): void => {
  uni.navigateBack({
    delta: 1
  })
}

const formatDate = (value: string | null): string => {
  if (value == null || value == '') {
    return '暂未记录'
  }

  const dateText = value.split('T')[0]
  if (dateText != null && dateText != '') {
    return dateText
  }

  return value
}

const getAccountName = (): string => {
  const accountId = profile.value.id
  if (accountId == null || accountId == '') {
    return '暂未记录'
  }
  if (accountId.length <= 18) {
    return accountId
  }
  return accountId.substring(0, 8) + '...' + accountId.substring(accountId.length - 6)
}

const getGenderText = (genderCode: string): string => {
  if (genderCode == 'male') {
    return '男'
  } else if (genderCode == 'female') {
    return '女'
  } else {
    return '保密'
  }
}

const getBirthdayText = (): string => {
  const birthday = profile.value.birthday
  if (birthday != null && birthday != '') {
    return birthday
  }
  return '请填写您的生日'
}

const getNicknameText = (): string => {
  const username = profile.value.username
  if (username != null && username != '') {
    return username
  }
  return '请填写昵称'
}

const getBioText = (): string => {
  const bio = profile.value.bio
  if (bio != null && bio != '') {
    return bio
  }
  return '记录你的康养生活'
}

const getHeightText = (): string => {
  const height = profile.value.height_cm
  if (height != null && height > 0) {
    return '' + height + ' cm'
  }
  return '未填写'
}

const getWeightText = (): string => {
  const weight = profile.value.weight_kg
  if (weight != null && weight > 0) {
    return '' + weight + ' kg'
  }
  return '未填写'
}

const getBirthdayDayOptions = (): Array<number> => {
  const year = birthdayYearOptions[tempBirthdayIndex.value[0]]
  const month = birthdayMonthOptions[tempBirthdayIndex.value[1]]
  let maxDay = 31
  if (month == 4 || month == 6 || month == 9 || month == 11) {
    maxDay = 30
  } else if (month == 2) {
    const leapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
    maxDay = leapYear ? 29 : 28
  }
  const days: Array<number> = []
  for (let day = 1; day <= maxDay; day++) {
    days.push(day)
  }
  return days
}

const getBmiText = (): string => {
  const height = profile.value.height_cm
  const weight = profile.value.weight_kg
  if (height == null || weight == null || height <= 0 || weight <= 0) {
    return '待完善'
  }
  const heightMeter = height / 100.0
  const bmi = weight / (heightMeter * heightMeter)
  const rounded = Math.round(bmi * 10.0) / 10.0
  return '' + rounded
}

const normalizeString = (value: string | null | undefined): string | null => {
  if (value == null) {
    return null
  }
  const trimmed = value.trim()
  return trimmed == '' ? null : trimmed
}

const normalizeNumber = (value: number | null | undefined): number | null => {
  if (value == null) {
    return null
  }
  const numericValue = Number(value)
  return numericValue == numericValue ? numericValue : null
}

const normalizeDateString = (value: string | null | undefined): string | null => {
  const normalized = normalizeString(value)
  if (normalized == null) {
    return null
  }
  const parts = normalized.split('T')
  return parts.length > 0 ? parts[0] : normalized
}

const deepCloneProfile = (source: UserProfile): UserProfile => {
  return {
    id: source.id ?? '',
    username: source.username ?? '',
    email: source.email ?? '',
    gender: source.gender ?? '',
    birthday: source.birthday ?? '',
    height_cm: source.height_cm ?? 0,
    weight_kg: source.weight_kg ?? 0,
    bio: source.bio ?? '',
    avatar_url: source.avatar_url ?? '',
    preferred_language: source.preferred_language ?? '',
    health_goal: source.health_goal ?? '',
    service_address: source.service_address ?? '',
    emergency_contact: source.emergency_contact ?? '',
    chronic_notes: source.chronic_notes ?? '',
    care_preference: source.care_preference ?? '',
    role: source.role ?? '',
    school_id: source.school_id ?? '',
    grade_id: source.grade_id ?? '',
    class_id: source.class_id ?? '',
    created_at: source.created_at ?? '',
    updated_at: source.updated_at ?? ''
  } as UserProfile
}

const getLanguageOptionById = (languageId: string | null | undefined): LanguageOption | null => {
  const normalizedId = normalizeString(languageId)
  if (normalizedId == null) {
    return null
  }

  for (let i = 0; i < languageOptions.value.length; i++) {
    const option = languageOptions.value[i]
    if (option.id == normalizedId) {
      return option
    }
  }

  return null
}

const getDefaultLanguageOption = (): LanguageOption | null => {
  for (let i = 0; i < languageOptions.value.length; i++) {
    if (languageOptions.value[i].isDefault == true) {
      return languageOptions.value[i]
    }
  }

  for (let i = 0; i < languageOptions.value.length; i++) {
    if (languageOptions.value[i].code == 'zh-CN') {
      return languageOptions.value[i]
    }
  }

  return languageOptions.value.length > 0 ? languageOptions.value[0] : null
}

const getLanguageLabel = (languageId: string | null): string => {
  const language = getLanguageOptionById(languageId)
  return language != null ? language.label : '未设置'
}

const getPreferredLanguageText = (): string => {
  const currentLanguageId = normalizeString(profile.value.preferred_language)
  if (currentLanguageId != null) {
    return getLanguageLabel(currentLanguageId)
  }

  const defaultLanguage = getDefaultLanguageOption()
  return defaultLanguage != null ? defaultLanguage.label : '未设置'
}

const loadLanguageOptions = async (): Promise<void> => {
  const result = await supa
    .from('ak_languages')
    .select('id, code, name, native_name, is_active, is_default, sort_order, created_at', {} as UTSJSONObject)
    .eq('is_active', true)
    .order('sort_order', { ascending: true })
    .execute()

  if (result.error != null) {
    console.error('加载语言列表失败:', JSON.stringify(result.error))
    languageOptions.value = []
    return
  }

  const rows = result.data
  const options: Array<LanguageOption> = []
  if (Array.isArray(rows)) {
    for (let i = 0; i < rows.length; i++) {
      const item = rows[i] as UTSJSONObject
      const row: AkLanguageRow = {
        id: item.getString('id') ?? '',
        code: item.getString('code') ?? '',
        name: item.getString('name') ?? '',
        native_name: item.getString('native_name') ?? '',
        is_active: item.getBoolean('is_active') ?? false,
        is_default: item.getBoolean('is_default') ?? false,
        sort_order: item.getNumber('sort_order') ?? 0,
        created_at: item.getString('created_at') ?? ''
      }
      if (row.id == '') {
        continue
      }
      const label = row.native_name != '' ? row.native_name : (row.name != '' ? row.name : row.code)
      options.push({
        id: row.id,
        code: row.code,
        name: row.name,
        nativeName: row.native_name,
        label,
        isDefault: row.is_default,
        sortOrder: row.sort_order,
        createdAt: row.created_at ?? ''
      } as LanguageOption)
    }
  }

  for (let i = 0; i < options.length; i++) {
    for (let j = i + 1; j < options.length; j++) {
      let shouldSwap = false
      if (options[j].sortOrder < options[i].sortOrder) {
        shouldSwap = true
      } else if (options[j].sortOrder == options[i].sortOrder && options[j].createdAt != '' && options[i].createdAt != '' && options[j].createdAt < options[i].createdAt) {
        shouldSwap = true
      }
      if (shouldSwap) {
        const temp = options[i]
        options[i] = options[j]
        options[j] = temp
      }
    }
  }

  languageOptions.value = options
}

const getTextOrPlaceholder = (fieldValue: string | null | undefined, placeholder: string): string => {
  if (fieldValue != null && fieldValue != '') {
    return fieldValue
  }
  return placeholder
}

const extractAddressDetail = (addressText: string, province: string, city: string): string => {
  let detail = addressText.trim()
  const provinceIndex = detail.indexOf(province)
  if (provinceIndex >= 0) {
    detail = detail.substring(provinceIndex + province.length).trim()
  }

  if (city != '' && city != province) {
    while (detail.indexOf(city) == 0) {
      detail = detail.substring(city.length).trim()
    }
  } else {
    while (detail.indexOf(province) == 0) {
      detail = detail.substring(province.length).trim()
    }
  }

  return detail
}

const normalizeServiceAddress = (addressText: string | null | undefined): string => {
  if (addressText == null || addressText == '') {
    return ''
  }

  const normalizedText = addressText.trim()
  const provinceOptions = getProvinceOptions()
  for (let i = 0; i < provinceOptions.length; i++) {
    const province = provinceOptions[i]
    if (normalizedText.indexOf(province) >= 0) {
      const cityOptions = getCityOptions(province)
      let matchedCity = ''
      for (let j = 0; j < cityOptions.length; j++) {
        const city = cityOptions[j]
        if (normalizedText.indexOf(city) >= 0) {
          matchedCity = city
          break
        }
      }

      const defaultCity = cityOptions.length > 0 ? cityOptions[0] : ''
      const city = matchedCity != '' ? matchedCity : defaultCity
      const detail = extractAddressDetail(normalizedText, province, matchedCity)
      return buildRegionAddress(province, city, detail)
    }
  }

  return normalizedText
}

const getServiceAddressText = (): string => {
  const normalizedAddress = normalizeServiceAddress(profile.value.service_address)
  return getTextOrPlaceholder(normalizedAddress, '请选择服务地址')
}

const getProvinceIndexByName = (province: string): number => {
  const provinceOptions = getProvinceOptions()
  for (let i = 0; i < provinceOptions.length; i++) {
    if (provinceOptions[i] == province) {
      return i
    }
  }
  return 0
}

const getCityOptions = (province: string): Array<string> => {
  const cities: Array<string> = []
  const provinceIndex = getProvinceIndexByName(province)
  const selectedProvince = regionOptions[provinceIndex]
  for (let i = 0; i < selectedProvince.cities.length; i++) {
    cities.push(selectedProvince.cities[i].name)
  }
  return cities
}

const getCurrentCityOptions = (): Array<string> => {
  const provinceOptions = getProvinceOptions()
  return getCityOptions(provinceOptions[tempAddressRegionIndex.value[0]])
}

const buildRegionAddress = (province: string, city: string, detail: string): string => {
  const cleanDetail = detail.trim()
  let regionText = province

  if (city != '' && city != province) {
    regionText = regionText + city
  }

  if (cleanDetail != '') {
    return regionText + ' ' + cleanDetail
  }

  return regionText
}

const syncAddressPickerWithText = (addressText: string): void => {
  const normalizedText = addressText.trim()
  const provinceOptions = getProvinceOptions()
  let provinceIndex = 0
  for (let i = 0; i < provinceOptions.length; i++) {
    if (normalizedText.indexOf(provinceOptions[i]) >= 0) {
      provinceIndex = i
      break
    }
  }

  const province = provinceOptions[provinceIndex]
  const cityOptions = getCityOptions(province)
  let cityIndex = 0
  let matchedCity = ''
  for (let i = 0; i < cityOptions.length; i++) {
    if (normalizedText.indexOf(cityOptions[i]) >= 0) {
      cityIndex = i
      matchedCity = cityOptions[i]
      break
    }
  }

  tempAddressRegionIndex.value = [provinceIndex, cityIndex]
  tempAddressDetail.value = extractAddressDetail(normalizedText, province, matchedCity)
}

const useAddressSuggestion = (addressText: string): void => {
  syncAddressPickerWithText(addressText)
}

const isValidEmergencyContact = (value: string): boolean => {
  if (value == '') {
    return true
  }

  const normalized = value.replace('，', ' ').replace(',', ' ').replace('；', ' ').replace(';', ' ').trim()
  if (normalized.length < 2) {
    return false
  }

  let digitText = ''
  for (let i = 0; i < normalized.length; i++) {
    const char = normalized.charAt(i)
    if (char >= '0' && char <= '9') {
      digitText = digitText + char
    }
  }

  if (digitText == '') {
    return normalized.length >= 2 && normalized.length <= 20
  }

  if (digitText.length != 11) {
    return false
  }

  return digitText.charAt(0) == '1'
}

const openTextEditor = (fieldName: string): void => {
  editorField.value = fieldName
  editorInputType.value = 'text'
  editorIsTextarea.value = false

  if (fieldName == 'username') {
    editorTitle.value = '编辑昵称'
    editorPlaceholder.value = '请填写昵称'
    editorDraft.value = profile.value.username ?? ''
  } else if (fieldName == 'bio') {
    editorTitle.value = '编辑个性签名'
    editorPlaceholder.value = '记录你的康养生活'
    editorDraft.value = profile.value.bio ?? ''
    editorIsTextarea.value = true
  } else if (fieldName == 'height_cm') {
    editorTitle.value = '编辑身高'
    editorPlaceholder.value = '请输入身高(cm)'
    editorDraft.value = profile.value.height_cm != null && profile.value.height_cm > 0 ? '' + profile.value.height_cm : ''
    editorInputType.value = 'number'
  } else if (fieldName == 'weight_kg') {
    editorTitle.value = '编辑体重'
    editorPlaceholder.value = '请输入体重(kg)'
    editorDraft.value = profile.value.weight_kg != null && profile.value.weight_kg > 0 ? '' + profile.value.weight_kg : ''
    editorInputType.value = 'number'
  } else if (fieldName == 'health_goal') {
    editorTitle.value = '自定义健康目标'
    editorPlaceholder.value = '请输入健康目标'
    editorDraft.value = profile.value.health_goal == customOptionLabel ? '' : profile.value.health_goal ?? ''
  } else if (fieldName == 'care_preference') {
    editorTitle.value = '自定义护理偏好'
    editorPlaceholder.value = '请输入护理偏好'
    editorDraft.value = profile.value.care_preference == customOptionLabel ? '' : profile.value.care_preference ?? ''
  } else if (fieldName == 'emergency_contact') {
    editorTitle.value = '编辑紧急联系人'
    editorPlaceholder.value = '请输入姓名或联系方式'
    editorDraft.value = profile.value.emergency_contact ?? ''
  } else if (fieldName == 'chronic_notes') {
    editorTitle.value = '编辑慢病/过敏备注'
    editorPlaceholder.value = '请输入慢病或过敏备注'
    editorDraft.value = profile.value.chronic_notes ?? ''
    editorIsTextarea.value = true
  } else {
    editorTitle.value = '编辑信息'
    editorPlaceholder.value = '请输入内容'
    editorDraft.value = ''
  }

  showEditorModal.value = true
}

const closeEditorModal = (): void => {
  showEditorModal.value = false
}

const onEditorInput = (e: UniInputEvent): void => {
  editorDraft.value = e.detail.value
}

const confirmEditorModal = (): void => {
  const draft = editorDraft.value.trim()
  if (editorField.value == 'emergency_contact' && !isValidEmergencyContact(draft)) {
    uni.showToast({
      title: '联系人格式不正确',
      icon: 'none'
    })
    return
  }
  if (editorField.value == 'username') {
    profile.value.username = draft
  } else if (editorField.value == 'bio') {
    profile.value.bio = draft
  } else if (editorField.value == 'height_cm') {
    profile.value.height_cm = draft == '' ? 0 : parseInt(draft)
  } else if (editorField.value == 'weight_kg') {
    profile.value.weight_kg = draft == '' ? 0 : parseInt(draft)
  } else if (editorField.value == 'health_goal') {
    profile.value.health_goal = draft
  } else if (editorField.value == 'care_preference') {
    profile.value.care_preference = draft
  } else if (editorField.value == 'emergency_contact') {
    profile.value.emergency_contact = draft
  } else if (editorField.value == 'chronic_notes') {
    profile.value.chronic_notes = draft
  }
  showEditorModal.value = false
}

const openHealthGoalPicker = (): void => {
  const currentValue = profile.value.health_goal
  const idx = currentValue != null ? healthGoalOptions.indexOf(currentValue) : -1
  tempHealthGoalIndex.value = [idx >= 0 ? idx : 0]
  showHealthGoalPicker.value = true
}

const onHealthGoalPickerViewChange = (e: UniPickerViewChangeEvent): void => {
  const idx = e.detail.value[0]
  tempHealthGoalIndex.value = [(idx >= 0 && idx < healthGoalOptions.length) ? idx : 0]
}

const confirmHealthGoalPicker = (): void => {
  const selectedValue = healthGoalOptions[tempHealthGoalIndex.value[0]]
  showHealthGoalPicker.value = false
  if (selectedValue == customOptionLabel) {
    openTextEditor('health_goal')
    return
  }
  profile.value.health_goal = selectedValue
}

const openCarePreferencePicker = (): void => {
  const currentValue = profile.value.care_preference
  const idx = currentValue != null ? carePreferenceOptions.indexOf(currentValue) : -1
  tempCarePreferenceIndex.value = [idx >= 0 ? idx : 0]
  showCarePreferencePicker.value = true
}

const onCarePreferencePickerViewChange = (e: UniPickerViewChangeEvent): void => {
  const idx = e.detail.value[0]
  tempCarePreferenceIndex.value = [(idx >= 0 && idx < carePreferenceOptions.length) ? idx : 0]
}

const confirmCarePreferencePicker = (): void => {
  const selectedValue = carePreferenceOptions[tempCarePreferenceIndex.value[0]]
  showCarePreferencePicker.value = false
  if (selectedValue == customOptionLabel) {
    openTextEditor('care_preference')
    return
  }
  profile.value.care_preference = selectedValue
}

const openAddressPicker = (): void => {
  const addressText = profile.value.service_address ?? ''
  syncAddressPickerWithText(addressText)
  showAddressPicker.value = true
}

const onAddressPickerViewChange = (e: UniPickerViewChangeEvent): void => {
  const values = e.detail.value
  const provinceOptions = getProvinceOptions()
  let provinceIndex = values[0]
  if (provinceIndex < 0 || provinceIndex >= provinceOptions.length) {
    provinceIndex = 0
  }

  const cityOptions = getCityOptions(provinceOptions[provinceIndex])
  let cityIndex = values[1]
  if (cityIndex < 0 || cityIndex >= cityOptions.length) {
    cityIndex = 0
  }

  tempAddressRegionIndex.value = [provinceIndex, cityIndex]
}

const onAddressDetailInput = (e: UniInputEvent): void => {
  tempAddressDetail.value = e.detail.value
}

const closeAddressPicker = (): void => {
  showAddressPicker.value = false
}

const confirmAddressPicker = (): void => {
  const provinceOptions = getProvinceOptions()
  const province = provinceOptions[tempAddressRegionIndex.value[0]]
  const cityOptions = getCurrentCityOptions()
  const city = cityOptions[tempAddressRegionIndex.value[1]]
  profile.value.service_address = buildRegionAddress(province, city, tempAddressDetail.value)
  saveRecentAddressSuggestion(profile.value.service_address ?? '')
  showAddressPicker.value = false
}

const openLanguagePicker = (): void => {
  if (languageOptions.value.length == 0) {
    uni.showToast({
      title: '语言列表加载中',
      icon: 'none'
    })
    return
  }

  const currentLanguageId = normalizeString(profile.value.preferred_language)
  const defaultLanguage = getDefaultLanguageOption()
  const targetLanguageId = currentLanguageId != null ? currentLanguageId : (defaultLanguage != null ? defaultLanguage.id : '')
  let idx = 0
  for (let i = 0; i < languageOptions.value.length; i++) {
    if (languageOptions.value[i].id == targetLanguageId) {
      idx = i
      break
    }
  }
  tempLanguageIndex.value = [idx]
  showLanguagePicker.value = true
}

const onLanguagePickerViewChange = (e: UniPickerViewChangeEvent): void => {
  const idx = e.detail.value[0]
  tempLanguageIndex.value = [(idx >= 0 && idx < languageOptions.value.length) ? idx : 0]
}

const confirmLanguagePicker = (): void => {
  if (languageOptions.value.length > 0) {
    profile.value.preferred_language = languageOptions.value[tempLanguageIndex.value[0]].id
  }
  showLanguagePicker.value = false
}

const loadProfile = async (): Promise<void> => {
  isLoading.value = true
  hasLoadError.value = false
  registeredDate.value = '暂未记录'
  
  const user = supa.user
  if (user == null) {
    hasLoadError.value = true
    isLoading.value = false
    return
  }
  
  const userEmail = user.getString('email')
  if (userEmail == null || userEmail == '') {
    hasLoadError.value = true
    isLoading.value = false
    return
  }

  const userCreatedAt = user.getString('created_at')
  if (userCreatedAt != null && userCreatedAt != '') {
    registeredDate.value = formatDate(userCreatedAt)
  }
  
  const result = await supa
    .from('ak_users')
    .select('*', {} as UTSJSONObject)
    .or('id.eq.' + (user.id as string) + ',auth_id.eq.' + (user.id as string))
    .execute()
  const data = result.data
  
  if (Array.isArray(data) && data.length > 0) {
    const prodata = data[0] as UTSJSONObject
    profileRowId.value = prodata.getString('id') ?? (user.id as string)
    const p: UserProfile = {
      id: profileRowId.value,
      username: prodata.getString('username') ?? '',
      email: prodata.getString('email') ?? '',
      gender: prodata.getString('gender') ?? 'other',
      birthday: prodata.getString('birthday') ?? '',
      height_cm: prodata.getNumber('height_cm') ?? 0,
      weight_kg: prodata.getNumber('weight_kg') ?? 0,
      bio: prodata.getString('bio') ?? '',
      avatar_url: prodata.getString('avatar_url') ?? '/static/logo.png',
      preferred_language: prodata.getString('preferred_language') ?? '',
      health_goal: prodata.getString('health_goal') ?? '',
      service_address: prodata.getString('service_address') ?? '',
      emergency_contact: prodata.getString('emergency_contact') ?? '',
      chronic_notes: prodata.getString('chronic_notes') ?? '',
      care_preference: prodata.getString('care_preference') ?? ''
    } as UserProfile
    p.service_address = normalizeServiceAddress(p.service_address)
    profile.value = p
    originalProfile.value = deepCloneProfile(p)
    const createdAt = prodata.getString('created_at')
    if (createdAt != null && createdAt != '') {
      registeredDate.value = formatDate(createdAt)
    }
    
    if (p.avatar_url != null && p.avatar_url != '') {
      userAvatar.value = p.avatar_url!
    }
    
    setUserProfile(p)
  } else {
    profileRowId.value = user.getString('id') ?? ''
    profile.value.id = profileRowId.value
    profile.value.username = user.getString('username') ?? ''
    profile.value.email = user.getString('email') ?? ''
    if (profile.value.avatar_url != null && profile.value.avatar_url != '') {
      userAvatar.value = profile.value.avatar_url!
    }
    
    if (profile.value.username == '') {
      const emailStr = profile.value.email
      if (emailStr != null && emailStr != '') {
        const parts = emailStr.split('@')
        if (parts.length > 0) {
          profile.value.username = parts[0]
        }
      }
    }
    profile.value.service_address = normalizeServiceAddress(profile.value.service_address)
    
    const newProfile = new UTSJSONObject({
      id: profileRowId.value,
      auth_id: user.getString('id') ?? '',
      username: profile.value.username,
      email: profile.value.email,
      gender: profile.value.gender,
      health_goal: profile.value.health_goal,
      service_address: profile.value.service_address,
      emergency_contact: profile.value.emergency_contact,
      chronic_notes: profile.value.chronic_notes,
      care_preference: profile.value.care_preference
    })
    
    const insertResult = await supa.from('ak_users').insert(newProfile).execute()
    if (insertResult.error == null) {
      const newProfileData: UserProfile = {
        id: profileRowId.value,
        username: profile.value.username,
        email: profile.value.email,
        gender: profile.value.gender,
        health_goal: profile.value.health_goal,
        service_address: profile.value.service_address,
        emergency_contact: profile.value.emergency_contact,
        chronic_notes: profile.value.chronic_notes,
        care_preference: profile.value.care_preference
      } as UserProfile
      setUserProfile(newProfileData)
    }
    originalProfile.value = deepCloneProfile(profile.value)
  }
  
  isLoading.value = false
}

const buildProfileUpdatePayload = (): UTSJSONObject => {
  const payload = new UTSJSONObject()
  const oldProfile = originalProfile.value
  const newProfile = profile.value

  if (oldProfile == null) {
    return payload
  }

  if (normalizeString(oldProfile.username) != normalizeString(newProfile.username)) {
    payload.set('username', normalizeString(newProfile.username))
  }
  if (normalizeString(oldProfile.avatar_url) != normalizeString(newProfile.avatar_url)) {
    payload.set('avatar_url', normalizeString(newProfile.avatar_url))
  }
  if (normalizeString(oldProfile.gender) != normalizeString(newProfile.gender)) {
    payload.set('gender', normalizeString(newProfile.gender))
  }
  if (normalizeDateString(oldProfile.birthday) != normalizeDateString(newProfile.birthday)) {
    payload.set('birthday', normalizeDateString(newProfile.birthday))
  }
  if (normalizeString(oldProfile.service_address) != normalizeString(newProfile.service_address)) {
    payload.set('service_address', normalizeString(newProfile.service_address))
  }
  if (normalizeString(oldProfile.bio) != normalizeString(newProfile.bio)) {
    payload.set('bio', normalizeString(newProfile.bio))
  }
  if (normalizeNumber(oldProfile.height_cm) != normalizeNumber(newProfile.height_cm)) {
    payload.set('height_cm', normalizeNumber(newProfile.height_cm))
  }
  if (normalizeNumber(oldProfile.weight_kg) != normalizeNumber(newProfile.weight_kg)) {
    payload.set('weight_kg', normalizeNumber(newProfile.weight_kg))
  }
  if (normalizeString(oldProfile.preferred_language) != normalizeString(newProfile.preferred_language)) {
    payload.set('preferred_language', normalizeString(newProfile.preferred_language))
  }
  if (normalizeString(oldProfile.health_goal) != normalizeString(newProfile.health_goal)) {
    payload.set('health_goal', normalizeString(newProfile.health_goal))
  }
  if (normalizeString(oldProfile.emergency_contact) != normalizeString(newProfile.emergency_contact)) {
    payload.set('emergency_contact', normalizeString(newProfile.emergency_contact))
  }
  if (normalizeString(oldProfile.chronic_notes) != normalizeString(newProfile.chronic_notes)) {
    payload.set('chronic_notes', normalizeString(newProfile.chronic_notes))
  }
  if (normalizeString(oldProfile.care_preference) != normalizeString(newProfile.care_preference)) {
    payload.set('care_preference', normalizeString(newProfile.care_preference))
  }

  return payload
}

const saveProfile = async (shouldReturn: boolean = false): Promise<void> => {
  const userid: string = profileRowId.value != '' ? profileRowId.value : (profile.value.id ?? '')
  const updatePayload = buildProfileUpdatePayload()
  if (UTSJSONObject.keys(updatePayload).length == 0) {
    uni.showToast({
      title: '没有修改内容',
      icon: 'none'
    })
    return
  }

  isSaving.value = true

  try {
    updatePayload.set('updated_at', new Date().toISOString())

    const result = await supa
      .from('ak_users')
      .update(updatePayload)
      .eq('id', userid)
      .execute()
    
    if (result.error == null) {
      originalProfile.value = deepCloneProfile(profile.value)
      setUserProfile(profile.value)
      uni.showToast({
        title: '保存成功',
        icon: 'success'
      })
      if (shouldReturn) {
        setTimeout((): void => {
          uni.navigateBack({
            delta: 1
          })
        }, 500)
      }
    } else {
      console.log('saveProfile update ak_users error:', JSON.stringify(result.error))
      uni.showToast({
        title: '保存失败',
        icon: 'none'
      })
    }
  } catch (e) {
    console.log('saveProfile exception:', e)
    uni.showToast({
      title: '保存失败，请稍后重试',
      icon: 'none'
    })
  }
  
  isSaving.value = false
}

const getUuid = (): string => {
  return `${Date.now()}_${Math.floor(Math.random() * 1e8)}`
}

const chooseAvatar = (): void => {
  uni.chooseImage({
    count: 1,
    sizeType: ['compressed'],
    sourceType: ['album', 'camera'],
    success: (res: ChooseImageSuccess) => {
      const upfilepath = res.tempFilePaths[0]
      const userId = profile.value.id ?? ''
      let ext = 'png'
      
      const tempFiles = res.tempFiles
      if (Array.isArray(tempFiles) && tempFiles.length > 0) {
        const fileObj: ChooseImageTempFile = tempFiles[0]
        const fileName = fileObj.name
        if (fileName != null && fileName != '') {
          const idx = fileName.lastIndexOf('.')
          if (idx >= 0) {
            ext = fileName.substring(idx + 1)
          }
        }
      }
      
      const uuid = getUuid()
      const remotePath = `profiles/${userId}_${uuid}.${ext}`
      
      supa.storage.from('zhipao').upload(remotePath, upfilepath, {}).then((uploadResult) => {
        if (uploadResult.status == 200 || uploadResult.status == 201) {
          const data = uploadResult.data
          if (data != null) {
            const dataObj = data as UTSJSONObject
            let avatarUrl = dataObj.getString('Key')
            if (avatarUrl != null && avatarUrl != '') {
              avatarUrl = 'https://ak3.oulog.com/storage/v1/object/public/' + avatarUrl
              userAvatar.value = avatarUrl
              profile.value.avatar_url = avatarUrl
              saveProfile()
            }
          }
        } else {
          uni.showToast({ title: '上传失败', icon: 'none' })
        }
      })
    }
  })
}

const showGenderPickerNow = (): void => {
  const genderValue = profile.value.gender
  const idx = genderValue != null ? genderOptions.indexOf(genderValue) : -1
  tempGenderIndex.value = [idx >= 0 ? idx : 0]
  showGenderPicker.value = true
}

const onGenderPickerViewChange = (e: UniPickerViewChangeEvent): void => {
  const idx = e.detail.value[0]
  tempGenderIndex.value = [(idx >= 0 && idx < genderOptions.length) ? idx : 0]
}

const confirmGenderPicker = (): void => {
  profile.value.gender = genderOptions[tempGenderIndex.value[0]]
  showGenderPicker.value = false
}

const onBirthdayPickerViewChange = (e: UniPickerViewChangeEvent): void => {
  const values = e.detail.value
  let yearIndex = values[0]
  if (yearIndex < 0 || yearIndex >= birthdayYearOptions.length) {
    yearIndex = 0
  }
  let monthIndex = values[1]
  if (monthIndex < 0 || monthIndex >= birthdayMonthOptions.length) {
    monthIndex = 0
  }
  const nextIndex = [yearIndex, monthIndex, 0]
  tempBirthdayIndex.value = nextIndex
  const dayOptions = getBirthdayDayOptions()
  let dayIndex = values[2]
  if (dayIndex < 0 || dayIndex >= dayOptions.length) {
    dayIndex = 0
  }
  tempBirthdayIndex.value = [yearIndex, monthIndex, dayIndex]
}

const showBirthdayPickernow = (): void => {
  const birthday = profile.value.birthday
  if (birthday != null && birthday != '') {
    const parts = birthday.split('-')
    if (parts.length == 3) {
      const yearValue = parseInt(parts[0])
      const monthValue = parseInt(parts[1])
      const dayValue = parseInt(parts[2])
      let yearIndex = birthdayYearOptions.indexOf(yearValue)
      if (yearIndex < 0) {
        yearIndex = 0
      }
      let monthIndex = birthdayMonthOptions.indexOf(monthValue)
      if (monthIndex < 0) {
        monthIndex = 0
      }
      tempBirthdayIndex.value = [yearIndex, monthIndex, 0]
      const dayOptions = getBirthdayDayOptions()
      let dayIndex = dayOptions.indexOf(dayValue)
      if (dayIndex < 0) {
        dayIndex = 0
      }
      tempBirthdayIndex.value = [yearIndex, monthIndex, dayIndex]
    }
  } else {
    tempBirthdayIndex.value = [birthdayYearOptions.indexOf(2000), 0, 0]
  }
  showBirthdayPicker.value = true
}

const confirmBirthdayPicker = (): void => {
  showBirthdayPicker.value = false
  const y = birthdayYearOptions[tempBirthdayIndex.value[0]]
  const m = birthdayMonthOptions[tempBirthdayIndex.value[1]]
  const dayOptions = getBirthdayDayOptions()
  const d = dayOptions[tempBirthdayIndex.value[2]]
  const mm = m < 10 ? '0' + m : '' + m
  const dd = d < 10 ? '0' + d : '' + d
  profile.value.birthday = `${y}-${mm}-${dd}`
}

onMounted(() => {
  loadRecentAddressSuggestions()
  loadLanguageOptions()
  loadProfile()
})
</script>

<style>
.page-wrapper {
  display: flex;
  flex-direction: column;
  background-color: #f6f6f6;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.custom-nav {
  height: 96rpx;
  background-color: #ffffff;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  padding: 0 24rpx;
  border-bottom-width: 1rpx;
  border-bottom-style: solid;
  border-bottom-color: #f0f0f0;
  box-sizing: border-box;
}

.nav-left,
.nav-right {
  width: 120rpx;
  height: 96rpx;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.nav-right {
  justify-content: flex-end;
}

.nav-icon {
  font-size: 36rpx;
  color: #222;
  font-weight: 500;
}

.nav-title {
  flex: 1;
  text-align: center;
  font-size: 32rpx;
  color: #222;
  font-weight: 500;
}

.profile-scroll {
  flex: 1;
  height: 0;
}

.profile-content-wrap {
  min-height: 100%;
  padding-bottom: 40rpx;
}

.profile-content {
  padding-top: 20rpx;
}

.profile-card {
  margin: 20rpx;
  padding: 8rpx 0;
  background-color: #ffffff;
  border-radius: 20rpx;
  box-sizing: border-box;
}

.card-title {
  padding: 18rpx 28rpx 8rpx 28rpx;
  font-size: 24rpx;
  color: #999;
}

.info-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  min-height: 102rpx;
  padding: 0 28rpx;
  box-sizing: border-box;
  border-bottom-width: 1rpx;
  border-bottom-style: solid;
  border-bottom-color: #f4f4f4;
}

.avatar-row {
  min-height: 130rpx;
}

.last-row {
  border-bottom-width: 0;
}

.info-label {
  width: 180rpx;
  font-size: 28rpx;
  color: #222;
}

.info-value-wrap {
  flex-shrink: 0;
  flex: 1;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-end;
  min-width: 0;
}

.avatar-value-wrap {
  justify-content: flex-end;
}

.info-value {
  flex: 1;
  font-size: 26rpx;
  color: #999;
  text-align: right;
  lines: 1;
  text-overflow: ellipsis;
}

.info-arrow {
  width: 28rpx;
  margin-left: 16rpx;
  font-size: 28rpx;
  color: #c7c7c7;
  text-align: right;
}

.avatar-image {
  width: 88rpx;
  height: 88rpx;
  border-radius: 44rpx;
  background-color: #ededed;
}

.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 80%;
}

.loading-text {
  font-size: 28rpx;
  color: #666;
}

.error-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding-top: 240rpx;
}

.error-text {
  font-size: 28rpx;
  color: #f44336;
  margin-bottom: 20rpx;
}

.retry-button {
  width: 240rpx;
  height: 84rpx;
  font-size: 28rpx;
  background-color: #2f80ed;
  color: white;
  border-radius: 42rpx;
}

.save-button {
  margin: 28rpx 20rpx 0 20rpx;
  width: auto;
  height: 90rpx;
  font-size: 32rpx;
  border-radius: 45rpx;
  background-color: #21b883;
  color: #fff;
  font-weight: 500;
  text-align: center;
}

.save-button:disabled {
  background: #ccc;
}

.picker-modal {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: #fff;
  z-index: 1000;
  padding-bottom: 30rpx;
  border-top-left-radius: 20rpx;
  border-top-right-radius: 20rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.picker-view {
  width: 750rpx;
  height: 320px;
  background: #fff;
}

.picker-item {
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 750rpx;
}

.birthday-picker-item {
  width: 250rpx;
}

.picker-actions {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  width: 750rpx;
  padding: 20rpx 40rpx 0 40rpx;
  box-sizing: border-box;
}

.picker-action-button {
  width: 300rpx;
  height: 84rpx;
  margin: 0;
  border-radius: 16rpx;
  font-size: 28rpx;
  text-align: center;
}

.picker-action-cancel {
  background: #f2f3f5;
  color: #666;
}

.picker-action-confirm {
  background: #21b883;
  color: #fff;
}

.editor-sheet,
.option-sheet {
  width: 750rpx;
  background: #fff;
  border-top-left-radius: 20rpx;
  border-top-right-radius: 20rpx;
  padding: 30rpx;
  box-sizing: border-box;
}

.editor-title {
  font-size: 30rpx;
  color: #222;
  text-align: center;
  margin-bottom: 24rpx;
}

.editor-input {
  width: 100%;
  height: 88rpx;
  padding: 0 24rpx;
  background-color: #f7f7f7;
  border-radius: 16rpx;
  box-sizing: border-box;
  font-size: 28rpx;
  color: #333;
}

.editor-textarea {
  width: 100%;
  height: 180rpx;
  padding: 24rpx;
  background-color: #f7f7f7;
  border-radius: 16rpx;
  box-sizing: border-box;
  font-size: 28rpx;
  color: #333;
}

.editor-actions {
  width: 100%;
  padding: 30rpx 0 0 0;
}

.address-sheet {
  width: 750rpx;
  background: #fff;
  border-top-left-radius: 20rpx;
  border-top-right-radius: 20rpx;
  padding: 30rpx;
  box-sizing: border-box;
}

.address-picker-view {
  width: 100%;
  height: 320px;
  background: #fff;
}

.address-suggestion-block {
  margin-bottom: 20rpx;
}

.address-suggestion-title {
  font-size: 24rpx;
  color: #999;
  margin-bottom: 12rpx;
}

.address-tag-list {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.address-tag {
  max-width: 100%;
  padding: 12rpx 18rpx;
  margin-right: 12rpx;
  margin-bottom: 12rpx;
  background-color: #ecf8f2;
  border-radius: 999rpx;
}

.address-tag-light {
  background-color: #f5f6f8;
}

.address-tag-text {
  font-size: 24rpx;
  color: #4b5563;
}

.address-picker-column {
  width: 345rpx;
}

.address-picker-item {
  width: 345rpx;
}

.address-detail-input {
  margin-top: 20rpx;
}

.option-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  min-height: 96rpx;
  border-bottom-width: 1rpx;
  border-bottom-style: solid;
  border-bottom-color: #f0f0f0;
}

.option-last-row {
  border-bottom-width: 0;
}

.option-text {
  font-size: 28rpx;
  color: #333;
}
</style>
