import { bodyTestMock } from './mockData.js'

function clone(value) {
    return JSON.parse(JSON.stringify(value))
}

function formatRecordTime(date) {
    const y = date.getFullYear()
    const m = String(date.getMonth() + 1).padStart(2, '0')
    const d = String(date.getDate()).padStart(2, '0')
    const h = String(date.getHours()).padStart(2, '0')
    const min = String(date.getMinutes()).padStart(2, '0')
    return `${y}-${m}-${d}  ${h}:${min}`
}

function formatIsoDate(date) {
    const y = date.getFullYear()
    const m = String(date.getMonth() + 1).padStart(2, '0')
    const d = String(date.getDate()).padStart(2, '0')
    return `${y}-${m}-${d}`
}

function formatTime(date) {
    const h = String(date.getHours()).padStart(2, '0')
    const min = String(date.getMinutes()).padStart(2, '0')
    return `${h}:${min}`
}

export function getDefaultBodyTestState() {
    return {
        settings: { ...bodyTestMock.settings },
        device: { ...bodyTestMock.device },
        records: clone(bodyTestMock.records)
    }
}

export function mergeBodyTestState(saved) {
    const defaults = getDefaultBodyTestState()
    if (!saved) return defaults
    return {
        settings: { ...defaults.settings, ...(saved.settings || {}) },
        device: { ...defaults.device, ...(saved.device || {}) },
        records: saved.records?.length ? saved.records : defaults.records
    }
}

export function getLatestBodyTestRecord(store) {
    const records = store.bodyTest?.records || []
    return records.length ? { ...records[0] } : null
}

export function getBodyTestRecordById(store, id) {
    const numId = Number(id)
    const record = (store.bodyTest?.records || []).find((item) => item.id === numId)
    return record ? { ...record } : null
}

export function getBodyTestHistory(store, year) {
    let list = (store.bodyTest?.records || []).map((item) => ({ ...item }))
    if (year && year !== 'all') {
        list = list.filter((r) => r.date.startsWith(String(year)))
    }
    return list
}

export function getBodyTestChangeBadge(record, previous) {
    if (!previous?.metrics || !record?.metrics) return null
    const diff = Math.round((record.metrics.bodyFat - previous.metrics.bodyFat) * 10) / 10
    if (diff === 0) return null
    const sign = diff > 0 ? '+' : ''
    return { key: 'bodyFat', text: `体脂率${sign}${diff}%`, good: diff < 0 }
}

export function getBodyTestYears(store) {
    const years = new Set((store.bodyTest?.records || []).map((r) => r.date.slice(0, 4)))
    return ['all', ...Array.from(years).sort().reverse()]
}

export function computeGrade(score) {
    if (score >= 90) return { grade: 'A', gradeLabel: '优秀' }
    if (score >= 80) return { grade: 'B+', gradeLabel: '良好' }
    if (score >= 70) return { grade: 'B', gradeLabel: '中等' }
    if (score >= 60) return { grade: 'C', gradeLabel: '一般' }
    return { grade: 'D', gradeLabel: '需改善' }
}

export function computeScore(metrics) {
    const bmi = metrics.bmi || 22
    const bodyFat = metrics.bodyFat || 25
    const muscle = metrics.muscleMass || 22
    const bmiScore = bmi >= 18.5 && bmi <= 24 ? 90 : bmi >= 17 && bmi <= 27 ? 75 : 60
    const fatScore = bodyFat <= 22 ? 92 : bodyFat <= 26 ? 80 : bodyFat <= 30 ? 68 : 55
    const muscleScore = muscle >= 22 ? 88 : muscle >= 20 ? 76 : 62
    return Math.round((bmiScore + fatScore + muscleScore) / 3)
}

export function computeChanges(current, previous) {
    if (!previous?.metrics) return {}
    const keys = ['weight', 'bmi', 'bodyFat', 'muscleMass', 'visceralFat', 'bmr', 'bodyWater', 'boneMass']
    const changes = {}
    keys.forEach((key) => {
        const cur = Number(current.metrics[key])
        const prev = Number(previous.metrics[key])
        if (Number.isFinite(cur) && Number.isFinite(prev)) {
            const diff = Math.round((cur - prev) * 10) / 10
            changes[key] = diff
        }
    })
    return changes
}

export function formatChangeValue(key, diff, unitSystem = 'metric') {
    if (diff === undefined || diff === null) return '--'
    const sign = diff > 0 ? '+' : ''
    const units = {
        weight: unitSystem === 'metric' ? 'kg' : 'lb',
        bodyFat: '%',
        muscleMass: 'kg',
        bmi: '',
        visceralFat: '级',
        bmr: 'kcal',
        bodyWater: '%',
        boneMass: 'kg'
    }
    const unit = units[key] || ''
    return `${sign}${diff}${unit}`
}

export function buildBodyReportSummary(record, previous) {
    if (!record) {
        return {
            date: '--',
            weight: '--',
            bmi: '--',
            bodyFat: '--',
            bmr: '--',
            status: '暂无数据',
            change: '--'
        }
    }
    const changes = computeChanges(record, previous)
    const weightChange = changes.weight
    let changeText = '--'
    if (weightChange !== undefined) {
        const sign = weightChange > 0 ? '+' : ''
        changeText = `${sign}${weightChange}kg`
    }
    return {
        date: record.date,
        weight: String(record.metrics.weight),
        bmi: String(record.metrics.bmi),
        bodyFat: `${record.metrics.bodyFat}%`,
        bmr: String(record.metrics.bmr),
        status: record.status,
        change: changeText,
        recordId: record.id
    }
}

