import { computed, onMounted, ref } from 'vue' import { useRoute, useRouter } from 'vue-router' import type { GrowthReport, Profile } from '@yuxingu/types' import { asPlanets, ascLonFromChart, birthLabel, buildRelationSharePayload, chartBlock, chartPlanetsFromSummary, chartTip as chartTipFromCharts, labelList, mainTabs, overlayEntriesFrom, profileInitial, relationTypes, resolveActiveChartKey, sectionsFromDetail, type SynastryMainTab, } from '../lib/synastryChart' import { ensureAccount } from '../lib/authSession' import { createSynastryPageActions } from './synastryPageActions' export type MainTab = SynastryMainTab export { relationTypes, mainTabs, birthLabel, profileInitial } export function useSynastryPage() { const route = useRoute() const router = useRouter() const loading = ref(false) const adding = ref(false) const paying = ref(false) const inviting = ref(false) const nearbyLoading = ref(false) const error = ref('') const nearbyHint = ref('') const invitePath = ref('') const inviteHighlight = ref(false) const profiles = ref([]) const nearby = ref<{ profile: Profile; distance_km: number }[]>([]) const profileA = ref('') const profileB = ref('') const asOf = ref(new Date().toISOString().slice(0, 10)) const report = ref(null) const shareOpen = ref(false) const ty = ref('') const tm = ref('') const td = ref('') const tName = ref('TA') const mainTab = ref('compare') const subTab = ref<'natal' | 'prog'>('natal') const marksWho = ref<'me' | 'other'>('me') const relationType = ref('伴侣') const showClassicSelects = ref(false) const showQuickAdd = ref(false) const needsSubTab = computed(() => ['composite', 'davison', 'marks'].includes(mainTab.value)) const pickableProfiles = computed(() => profiles.value.filter((p) => p.relation === 'other' && p.id !== profileA.value), ) const selfProfiles = computed(() => profiles.value.filter((p) => p.relation === 'self')) const profileAName = computed(() => { const p = profiles.value.find((x) => x.id === profileA.value) return p?.display_name || '' }) const selfInitial = computed(() => (profileAName.value || '我').slice(0, 1)) const summary = computed(() => (report.value?.summary || {}) as Record) const detail = computed(() => (report.value?.detail || null) as Record | null) const charts = computed(() => (summary.value.charts || {}) as Record) const headline = computed(() => String(summary.value.headline || '')) const oneLiner = computed(() => String(summary.value.one_liner || '')) const love = computed(() => Number(summary.value.love_index || 0)) const friend = computed(() => Number(summary.value.friend_index || 0)) const marriage = computed(() => Number(summary.value.marriage_index || 0)) const loveNote = computed(() => String(summary.value.love_note || '')) const asOfLabel = computed(() => String(summary.value.as_of || asOf.value)) const planetsA = computed(() => chartPlanetsFromSummary(summary.value, 'chart_a')) const planetsB = computed(() => chartPlanetsFromSummary(summary.value, 'chart_b')) const ascA = computed(() => ascLonFromChart(summary.value.chart_a)) const ascB = computed(() => ascLonFromChart(summary.value.chart_b)) const aspectPreview = computed(() => labelList(summary.value.aspects_preview)) function chartTip(key: string): string { return chartTipFromCharts(charts.value, key) } const activeChartKey = computed(() => resolveActiveChartKey(mainTab.value, subTab.value, marksWho.value), ) const activePlanets = computed(() => asPlanets(chartBlock(charts.value, activeChartKey.value)?.planets)) const activeAsc = computed(() => { const lon = chartBlock(charts.value, activeChartKey.value)?.asc_lon return typeof lon === 'number' ? lon : null }) const activeAspectPreview = computed(() => labelList(chartBlock(charts.value, activeChartKey.value)?.aspects_preview), ) const activeChartTip = computed(() => chartTip(activeChartKey.value)) const overlayTip = computed(() => String(chartBlock(charts.value, 'overlay')?.tip || '')) const overlayEntries = computed(() => overlayEntriesFrom(charts.value)) const fullAspects = computed(() => labelList(detail.value?.aspects)) const sections = computed(() => sectionsFromDetail(detail.value)) const sharePayload = computed(() => buildRelationSharePayload( report.value, summary.value, headline.value, love.value, friend.value, marriage.value, ), ) const { loadProfiles, addTemp, generate, createInvite, loadNearby, buyDeep, reset } = createSynastryPageActions({ loading, adding, paying, inviting, nearbyLoading, error, nearbyHint, invitePath, profiles, nearby, profileA, profileB, asOf, report, ty, tm, td, tName, mainTab, showQuickAdd, }) onMounted(async () => { if (!(await ensureAccount(router, route.fullPath))) return await loadProfiles() if (route.query.invite === '1') { inviteHighlight.value = true if (profileA.value) { await createInvite() } else { error.value = '请先完成自己的档案,再邀请好友合盘' } void router.replace({ path: '/synastry', query: {} }) } }) return { loading, adding, paying, inviting, nearbyLoading, error, nearbyHint, invitePath, inviteHighlight, profiles, nearby, profileA, profileB, asOf, report, shareOpen, ty, tm, td, tName, mainTab, subTab, marksWho, relationType, showClassicSelects, showQuickAdd, needsSubTab, pickableProfiles, selfProfiles, profileAName, selfInitial, profileInitial, headline, oneLiner, love, friend, marriage, loveNote, asOfLabel, planetsA, planetsB, ascA, ascB, aspectPreview, chartTip, activePlanets, activeAsc, activeAspectPreview, activeChartTip, overlayTip, overlayEntries, fullAspects, sections, sharePayload, detail, birthLabel, addTemp, generate, createInvite, loadNearby, buyDeep, reset, } }