<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import {
  appDiningProfileConfigGet,
  appDiningProfileGet,
  appDiningProfileSavePost,
} from '@/service'
const { t } = useI18n()

type Option = { id: string; label: string }
type Field = {
  fieldKey: string
  fieldName: string
  groupKey: string
  groupName: string
  sortNum: number
  isRequired: boolean
  multiple: boolean
  options: Option[]
}
type Group = {
  key: string
  title: string
  sortNum: number
  fields: Field[]
}
type SelectedMap = Record<string, string[]>
type ProfileMap = Record<string, unknown>

const PREF_FLAG_KEY = 'ai_diet_pref_done'
const PREF_DATA_KEY = 'ai_diet_pref_data'

const loading = ref(false)
const groups = ref<Group[]>([])
const selectedMap = ref<SelectedMap>({})

function getFallbackGroups(): Group[] {
  return [
    {
      key: 'taste',
      title: t('pages.ai.dietPreference.fallback.groupTaste'),
      sortNum: 1,
      fields: [
        {
          fieldKey: 'taste_like',
          fieldName: t('pages.ai.dietPreference.fallback.tasteLike'),
          groupKey: 'taste',
          groupName: t('pages.ai.dietPreference.fallback.groupTaste'),
          sortNum: 1,
          isRequired: false,
          multiple: false,
          options: [
            { id: 'zkw', label: t('pages.ai.dietPreference.fallback.optionHeavy') },
            { id: 'qd', label: t('pages.ai.dietPreference.fallback.optionLight') },
            { id: 'ml', label: t('pages.ai.dietPreference.fallback.optionSpicy') },
          ],
        },
        {
          fieldKey: 'taste_taboo',
          fieldName: t('pages.ai.dietPreference.fallback.tasteTaboo'),
          groupKey: 'taste',
          groupName: t('pages.ai.dietPreference.fallback.groupTaste'),
          sortNum: 2,
          isRequired: false,
          multiple: true,
          options: [
            { id: 'seafood', label: t('pages.ai.dietPreference.fallback.optionSeafood') },
            { id: 'organ', label: t('pages.ai.dietPreference.fallback.optionOrgan') },
            { id: 'onion', label: t('pages.ai.dietPreference.fallback.optionOnion') },
          ],
        },
      ],
    },
  ]
}

const hasGroups = computed(() => groups.value.length > 0)

function goPreference() {
  const current = getCurrentPages?.().slice(-1)[0]
  if (current?.route === 'pages/ai/diet-preference/index') return
  uni.navigateTo({
    url: '/pages/ai/diet-preference/index',
  })
}

function parseOptionsJson(optionsJson: unknown): Option[] {
  if (!optionsJson) return []
  let rawList: any[] = []
  if (Array.isArray(optionsJson)) {
    rawList = optionsJson
  } else if (typeof optionsJson === 'string') {
    try {
      rawList = JSON.parse(optionsJson)
    } catch (e) {
      rawList = []
    }
  }
  return rawList.map((opt, idx) => ({
    id: String(opt?.k ?? opt?.key ?? opt?.id ?? idx),
    label: String(opt?.v ?? opt?.value ?? opt?.name ?? `选项${idx + 1}`),
  }))
}