export function getBodyTestTrendData(store, metricKey, limit = 6) {
    const records = [...(store.bodyTest?.records || [])].reverse().slice(-limit)
    return records.map((item) => ({
        id: item.id,
        date: item.date,
        label: item.date.slice(5),
        value: Number(item.metrics[metricKey]) || 0
    }))
}

export function getCompareData(store, idA, idB) {
    const a = getBodyTestRecordById(store, idA)
    const b = getBodyTestRecordById(store, idB)
    if (!a || !b) return null
    const keys = ['weight', 'bmi', 'bodyFat', 'muscleMass', 'visceralFat', 'bmr']
    const metrics = keys.map((key) => ({
        key,
        label: bodyTestMock.metricDefs.find((m) => m.key === key)?.label || key,
        valueA: a.metrics[key],
        valueB: b.metrics[key],
        diff: Math.round((a.metrics[key] - b.metrics[key]) * 10) / 10
    }))
    return { recordA: a, recordB: b, metrics }
}

export function getRecommendedCourses(record) {
    const ids = record?.recommendedCourseIds || []
    return bodyTestMock.recommendedCourses.filter((c) => ids.includes(c.id))
}

export function updateBodyTestSettings(store, patch) {
    store.bodyTest.settings = { ...store.bodyTest.settings, ...patch }
    return store
}

export function connectBodyTestDevice(store) {
    store.bodyTest.device = {
        ...store.bodyTest.device,
        connected: true,
        battery: Math.min(100, (store.bodyTest.device.battery || 80) + Math.floor(Math.random() * 5)),
        lastConnected: formatRecordTime(new Date())
    }
    return store
}

export function disconnectBodyTestDevice(store) {
    store.bodyTest.device = { ...store.bodyTest.device, connected: false }
    return store
}

function nextRecordId(records) {
    return (records || []).reduce((max, item) => Math.max(max, item.id || 0), 0) + 1
}

/** 模拟一次完整体测并写入记录 */
export function saveSimulatedBodyTestRecord(store, finalMetrics) {
    const now = new Date()
    const previous = getLatestBodyTestRecord(store)
    const metrics = { ...finalMetrics }
    const heightCm = Number(store.profile?.height) || 165
    const heightM = heightCm / 100
    metrics.bmi = Math.round((metrics.weight / (heightM * heightM)) * 10) / 10

    const score = computeScore(metrics)
    const { grade, gradeLabel } = computeGrade(score)
    const status = score >= 80 ? '比较健康' : score >= 70 ? '需关注' : '建议改善'

    const radar = {
        weight: Math.min(95, Math.round(score * 0.9 + Math.random() * 5)),
        bodyFat: Math.min(95, Math.round(100 - metrics.bodyFat * 2.5)),
        muscle: Math.min(95, Math.round(metrics.muscleMass * 3.2)),
        bone: Math.min(95, Math.round(metrics.boneMass * 32)),
        water: Math.min(95, Math.round(metrics.bodyWater * 1.4)),
        bmr: Math.min(95, Math.round(metrics.bmr / 16))
    }

    const record = {
        id: nextRecordId(store.bodyTest.records),
        date: formatIsoDate(now),
        time: formatTime(now),
        score,
        grade,
        gradeLabel,
        status,
        metrics,
        radar,
        bodySegments: clone(bodyTestMock.records[0].bodySegments),
        advice: clone(bodyTestMock.records[0].advice),
        recommendedCourseIds: [1, 2]
    }

    if (previous) {
        record.changes = computeChanges(record, previous)
    }

    store.bodyTest.records.unshift(record)
    store.bodyReport = buildBodyReportSummary(record, previous)
    return record
}

/** 测量过程实时数据插值 */
export function interpolateMeasuringMetrics(progress, profile) {
    const baseWeight = Number(profile?.weight) || 64
    const target = {
        weight: baseWeight - 0.3 + Math.random() * 0.2,
        bodyFat: 24.5 + Math.random() * 0.8,
        muscleMass: 22.4 + Math.random() * 0.3,
        visceralFat: 6,
        bmr: 1380 + Math.floor(Math.random() * 20),
        bodyWater: 52.5 + Math.random(),
        boneMass: 2.4,
        protein: 16.2
    }
    const ratio = Math.min(1, progress / 100)
    return {
        weight: Math.round((baseWeight + (target.weight - baseWeight) * ratio) * 10) / 10,
        bodyFat: Math.round((26 + (target.bodyFat - 26) * ratio) * 10) / 10,
        muscleMass: Math.round((21.5 + (target.muscleMass - 21.5) * ratio) * 10) / 10,
        bmr: Math.round(1340 + (target.bmr - 1340) * ratio),
        bodyWater: Math.round((51 + (target.bodyWater - 51) * ratio) * 10) / 10
    }
}

export { bodyTestMock }