function normalizeConfig(data: any): Group[] {
  const list = Array.isArray(data) ? data : Array.isArray(data?.list) ? data.list : []
  if (!list.length) return getFallbackGroups()

  const groupMap = new Map<string, Group>()
  list.forEach((item: any, idx: number) => {
    const groupKey = String(item?.groupKey ?? `group_${idx}`)
    const groupName = String(item?.groupName ?? `分组${idx + 1}`)
    const groupSort = Number(item?.sortNum ?? idx)
    const fieldKey = String(item?.fieldKey ?? `${groupKey}_field_${idx}`)
    const options = parseOptionsJson(item?.optionsJson)
    if (!options.length) return

    const field: Field = {
      fieldKey,
      fieldName: String(item?.fieldName ?? fieldKey),
      groupKey,
      groupName,
      sortNum: Number(item?.sortNum ?? idx),
      isRequired: Number(item?.isRequired ?? 0) === 1,
      multiple: Number(item?.multiSelect ?? 0) === 1,
      options,
    }

    if (!groupMap.has(groupKey)) {
      groupMap.set(groupKey, {
        key: groupKey,
        title: groupName,
        sortNum: groupSort,
        fields: [field],
      })
    } else {
      groupMap.get(groupKey)!.fields.push(field)
    }
  })

  const groupsBySort = Array.from(groupMap.values())
    .map((group) => ({
      ...group,
      fields: group.fields.sort((a, b) => a.sortNum - b.sortNum),
    }))
    .sort((a, b) => a.sortNum - b.sortNum)

  return groupsBySort.length ? groupsBySort : getFallbackGroups()
}

function collectSelectedKeys(profileData: any): Record<string, Set<string>> {
  const map: Record<string, Set<string>> = {}
  if (!profileData || typeof profileData !== 'object') return map

  const normalizeValues = (val: unknown): string[] => {
    if (Array.isArray(val)) return val.map((v) => String(v))
    if (val == null || val === '') return []
    // 兼容后端返回 "a,b,c" 形式
    if (typeof val === 'string' && val.includes(',')) {
      return val.split(',').map((v) => v.trim()).filter(Boolean)
    }
    return [String(val)]
  }

  Object.keys(profileData).forEach((key) => {
    map[key] = new Set(normalizeValues(profileData[key]))
  })
  return map
}

function initSelectionByGroups(profileData: any) {
  const selectedFromServer = collectSelectedKeys(profileData)
  const nextMap: SelectedMap = {}
  groups.value.forEach((group) => {
    group.fields.forEach((field) => {
      const matched =
        selectedFromServer[field.fieldKey] ||
        selectedFromServer[field.fieldName] ||
        selectedFromServer[field.fieldKey.toLowerCase()]
      if (matched && matched.size > 0) {
        nextMap[field.fieldKey] = field.options
          .map((o) => o.id)
          .filter((id) => matched.has(id) || matched.has(String(id)))
      } else {
        nextMap[field.fieldKey] = []
      }
    })
  })
  selectedMap.value = nextMap
}

function toggleOption(field: Field, optionId: string) {
  const arr = selectedMap.value[field.fieldKey] || []
  const idx = arr.indexOf(optionId)
  if (field.multiple) {
    if (idx >= 0) arr.splice(idx, 1)
    else arr.push(optionId)
  } else {
    selectedMap.value[field.fieldKey] = idx >= 0 ? [] : [optionId]
    return
  }
  selectedMap.value[field.fieldKey] = [...arr]
}

function isSelected(groupKey: string, optionId: string) {
  return (selectedMap.value[groupKey] || []).includes(optionId)
}

function buildSavePayload() {
  const fields: ProfileMap = {}
  groups.value.forEach((group) => {
    group.fields.forEach((field) => {
      const values = selectedMap.value[field.fieldKey] || []
      if (!values.length) return
      fields[field.fieldKey] = field.multiple ? values : values[0]
    })
  })
  return { fields }
}

async function loadData() {
  loading.value = true
  try {
    const [configRes, profileRes] = await Promise.all([
      appDiningProfileConfigGet({}),
      appDiningProfileGet({}),
    ])
    groups.value = normalizeConfig(configRes?.data)
    initSelectionByGroups(profileRes?.data)
  } catch (e) {
    groups.value = getFallbackGroups()
    initSelectionByGroups({})
  } finally {
    loading.value = false
  }
}

async function handleComplete() {
  try {
    const body = buildSavePayload()
    await appDiningProfileSavePost({ body })
    uni.setStorageSync(PREF_DATA_KEY, selectedMap.value)
    uni.setStorageSync(PREF_FLAG_KEY, true)
    uni.redirectTo({
      url: '/pages/ai/chat/index',
    })
  } catch (e) {
    // 保存失败时沿用项目全局错误提示
  }
}

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

<template>
  <view class="page">
    <navbar :title="t('navbar-ai-diet-preference')">
    </navbar>
    <view class="header">
      <view class="header-title" style="display: flex; align-items: center;">
        <image src="/static/app/images/ai-diet-preference-title.png" class="w-44rpx h-44rpx ml-8rpx shrink-0"></image>
        <text class="title">{{ t('pages.ai.dietPreference.title') }}</text>
      </view>
      <text class="sub">{{ t('pages.ai.dietPreference.sub') }}</text>
    </view>

    <view  style="padding: 22rpx;">

    <view v-if="loading" class="section">
      <view class="section-title">{{ t('pages.ai.dietPreference.loadingConfig') }}</view>
    </view>

    <view v-else-if="!hasGroups" class="section">
      <view class="section-title">{{ t('pages.ai.dietPreference.empty') }}</view>
    </view>

    <template v-else>
      <view class="section" v-for="group in groups" :key="group.key">
        <view class="section-title">{{ group.title }}</view>
        <view class="field-block" v-for="field in group.fields" :key="field.fieldKey">
          <view class="field-title">
            <text>{{ field.fieldName }}</text>
            <text v-if="field.isRequired" class="required">*</text>
            <text class="mode-tag">{{ field.multiple ? t('pages.ai.dietPreference.multi') : t('pages.ai.dietPreference.single') }}</text>
          </view>
          <view class="chips">
            <view
              v-for="opt in field.options"
              :key="opt.id"
              class="chip"
              :class="isSelected(field.fieldKey, opt.id) ? 'chip--active' : ''"
              @click="toggleOption(field, opt.id)"
            >
              <text>{{ opt.label }}</text>
            </view>
          </view>
        </view>
      </view>
    </template>

    <view class="footer">
      <button class="btn" @click="handleComplete">
        {{ t('pages.ai.dietPreference.submit') }}
      </button>
    </view>
  </view>
  </view>
</template>

<style scoped lang="scss">
.page {
  background: #f2f2f2;
  min-height: 100vh;
  // padding: 24rpx;
}

.header {
  background: #EFFDF5;
  // border-radius: 20rpx;
  padding: 22rpx 22rpx;
  box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
}

.title {
  font-size: 28rpx;
  font-weight: 500;
  color: #065E46;
  display: block;
  margin-left: 12rpx;
}

.sub {
  display: block;
  margin-top: 12rpx;
  font-size: 24rpx;
  color: #027857;
  line-height: 1.4;
}

.section {
  margin-top: 22rpx;
  background: #fff;
  border-radius: 20rpx;
  padding: 22rpx;
}

.section-title {
  font-size: 28rpx;
  font-weight: 600;
  color: #111;
  margin-bottom: 16rpx;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 16rpx;
}

.field-block + .field-block {
  margin-top: 20rpx;
}

.field-title {
  margin-bottom: 14rpx;
  display: flex;
  align-items: center;
  gap: 8rpx;
  font-size: 24rpx;
  color: #333;
}

.required {
  color: #e23636;
}

.mode-tag {
  color: #999;
  font-size: 22rpx;
}

.chip {
  padding: 14rpx 18rpx;
  border-radius: 999rpx;
  background: #f6f6f6;
  color: #333;
  font-size: 24rpx;
  line-height: 1;
}

.chip--active {
  background: #14181b;
  color: #fff;
}

.footer {
  margin-top: 28rpx;
  background: transparent;
}

.btn {
  width: 100%;
  border-radius: 16rpx;
  background: #14181b;
  color: #fff;
  font-size: 28rpx;
  padding: 18rpx 0;
}

.tip {
  margin-top: 16rpx;
  font-size: 22rpx;
  color: #999;
  text-align: center;
}

.nav-action {
  font-size: 24rpx;
  color: #14181b;
  padding: 8rpx 0 8rpx 16rpx;
}
</style>

