<template>
  <div class="transaction-screen">
    <div class="screen-backdrop"></div>

    <header class="screen-header">
      <div class="screen-heading">
        <div class="screen-title">交易综合分析大屏</div>
        <div class="screen-subtitle">账户交易、POS刷卡、信用卡账单、分期贷款与地点消费综合洞察</div>
      </div>
      <div class="screen-actions">
        <el-select v-model="queryParams.type" class="filter-type" popper-class="analysis-screen-popper" @change="handleTimeTypeChange">
          <el-option label="按日" value="1" />
          <el-option label="按月" value="2" />
          <el-option label="按年" value="3" />
        </el-select>
        <el-date-picker
          v-if="queryParams.type === '1'"
          v-model="queryParams.time"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          value-format="YYYY-MM-DD"
          class="filter-date"
          popper-class="analysis-screen-popper"
        />
        <el-date-picker
          v-else-if="queryParams.type === '2'"
          v-model="queryParams.time"
          type="monthrange"
          range-separator="至"
          start-placeholder="开始月份"
          end-placeholder="结束月份"
          value-format="YYYY-MM"
          class="filter-date"
          popper-class="analysis-screen-popper"
        />
        <template v-else>
          <el-date-picker
            v-model="queryParams.time[0]"
            type="year"
            placeholder="开始年份"
            value-format="YYYY"
            class="filter-year"
            popper-class="analysis-screen-popper"
          />
          <span class="range-split">至</span>
          <el-date-picker
            v-model="queryParams.time[1]"
            type="year"
            placeholder="结束年份"
            value-format="YYYY"
            class="filter-year"
            popper-class="analysis-screen-popper"
          />
        </template>
        <div class="screen-action-group">
          <el-button type="primary" icon="Search" :loading="loading" class="screen-btn screen-btn-primary" @click="loadDashboard">查询</el-button>
          <el-button icon="Refresh" class="screen-btn screen-btn-plain" @click="resetQuery">重置</el-button>
        </div>
      </div>
    </header>

    <main class="screen-main">
      <section class="metric-grid">
        <div v-for="item in topMetrics" :key="item.key" class="metric-card">
          <span>{{ item.label }}</span>
          <strong :class="item.className">{{ item.value }}</strong>
          <em>{{ item.remark }}</em>
        </div>
      </section>

      <section class="insight-grid">
        <div class="panel panel-span-2">
          <div class="panel-head">
            <span>收支趋势</span>
            <em>{{ rangeText }}</em>
          </div>
          <div id="transactionTrendChart" class="chart chart-large"></div>
        </div>
        <div class="panel">
          <div class="panel-head">
            <span>支出结构</span>
            <em>日常 / 手续费 / 分期 / 贷款</em>
          </div>
          <div id="expenseStructureChart" class="chart"></div>
        </div>
        <div class="panel">
          <div class="panel-head">
            <span>风险压力</span>
            <em>信用卡 / 分期 / 贷款</em>
          </div>
          <div id="riskRadarChart" class="chart"></div>
        </div>
      </section>

      <section class="analysis-grid">
        <div class="panel daily-rank-panel">
          <div class="panel-head">
            <span>日常消费子类排行</span>
            <em class="rank-total">{{ formatMoney(dailyExpenseTotal) }}</em>
          </div>
          <div class="rank-list">
            <div v-for="(item, index) in dailyExpenseRanks" :key="item.name" class="rank-row" :style="{ '--rank-width': `${item.percent}%` }">
              <span class="rank-index">{{ index + 1 }}</span>
              <span class="rank-name">{{ item.name }}</span>
              <strong>{{ formatMoney(item.value) }}</strong>
              <i></i>
            </div>
            <el-empty v-if="!dailyExpenseRanks.length" description="暂无日常消费数据" :image-size="70" />
          </div>
        </div>

        <div class="panel">
          <div class="panel-head">
            <span>POS刷卡分析</span>
            <em>{{ posSummary.count || 0 }}笔</em>
          </div>
          <div id="posTrendChart" class="chart chart-small"></div>
          <div class="mini-stats">
            <div>
              <span>刷卡金额</span>
              <strong>{{ formatMoney(posSummary.amount) }}</strong>
            </div>
            <div>
              <span>手续费</span>
              <strong>{{ formatMoney(posSummary.commission) }}</strong>
            </div>
            <div>
              <span>入账金额</span>
              <strong>{{ formatMoney(posSummary.actualAmount) }}</strong>
            </div>
          </div>
        </div>

        <div class="panel">
          <div class="panel-head">
            <span>信用卡消费统计</span>
            <em>账单与额度</em>
          </div>
          <div id="creditBillChart" class="chart chart-small"></div>
          <div class="mini-stats">
            <div>
              <span>累计账单</span>
              <strong>{{ formatMoney(creditSummary.actualCreditBill) }}</strong>
            </div>
            <div>
              <span>月均账单</span>
              <strong>{{ formatMoney(creditSummary.averageCreditBill) }}</strong>
            </div>
            <div>
              <span>使用率</span>
              <strong>{{ formatPercent(creditSummary.creditBillRate) }}</strong>
            </div>
          </div>
        </div>

        <div class="panel">
          <div class="panel-head">
            <span>分期与贷款待还</span>
            <em>未来6个月计划</em>
          </div>
          <div id="repaymentChart" class="chart chart-small"></div>
          <div class="dual-summary">
            <div>
              <span>信用卡分期待还</span>
              <strong>{{ formatMoney(installmentSummary.leftDetail) }}</strong>
              <em>未结清 {{ installmentSummary.unclearedDetailCount || 0 }}笔</em>
            </div>
            <div>
              <span>贷款待还</span>
              <strong>{{ formatMoney(loanSummary.leftDetail) }}</strong>
              <em>未结清 {{ loanSummary.unclearedDetailCount || 0 }}笔</em>
            </div>
          </div>
        </div>
      </section>

      <section class="bottom-grid">
        <div class="panel">
          <div class="panel-head">
            <span>地点消费热点</span>
            <em>{{ locationOverview.locationCount || 0 }}个地点</em>
          </div>
          <div class="location-list">
            <div v-for="(item, index) in locationRanks" :key="item.locationKey" class="location-row">
              <span>{{ String(index + 1).padStart(2, '0') }}</span>
              <div>
                <strong>{{ item.locationName || '未命名地点' }}</strong>
                <em>{{ item.locationAddress || formatCoordinate(item) }}</em>
              </div>
              <b>{{ formatMoney(item.totalAmount) }}</b>
            </div>
            <el-empty v-if="!locationRanks.length" description="暂无地点消费数据" :image-size="70" />
          </div>
        </div>

        <div class="panel">
          <div class="panel-head">
            <span>综合洞察</span>
            <em>基于当前筛选周期</em>
          </div>
          <div class="insight-list">
            <div v-for="item in insightItems" :key="item.title" class="insight-row">
              <span>{{ item.title }}</span>
              <strong>{{ item.value }}</strong>
              <em>{{ item.desc }}</em>
            </div>
          </div>
        </div>

        <div class="panel">
          <div class="panel-head">
            <span>重点明细</span>
            <em>账单 / POS / 还款</em>
          </div>
          <div class="event-list">
            <div v-for="item in eventItems" :key="`${item.type}-${item.time}-${item.value}`" class="event-row">
              <span :class="`event-tag event-${item.type}`">{{ item.label }}</span>
              <strong>{{ item.time }}</strong>
              <em>{{ item.name }}</em>
              <b>{{ item.value }}</b>
            </div>
            <el-empty v-if="!eventItems.length" description="暂无重点明细" :image-size="70" />
          </div>
        </div>
      </section>

      <section class="decision-grid">
        <div class="panel">
          <div class="panel-head">
            <span>智能洞察结论</span>
            <em>{{ conclusionItems.length }}条自动结论</em>
          </div>
          <div class="conclusion-list">
            <div v-for="item in conclusionItems" :key="item.title" :class="['conclusion-card', `level-${item.level}`]">
              <span>{{ item.type }}</span>
              <strong>{{ item.title }}</strong>
              <em>{{ item.desc }}</em>
            </div>
          </div>
        </div>

        <div class="panel">
          <div class="panel-head">
            <span>交易风险提醒</span>
            <em>{{ alertItems.length }}条提醒</em>
          </div>
          <div class="forecast-grid">
            <div>
              <span>预计周期总支出</span>
              <strong>{{ formatMoney(forecastExpense) }}</strong>
              <em>{{ forecastDesc }}</em>
            </div>
            <div>
              <span>现金流状态</span>
              <strong :class="netBalance < 0 ? 'value-warning' : 'value-cyan'">{{ formatMoney(netBalance) }}</strong>
              <em>收入 {{ formatMoney(totalIncome) }} / 支出 {{ formatMoney(totalOutcome) }}</em>
            </div>
          </div>
          <div class="alert-list">
            <div v-for="item in alertItems" :key="item.title" :class="['alert-row', `alert-${item.level}`]">
              <span>{{ item.title }}</span>
              <strong>{{ item.value }}</strong>
              <em>{{ item.desc }}</em>
            </div>
            <el-empty v-if="!alertItems.length" description="暂无风险提醒" :image-size="70" />
          </div>
        </div>
      </section>
    </main>

    <div v-if="loading" class="screen-loading">
      <el-icon class="is-loading"><Loading /></el-icon>
      <span>正在汇总交易数据</span>
    </div>
  </div>
</template>

<script setup name="TransactionAnalysisScreen">
import dayjs from 'dayjs'
import * as echarts from 'echarts'
import {
  getAcccountsOutInAnalysis,
  getDailyExpensesAnalysis,
  getPosAnalysis,
  getCreditAnalysis,
  getInstallmentHistoryAnalysis,
  getAccountDealLocationOverview,
  getAccountDealLocationPoints
} from '@/api/invest/statisticAnalysis'

const loading = ref(false)
const queryParams = ref(getDefaultQueryParams())

const outInSummary = ref({})
const dailySummary = ref({})
const posSummary = ref({})
const creditSummary = ref({})
const installmentSummary = ref({})
const loanSummary = ref({})
const locationOverview = ref({})
const locationPoints = ref([])
const trendData = ref([])
const dailyTrendData = ref([])
const posTrendData = ref([])
const creditBillData = ref([])
const installmentPlanData = ref([])
const loanPlanData = ref([])

let trendChart = null
let expenseStructureChart = null
let riskRadarChart = null
let posTrendChart = null
let creditBillChart = null
let repaymentChart = null

const rangeText = computed(() => {
  const time = queryParams.value.time || []
  if (time.length !== 2) return '全部周期'
  return `${time[0]} 至 ${time[1]}`
})

const totalIncome = computed(() => toNumber(outInSummary.value.salaryIncome) + toNumber(outInSummary.value.investIncome))
const totalOutcome = computed(() => toNumber(outInSummary.value.totalOutcome))
const netBalance = computed(() => toNumber(outInSummary.value.balance))
const dailyExpenseTotal = computed(() => toNumber(dailySummary.value.dailyExpenses))
const financeCost = computed(
  () => toNumber(outInSummary.value.posExpenses) + toNumber(outInSummary.value.creditInterest) + toNumber(outInSummary.value.onLineInterest)
)
const repaymentPressure = computed(() => toNumber(installmentSummary.value.leftDetail) + toNumber(loanSummary.value.leftDetail))
const topLocation = computed(() => locationPoints.value[0] || null)
const selectedPeriodCount = computed(() => {
  const [start, end] = queryParams.value.time || []
  if (!start || !end) return Math.max(trendData.value.length, dailyTrendData.value.length, posTrendData.value.length, creditBillData.value.length, 1)
  if (queryParams.value.type === '1') return Math.max(dayjs(end).diff(dayjs(start), 'day') + 1, 1)
  if (queryParams.value.type === '2') return Math.max(dayjs(`${end}-01`).diff(dayjs(`${start}-01`), 'month') + 1, 1)
  return Math.max(Number(end) - Number(start) + 1, 1)
})
const elapsedPeriodRate = computed(() => {
  const time = queryParams.value.time || []
  if (queryParams.value.type === '2' && time[1] === dayjs().format('YYYY-MM')) {
    return Math.min(1, Math.max(0.03, dayjs().date() / dayjs().daysInMonth()))
  }
  if (queryParams.value.type === '3' && time[1] === dayjs().format('YYYY')) {
    const yearStart = dayjs().startOf('year')
    const yearDays = dayjs().endOf('year').diff(yearStart, 'day') + 1
    return Math.min(1, Math.max(0.03, (dayjs().diff(yearStart, 'day') + 1) / yearDays))
  }
  return 1
})
const currentPeriodExpense = computed(() => {
  const currentDailyExpense = getLatestTrendValue(dailyTrendData.value)
  if (currentDailyExpense > 0 && dailyExpenseTotal.value > 0) {
    return Math.min(totalOutcome.value, currentDailyExpense * (totalOutcome.value / dailyExpenseTotal.value))
  }
  return selectedPeriodCount.value ? totalOutcome.value / selectedPeriodCount.value : totalOutcome.value
})
const forecastExpense = computed(() => {
  if (elapsedPeriodRate.value < 1) {
    const historicalExpense = Math.max(0, totalOutcome.value - currentPeriodExpense.value)
    const currentForecast = currentPeriodExpense.value / elapsedPeriodRate.value
    return Math.max(totalOutcome.value, historicalExpense + currentForecast)
  }
  return totalOutcome.value
})
const forecastDesc = computed(() => {
  if (elapsedPeriodRate.value < 1) return queryParams.value.type === '3' ? '当前年按已过天数外推' : '当前月按已过天数外推'
  return `按 ${selectedPeriodCount.value} 个统计周期汇总`
})

const topMetrics = computed(() => [
  {
    key: 'income',
    label: '收入合计',
    value: formatMoney(totalIncome.value),
    remark: `工资 ${formatMoney(outInSummary.value.salaryIncome)} / 投资 ${formatMoney(outInSummary.value.investIncome)}`,
    className: 'value-income'
  },
  {
    key: 'outcome',
    label: '支出合计',
    value: formatMoney(totalOutcome.value),
    remark: `日常 ${formatMoney(dailyExpenseTotal.value)} / 非日常 ${formatMoney(outInSummary.value.notDailyExpenses)}`,
    className: 'value-expense'
  },
  {
    key: 'balance',
    label: '收支差额',
    value: formatMoney(netBalance.value),
    remark: netBalance.value >= 0 ? '当前周期净流入' : '当前周期净流出',
    className: netBalance.value >= 0 ? 'value-income' : 'value-warning'
  },
  {
    key: 'pos',
    label: 'POS刷卡',
    value: formatMoney(posSummary.value.amount),
    remark: `${posSummary.value.count || 0}笔，手续费 ${formatMoney(posSummary.value.commission)}`,
    className: 'value-cyan'
  },
  {
    key: 'credit',
    label: '信用卡账单',
    value: formatMoney(creditSummary.value.actualCreditBill),
    remark: `月均 ${formatMoney(creditSummary.value.averageCreditBill)}，使用率 ${formatPercent(creditSummary.value.creditBillRate)}`,
    className: 'value-blue'
  },
  {
    key: 'repayment',
    label: '待还压力',
    value: formatMoney(repaymentPressure.value),
    remark: `分期 ${formatMoney(installmentSummary.value.leftDetail)} / 贷款 ${formatMoney(loanSummary.value.leftDetail)}`,
    className: 'value-warning'
  },
  {
    key: 'location',
    label: '定位消费',
    value: formatMoney(locationOverview.value.totalAmount),
    remark: `${locationOverview.value.locationCount || 0}个地点 / ${locationOverview.value.dealCount || 0}笔`,
    className: 'value-cyan'
  },
  {
    key: 'financeCost',
    label: '资金成本',
    value: formatMoney(financeCost.value),
    remark: `POS费 ${formatMoney(outInSummary.value.posExpenses)} / 分期息 ${formatMoney(outInSummary.value.creditInterest)} / 贷款息 ${formatMoney(
      outInSummary.value.onLineInterest
    )}`,
    className: 'value-expense'
  }
])

const dailyExpenseRanks = computed(() => {
  const rows = normalizeSeries(dailySummary.value.accountsList, 'time', 'value').sort((first, second) => second.value - first.value)
  const maxValue = Math.max(...rows.map((item) => item.value), 0)
  return rows.slice(0, 6).map((item) => ({
    name: item.name,
    value: item.value,
    percent: maxValue ? Math.max(6, (item.value / maxValue) * 100) : 0
  }))
})

const locationRanks = computed(() => locationPoints.value.slice(0, 8))

const insightItems = computed(() => {
  const avgDailyExpense = dailyTrendData.value.length ? dailyExpenseTotal.value / dailyTrendData.value.length : 0
  const posFeeRate = toNumber(posSummary.value.amount) ? (toNumber(posSummary.value.commission) / toNumber(posSummary.value.amount)) * 100 : 0
  const topDaily = dailyExpenseRanks.value[0]
  return [
    {
      title: '日均消费',
      value: formatMoney(avgDailyExpense),
      desc: `按 ${dailyTrendData.value.length || 0} 个统计点计算`
    },
    {
      title: '最高消费子类',
      value: topDaily ? topDaily.name : '--',
      desc: topDaily ? formatMoney(topDaily.value) : '暂无日常支出'
    },
    {
      title: 'POS费率',
      value: formatPercent(posFeeRate),
      desc: `刷卡 ${formatMoney(posSummary.value.amount)}，手续费 ${formatMoney(posSummary.value.commission)}`
    },
    {
      title: '热点地点',
      value: topLocation.value?.locationName || '--',
      desc: topLocation.value ? `${formatMoney(topLocation.value.totalAmount)} / ${topLocation.value.dealCount || 0}笔` : '暂无定位交易'
    },
    {
      title: '分期贷款压力',
      value: formatMoney(repaymentPressure.value),
      desc: `待还占支出 ${formatPercent(totalOutcome.value ? (repaymentPressure.value / totalOutcome.value) * 100 : 0)}`
    }
  ]
})

const eventItems = computed(() => {
  const creditEvents = normalizeSeries(creditSummary.value.tableCreditBillList || creditBillData.value, 'time', 'value')
    .slice(0, 4)
    .map((item) => ({ type: 'credit', label: '账单', time: item.name, name: '信用卡账单', value: formatMoney(item.value) }))
  const posEvents = normalizeSeries(posSummary.value.tablePosList || posTrendData.value, 'time', 'value')
    .slice(0, 4)
    .map((item) => ({ type: 'pos', label: 'POS', time: item.name, name: '刷卡消费', value: formatMoney(item.value) }))
  const repayEvents = normalizeSeries(
    [...(installmentSummary.value.tableHistoryDetailList || []), ...(loanSummary.value.tableHistoryDetailList || [])],
    'time',
    'value'
  )
    .slice(0, 4)
    .map((item) => ({ type: 'repay', label: '还款', time: item.name, name: '分期/贷款待还', value: formatMoney(item.value) }))
  return [...creditEvents, ...posEvents, ...repayEvents].sort((first, second) => String(second.time).localeCompare(String(first.time))).slice(0, 10)
})

const conclusionItems = computed(() => {
  const items = []
  const topDaily = dailyExpenseRanks.value[0]
  const topDailyRatio = dailyExpenseTotal.value && topDaily ? (topDaily.value / dailyExpenseTotal.value) * 100 : 0
  const posFeeRate = toNumber(posSummary.value.amount) ? (toNumber(posSummary.value.commission) / toNumber(posSummary.value.amount)) * 100 : 0
  const repaymentRatio = totalOutcome.value ? (repaymentPressure.value / totalOutcome.value) * 100 : 0
  const financeCostRatio = totalOutcome.value ? (financeCost.value / totalOutcome.value) * 100 : 0
  const locationRatio = totalOutcome.value ? (toNumber(locationOverview.value.totalAmount) / totalOutcome.value) * 100 : 0
  const creditUsage = toNumber(creditSummary.value.creditBillRate)

  items.push({
    type: netBalance.value >= 0 ? '现金流' : '现金流预警',
    level: netBalance.value >= 0 ? 'good' : 'danger',
    title: netBalance.value >= 0 ? '当前周期保持净流入' : '当前周期出现净流出',
    desc: `收入 ${formatMoney(totalIncome.value)}，支出 ${formatMoney(totalOutcome.value)}，差额 ${formatMoney(netBalance.value)}。`
  })

  if (topDaily) {
    items.push({
      type: '消费结构',
      level: topDailyRatio >= 35 ? 'warning' : 'info',
      title: `${topDaily.name} 是当前最高消费子类`,
      desc: `消费 ${formatMoney(topDaily.value)}，占日常消费 ${formatPercent(topDailyRatio)}。`
    })
  }

  items.push({
    type: '信用卡',
    level: creditUsage >= 80 ? 'warning' : 'info',
    title: `信用卡使用率 ${formatPercent(creditUsage)}`,
    desc: `累计账单 ${formatMoney(creditSummary.value.actualCreditBill)}，月均 ${formatMoney(creditSummary.value.averageCreditBill)}。`
  })

  items.push({
    type: 'POS刷卡',
    level: posFeeRate >= 0.8 ? 'warning' : 'info',
    title: `POS刷卡费率约 ${formatPercent(posFeeRate)}`,
    desc: `刷卡 ${formatMoney(posSummary.value.amount)}，手续费 ${formatMoney(posSummary.value.commission)}，入账 ${formatMoney(
      posSummary.value.actualAmount
    )}。`
  })

  items.push({
    type: '分期贷款',
    level: repaymentRatio >= 50 ? 'danger' : repaymentRatio >= 25 ? 'warning' : 'info',
    title: `待还压力占支出 ${formatPercent(repaymentRatio)}`,
    desc: `分期待还 ${formatMoney(installmentSummary.value.leftDetail)}，贷款待还 ${formatMoney(loanSummary.value.leftDetail)}。`
  })

  items.push({
    type: '资金成本',
    level: financeCostRatio >= 10 ? 'warning' : 'info',
    title: `资金成本占支出 ${formatPercent(financeCostRatio)}`,
    desc: `POS费、分期利息、贷款利息合计 ${formatMoney(financeCost.value)}。`
  })

  if (topLocation.value) {
    items.push({
      type: '地点消费',
      level: locationRatio >= 60 ? 'warning' : 'info',
      title: `${topLocation.value.locationName || '未命名地点'} 是热点消费地点`,
      desc: `定位消费 ${formatMoney(locationOverview.value.totalAmount)}，占总支出 ${formatPercent(locationRatio)}。`
    })
  }

  return items.slice(0, 8)
})

const alertItems = computed(() => {
  const items = []
  const creditRate = toNumber(creditSummary.value.creditBillRate)
  const repaymentRatio = totalOutcome.value ? (repaymentPressure.value / totalOutcome.value) * 100 : 0
  const financeRate = totalOutcome.value ? (financeCost.value / totalOutcome.value) * 100 : 0
  const dailyRate = totalOutcome.value ? (dailyExpenseTotal.value / totalOutcome.value) * 100 : 0

  if (netBalance.value < 0) {
    items.push({
      title: '当前周期现金流为负',
      value: formatMoney(netBalance.value),
      desc: `收入 ${formatMoney(totalIncome.value)}，支出 ${formatMoney(totalOutcome.value)}。`,
      level: 'danger'
    })
  }

  if (dailyRate >= 70) {
    items.push({
      title: '日常消费占比较高',
      value: formatPercent(dailyRate),
      desc: `日常消费 ${formatMoney(dailyExpenseTotal.value)}，总支出 ${formatMoney(totalOutcome.value)}。`,
      level: 'warning'
    })
  }

  if (financeRate >= 10) {
    items.push({
      title: '资金成本偏高',
      value: formatPercent(financeRate),
      desc: `POS费、分期利息、贷款利息合计 ${formatMoney(financeCost.value)}。`,
      level: 'warning'
    })
  }

  if (repaymentRatio >= 50) {
    items.push({
      title: '待还压力偏高',
      value: formatMoney(repaymentPressure.value),
      desc: `待还占当前周期支出 ${formatPercent(repaymentRatio)}，建议关注近期现金流。`,
      level: repaymentRatio >= 80 ? 'danger' : 'warning'
    })
  }

  if (creditRate >= 80) {
    items.push({
      title: '信用卡使用率偏高',
      value: formatPercent(creditRate),
      desc: `累计账单 ${formatMoney(creditSummary.value.actualCreditBill)}，注意账单集中还款压力。`,
      level: 'warning'
    })
  }

  if (!items.length && totalOutcome.value > 0) {
    items.push({
      title: '交易风险平稳',
      value: formatMoney(totalOutcome.value),
      desc: '当前周期现金流、资金成本和待还压力未触发明显风险。',
      level: 'good'
    })
  }

  return items
})

function getQueryRange() {
  const [start, end] = queryParams.value.time || []
  return {
    type: queryParams.value.type,
    startTime: start || '',
    endTime: end || ''
  }
}

function getLocationQueryRange() {
  const { type, startTime, endTime } = getQueryRange()
  if (type === '2') {
    const nowMonth = dayjs().format('YYYY-MM')
    return {
      startTime: `${startTime}-01`,
      endTime: endTime === nowMonth ? dayjs().format('YYYY-MM-DD') : dayjs(`${endTime}-01`).endOf('month').format('YYYY-MM-DD')
    }
  }
  if (type === '3') {
    const nowYear = dayjs().format('YYYY')
    return {
      startTime: `${startTime}-01-01`,
      endTime: endTime === nowYear ? dayjs().format('YYYY-MM-DD') : `${endTime}-12-31`
    }
  }
  return { startTime, endTime }
}

function getRepaymentQueryRange() {
  const now = dayjs()
  return {
    type: '2',
    startTime: now.format('YYYY-MM'),
    endTime: now.add(5, 'month').format('YYYY-MM')
  }
}

function handleTimeTypeChange(type) {
  const now = dayjs()
  if (type === '1') {
    queryParams.value.time = [now.subtract(30, 'day').format('YYYY-MM-DD'), now.format('YYYY-MM-DD')]
  } else if (type === '2') {
    queryParams.value.time = [now.subtract(11, 'month').format('YYYY-MM'), now.format('YYYY-MM')]
  } else {
    queryParams.value.time = [now.subtract(4, 'year').format('YYYY'), now.format('YYYY')]
  }
}

function resetQuery() {
  queryParams.value = getDefaultQueryParams()
  loadDashboard()
}

function getDefaultQueryParams() {
  const now = dayjs()
  return {
    type: '1',
    time: [now.subtract(30, 'day').format('YYYY-MM-DD'), now.format('YYYY-MM-DD')]
  }
}

async function loadDashboard() {
  loading.value = true
  try {
    const range = getQueryRange()
    const locationRange = getLocationQueryRange()
    const repaymentRange = getRepaymentQueryRange()
    const [outInRes, dailyRes, posRes, creditRes, installmentRes, loanRes, locationOverviewRes, locationPointsRes] = await Promise.all([
      getAcccountsOutInAnalysis({ ...range }),
      getDailyExpensesAnalysis({ ...range }),
      getPosAnalysis({ ...range }),
      getCreditAnalysis({
        type: queryParams.value.type === '1' ? 2 : queryParams.value.type,
        startTime: normalizeCreditStart(range),
        endTime: normalizeCreditEnd(range)
      }),
      getInstallmentHistoryAnalysis({ ...repaymentRange, dataType: '2' }),
      getInstallmentHistoryAnalysis({ ...repaymentRange, dataType: '3' }),
      getAccountDealLocationOverview({ ...locationRange, dealType: '2' }),
      getAccountDealLocationPoints({ ...locationRange, dealType: '2' })
    ])

    outInSummary.value = outInRes.data || {}
    dailySummary.value = dailyRes.data || {}
    posSummary.value = posRes.data || {}
    creditSummary.value = creditRes.data || {}
    installmentSummary.value = installmentRes.data || {}
    loanSummary.value = loanRes.data || {}
    locationOverview.value = locationOverviewRes.data || {}
    locationPoints.value = locationPointsRes.data || []

    trendData.value = sortSeriesByTime(normalizeSeries(outInSummary.value.acccountsList, 'time', 'value'))
    dailyTrendData.value = sortSeriesByTime(normalizeSeries(dailySummary.value.acccountsDateList, 'time', 'value'))
    posTrendData.value = sortSeriesByTime(normalizeSeries(posSummary.value.posList, 'time', 'value'))
    creditBillData.value = sortSeriesByTime(normalizeSeries(creditSummary.value.creditBillList, 'time', 'value'))
    installmentPlanData.value = sortSeriesByTime(normalizeSeries(installmentSummary.value.historyDetailList, 'time', 'value'))
    loanPlanData.value = sortSeriesByTime(normalizeSeries(loanSummary.value.historyDetailList, 'time', 'value'))

    await nextTick()
    renderCharts()
  } finally {
    loading.value = false
  }
}

function normalizeCreditStart(range) {
  if (range.type === '1') return dayjs(range.startTime).format('YYYY-MM')
  return range.startTime
}

function normalizeCreditEnd(range) {
  if (range.type === '1') return dayjs(range.endTime).format('YYYY-MM')
  return range.endTime
}

function normalizeSeries(list, nameKey = 'time', valueKey = 'value') {
  if (!Array.isArray(list)) return []
  return list
    .filter((item) => item)
    .map((item) => ({
      name: item[nameKey] ?? item.time ?? item.remark ?? '--',
      value: toNumber(item[valueKey] ?? item.amount ?? item.totalAmount ?? 0),
      raw: item
    }))
}

function sortSeriesByTime(list) {
  return [...list].sort((first, second) => getSeriesTimeValue(first.name) - getSeriesTimeValue(second.name))
}

function getSeriesTimeValue(value) {
  const date = dayjs(String(value))
  if (date.isValid()) return date.valueOf()
  const number = Number(value)
  return Number.isFinite(number) ? number : 0
}

function getLatestTrendValue(list) {
  if (!Array.isArray(list) || !list.length) return 0
  return toNumber(list[list.length - 1]?.value)
}

function toNumber(value) {
  const number = Number(value || 0)
  return Number.isFinite(number) ? number : 0
}

function formatMoney(value) {
  return toNumber(value).toLocaleString('zh-CN', {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  })
}

function formatPercent(value) {
  const number = toNumber(value)
  return `${number.toFixed(number >= 10 ? 0 : 1)}%`
}

function formatCoordinate(point) {
  const longitude = Number(point?.longitude)
  const latitude = Number(point?.latitude)
  if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) return '暂无地址'
  return `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`
}

function getChart(id, current) {
  const el = document.getElementById(id)
  if (!el) return null
  if (!current) return echarts.init(el)
  return current
}

function renderCharts() {
  renderTrendChart()
  renderExpenseStructureChart()
  renderRiskRadarChart()
  renderPosTrendChart()
  renderCreditBillChart()
  renderRepaymentChart()
}

function baseChartOption() {
  return {
    backgroundColor: 'transparent',
    textStyle: {
      color: 'rgba(226, 232, 240, 0.76)',
      fontFamily: 'Microsoft YaHei, Arial, sans-serif'
    },
    tooltip: {
      trigger: 'axis',
      backgroundColor: 'rgba(3, 15, 28, 0.94)',
      borderColor: 'rgba(103, 232, 249, 0.28)',
      textStyle: { color: '#e0faff' }
    },
    grid: {
      left: 34,
      right: 18,
      top: 34,
      bottom: 26,
      containLabel: true
    }
  }
}

function renderTrendChart() {
  trendChart = getChart('transactionTrendChart', trendChart)
  if (!trendChart) return
  const allTimes = Array.from(new Set([...trendData.value.map((item) => item.name), ...dailyTrendData.value.map((item) => item.name)]))
  const trendMap = new Map(trendData.value.map((item) => [item.name, item.value]))
  const dailyMap = new Map(dailyTrendData.value.map((item) => [item.name, item.value]))
  trendChart.setOption({
    ...baseChartOption(),
    legend: {
      top: 2,
      right: 12,
      textStyle: { color: 'rgba(226, 232, 240, 0.68)' },
      data: ['收支差额', '日常支出']
    },
    xAxis: {
      type: 'category',
      data: allTimes,
      axisLine: { lineStyle: { color: 'rgba(125, 211, 252, 0.22)' } },
      axisLabel: { color: 'rgba(226, 232, 240, 0.62)' }
    },
    yAxis: {
      type: 'value',
      axisLabel: { color: 'rgba(226, 232, 240, 0.62)' },
      splitLine: { lineStyle: { color: 'rgba(148, 163, 184, 0.12)' } }
    },
    series: [
      {
        name: '收支差额',
        type: 'line',
        smooth: true,
        symbolSize: 6,
        data: allTimes.map((time) => trendMap.get(time) || 0),
        lineStyle: { width: 3, color: '#67e8f9' },
        itemStyle: { color: '#67e8f9' },
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: 'rgba(103, 232, 249, 0.28)' },
            { offset: 1, color: 'rgba(103, 232, 249, 0.02)' }
          ])
        }
      },
      {
        name: '日常支出',
        type: 'bar',
        barMaxWidth: 18,
        data: allTimes.map((time) => dailyMap.get(time) || 0),
        itemStyle: { color: '#2dd4bf', borderRadius: [4, 4, 0, 0] }
      }
    ]
  })
}

function renderExpenseStructureChart() {
  expenseStructureChart = getChart('expenseStructureChart', expenseStructureChart)
  if (!expenseStructureChart) return
  const data = [
    { name: '日常支出', value: dailyExpenseTotal.value },
    { name: 'POS手续费', value: toNumber(outInSummary.value.posExpenses) },
    { name: '分期利息', value: toNumber(outInSummary.value.creditInterest) },
    { name: '贷款利息', value: toNumber(outInSummary.value.onLineInterest) },
    { name: '其他支出', value: Math.max(0, totalOutcome.value - dailyExpenseTotal.value - financeCost.value) }
  ].filter((item) => item.value > 0)
  expenseStructureChart.setOption({
    backgroundColor: 'transparent',
    tooltip: {
      trigger: 'item',
      backgroundColor: 'rgba(3, 15, 28, 0.94)',
      borderColor: 'rgba(103, 232, 249, 0.28)',
      textStyle: { color: '#e0faff' }
    },
    color: ['#67e8f9', '#2dd4bf', '#facc15', '#fb7185', '#a78bfa'],
    series: [
      {
        type: 'pie',
        radius: ['52%', '72%'],
        center: ['50%', '50%'],
        avoidLabelOverlap: true,
        label: { color: 'rgba(226, 232, 240, 0.72)', formatter: '{b}\n{d}%' },
        labelLine: { lineStyle: { color: 'rgba(226, 232, 240, 0.26)' } },
        data
      }
    ]
  })
}

function renderRiskRadarChart() {
  riskRadarChart = getChart('riskRadarChart', riskRadarChart)
  if (!riskRadarChart) return
  const creditRate = toNumber(creditSummary.value.creditBillRate)
  const installmentRate = totalOutcome.value ? (toNumber(installmentSummary.value.leftDetail) / totalOutcome.value) * 100 : 0
  const loanRate = totalOutcome.value ? (toNumber(loanSummary.value.leftDetail) / totalOutcome.value) * 100 : 0
  const feeRate = totalOutcome.value ? (financeCost.value / totalOutcome.value) * 100 : 0
  riskRadarChart.setOption({
    backgroundColor: 'transparent',
    tooltip: {
      backgroundColor: 'rgba(3, 15, 28, 0.94)',
      borderColor: 'rgba(103, 232, 249, 0.28)',
      textStyle: { color: '#e0faff' }
    },
    radar: {
      radius: '66%',
      center: ['50%', '55%'],
      indicator: [
        { name: '信用卡使用率', max: 100 },
        { name: '分期压力', max: 100 },
        { name: '贷款压力', max: 100 },
        { name: '资金成本', max: 100 },
        { name: '支出强度', max: 100 }
      ],
      axisName: { color: 'rgba(226, 232, 240, 0.72)' },
      splitLine: { lineStyle: { color: 'rgba(125, 211, 252, 0.18)' } },
      splitArea: { areaStyle: { color: ['rgba(14, 165, 233, 0.04)', 'rgba(45, 212, 191, 0.03)'] } },
      axisLine: { lineStyle: { color: 'rgba(125, 211, 252, 0.18)' } }
    },
    series: [
      {
        type: 'radar',
        data: [
          {
            value: [creditRate, installmentRate, loanRate, feeRate, Math.min(100, (totalOutcome.value / Math.max(totalIncome.value, 1)) * 100)],
            name: '压力指数',
            areaStyle: { color: 'rgba(103, 232, 249, 0.22)' },
            lineStyle: { color: '#67e8f9', width: 2 },
            itemStyle: { color: '#67e8f9' }
          }
        ]
      }
    ]
  })
}

function renderPosTrendChart() {
  posTrendChart = getChart('posTrendChart', posTrendChart)
  if (!posTrendChart) return
  posTrendChart.setOption({
    ...baseChartOption(),
    xAxis: {
      type: 'category',
      data: posTrendData.value.map((item) => item.name),
      axisLabel: { color: 'rgba(226, 232, 240, 0.56)' },
      axisLine: { lineStyle: { color: 'rgba(125, 211, 252, 0.16)' } }
    },
    yAxis: {
      type: 'value',
      axisLabel: { color: 'rgba(226, 232, 240, 0.56)' },
      splitLine: { lineStyle: { color: 'rgba(148, 163, 184, 0.1)' } }
    },
    series: [
      {
        name: 'POS刷卡',
        type: 'bar',
        barMaxWidth: 18,
        data: posTrendData.value.map((item) => item.value),
        itemStyle: { color: '#67e8f9', borderRadius: [4, 4, 0, 0] }
      }
    ]
  })
}

function renderCreditBillChart() {
  creditBillChart = getChart('creditBillChart', creditBillChart)
  if (!creditBillChart) return
  creditBillChart.setOption({
    ...baseChartOption(),
    xAxis: {
      type: 'category',
      data: creditBillData.value.map((item) => item.name),
      axisLabel: { color: 'rgba(226, 232, 240, 0.56)' },
      axisLine: { lineStyle: { color: 'rgba(125, 211, 252, 0.16)' } }
    },
    yAxis: {
      type: 'value',
      axisLabel: { color: 'rgba(226, 232, 240, 0.56)' },
      splitLine: { lineStyle: { color: 'rgba(148, 163, 184, 0.1)' } }
    },
    series: [
      {
        name: '信用卡账单',
        type: 'line',
        smooth: true,
        data: creditBillData.value.map((item) => item.value),
        lineStyle: { width: 3, color: '#a78bfa' },
        itemStyle: { color: '#a78bfa' },
        areaStyle: { color: 'rgba(167, 139, 250, 0.18)' }
      }
    ]
  })
}

function renderRepaymentChart() {
  repaymentChart = getChart('repaymentChart', repaymentChart)
  if (!repaymentChart) return
  const allTimes = Array.from(new Set([...installmentPlanData.value.map((item) => item.name), ...loanPlanData.value.map((item) => item.name)])).sort(
    (first, second) => getSeriesTimeValue(first) - getSeriesTimeValue(second)
  )
  const installmentMap = new Map(installmentPlanData.value.map((item) => [item.name, item.value]))
  const loanMap = new Map(loanPlanData.value.map((item) => [item.name, item.value]))
  repaymentChart.setOption({
    ...baseChartOption(),
    legend: {
      top: 2,
      right: 12,
      textStyle: { color: 'rgba(226, 232, 240, 0.68)' },
      data: ['信用卡分期', '贷款']
    },
    xAxis: {
      type: 'category',
      data: allTimes,
      axisLabel: { color: 'rgba(226, 232, 240, 0.56)' },
      axisLine: { lineStyle: { color: 'rgba(125, 211, 252, 0.16)' } }
    },
    yAxis: {
      type: 'value',
      axisLabel: { color: 'rgba(226, 232, 240, 0.56)' },
      splitLine: { lineStyle: { color: 'rgba(148, 163, 184, 0.1)' } }
    },
    series: [
      {
        name: '信用卡分期',
        type: 'bar',
        stack: 'repayment',
        barMaxWidth: 20,
        data: allTimes.map((time) => installmentMap.get(time) || 0),
        itemStyle: { color: '#facc15', borderRadius: [4, 4, 0, 0] }
      },
      {
        name: '贷款',
        type: 'bar',
        stack: 'repayment',
        barMaxWidth: 20,
        data: allTimes.map((time) => loanMap.get(time) || 0),
        itemStyle: { color: '#fb7185', borderRadius: [4, 4, 0, 0] }
      }
    ]
  })
}

function resizeCharts() {
  ;[trendChart, expenseStructureChart, riskRadarChart, posTrendChart, creditBillChart, repaymentChart].forEach((chart) => chart?.resize())
}

onMounted(() => {
  loadDashboard()
  window.addEventListener('resize', resizeCharts)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeCharts)
  ;[trendChart, expenseStructureChart, riskRadarChart, posTrendChart, creditBillChart, repaymentChart].forEach((chart) => chart?.dispose())
})
</script>

<style lang="scss" scoped>
.transaction-screen {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  box-sizing: border-box;
  color: #f8fafc;
  background: #030a13;
  scrollbar-gutter: stable;
}

.screen-backdrop {
  position: fixed;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(14, 165, 233, 0.08) 1px, transparent 1px), linear-gradient(180deg, rgba(14, 165, 233, 0.07) 1px, transparent 1px),
    linear-gradient(120deg, rgba(14, 165, 233, 0.14), transparent 42%), linear-gradient(250deg, rgba(20, 184, 166, 0.12), transparent 48%), #030a13;
  background-size: 44px 44px, 44px 44px, auto, auto, auto;
}

.screen-header,
.screen-main,
.screen-loading {
  position: relative;
  z-index: 1;
}

.screen-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 20px;
  background: rgba(3, 15, 28, 0.86);
  border-bottom: 1px solid rgba(125, 211, 252, 0.22);
  backdrop-filter: blur(10px);
}

.screen-title {
  font-size: 27px;
  font-weight: 800;
  letter-spacing: 0;
}

.screen-subtitle {
  margin-top: 6px;
  color: rgba(186, 230, 253, 0.64);
  font-size: 13px;
}

.screen-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
}

.filter-type {
  width: 94px;
}

.filter-date {
  width: 260px;
}

.filter-year {
  width: 128px;
}

.range-split {
  display: inline-flex;
  align-items: center;
  height: 34px;
  color: rgba(186, 230, 253, 0.68);
  font-size: 12px;
}

.screen-actions :deep(.el-input__wrapper),
.screen-actions :deep(.el-select__wrapper) {
  min-height: 34px;
  color: #dff7ff;
  background: rgba(3, 15, 28, 0.68);
  border: 1px solid rgba(103, 232, 249, 0.32);
  border-radius: 4px;
  box-shadow: inset 0 0 18px rgba(14, 165, 233, 0.12);
}

.screen-actions :deep(.el-input__inner),
.screen-actions :deep(.el-range-input),
.screen-actions :deep(.el-select__selected-item),
.screen-actions :deep(.el-range-separator) {
  color: #e0faff;
}

.screen-action-group {
  display: inline-flex;
  gap: 8px;
  white-space: nowrap;
}

.screen-action-group :deep(.el-button + .el-button) {
  margin-left: 0;
}

.screen-btn {
  height: 34px;
  min-width: 72px;
  padding: 0 14px;
  color: #dff7ff;
  font-weight: 700;
  background: rgba(3, 15, 28, 0.66);
  border: 1px solid rgba(103, 232, 249, 0.34);
  border-radius: 4px;
  box-shadow: inset 0 0 14px rgba(14, 165, 233, 0.16);
}

.screen-btn-primary {
  color: #06121e;
  background: linear-gradient(135deg, #67e8f9 0%, #2dd4bf 100%);
  border-color: rgba(103, 232, 249, 0.86);
}

.screen-main {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 18px 18px;
}

.metric-grid {
  display: grid;
  grid-template-columns: repeat(8, minmax(132px, 1fr));
  gap: 8px;
}

.metric-card,
.panel {
  background: linear-gradient(145deg, rgba(8, 20, 32, 0.9), rgba(8, 47, 73, 0.66));
  border: 1px solid rgba(125, 211, 252, 0.18);
  border-radius: 6px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.28), inset 0 0 26px rgba(14, 165, 233, 0.08);
  backdrop-filter: blur(8px);
}

.metric-card {
  min-width: 0;
  min-height: 82px;
  padding: 10px 12px;
}

.metric-card span,
.metric-card em {
  display: block;
  color: rgba(186, 230, 253, 0.62);
  font-size: 12px;
  line-height: 1.3;
  overflow-wrap: anywhere;
  white-space: normal;
}

.metric-card strong {
  display: block;
  margin-top: 7px;
  font-size: 20px;
  line-height: 1.1;
  overflow-wrap: anywhere;
  white-space: normal;
}

.metric-card em {
  margin-top: 8px;
  font-style: normal;
}

.value-income {
  color: #86efac;
}

.value-expense,
.value-warning {
  color: #fca5a5;
}

.value-cyan {
  color: #67e8f9;
}

.value-blue {
  color: #a5b4fc;
}

.insight-grid,
.analysis-grid,
.bottom-grid,
.decision-grid {
  display: grid;
  gap: 10px;
}

.insight-grid {
  grid-template-columns: 1.2fr 1.2fr 1fr 1fr;
}

.analysis-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.bottom-grid {
  grid-template-columns: 1.1fr 1fr 1.2fr;
}

.bottom-grid .panel {
  min-height: 236px;
}

.decision-grid {
  grid-template-columns: 1.4fr 0.9fr;
}

.panel {
  min-width: 0;
  min-height: 260px;
  padding: 12px;
}

.panel-span-2 {
  grid-column: span 2;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}

.panel-head span {
  color: #e0faff;
  font-size: 15px;
  font-weight: 800;
}

.panel-head em {
  color: rgba(186, 230, 253, 0.54);
  font-size: 12px;
  font-style: normal;
  overflow-wrap: anywhere;
  text-align: right;
  white-space: normal;
}

.panel-head .rank-total {
  color: #67e8f9;
  font-size: 16px;
  font-weight: 800;
  text-shadow: 0 0 14px rgba(103, 232, 249, 0.28);
}

.chart {
  width: 100%;
  height: 220px;
}

.chart-large {
  height: 226px;
}

.chart-small {
  height: 142px;
}

.rank-list,
.location-list,
.insight-list,
.event-list,
.conclusion-list,
.alert-list {
  min-height: 0;
}

.daily-rank-panel {
  min-height: 0;
}

.daily-rank-panel .rank-list {
  padding-right: 4px;
}

.rank-row {
  position: relative;
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  min-height: 34px;
  padding: 8px 9px;
  border: 1px solid rgba(125, 211, 252, 0.11);
  border-radius: 5px;
  background: rgba(3, 15, 28, 0.44);
}

.daily-rank-panel .rank-row {
  min-height: 28px;
  padding: 5px 9px;
}

.rank-row + .rank-row {
  margin-top: 7px;
}

.daily-rank-panel .rank-row + .rank-row {
  margin-top: 4px;
}

.rank-row i {
  position: absolute;
  left: 0;
  bottom: 0;
  width: var(--rank-width, 0%);
  height: 2px;
  background: linear-gradient(90deg, #67e8f9, #2dd4bf);
}

.rank-index {
  color: rgba(103, 232, 249, 0.86);
  font-weight: 800;
}

.rank-name,
.rank-row strong {
  font-size: 12px;
  overflow-wrap: anywhere;
  white-space: normal;
}

.rank-name {
  color: rgba(226, 232, 240, 0.78);
}

.rank-row strong {
  color: #e0faff;
}

.daily-rank-panel .rank-row strong {
  color: #e0faff;
  font-size: 13px;
  font-weight: 900;
  text-shadow: 0 0 12px rgba(103, 232, 249, 0.26);
}

.mini-stats,
.dual-summary {
  display: grid;
  gap: 8px;
}

.mini-stats {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 8px;
}

.dual-summary {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: 8px;
}

.mini-stats div,
.dual-summary div {
  min-width: 0;
  padding: 8px;
  background: rgba(3, 15, 28, 0.42);
  border: 1px solid rgba(125, 211, 252, 0.12);
  border-radius: 5px;
}

.mini-stats span,
.dual-summary span,
.dual-summary em {
  display: block;
  color: rgba(186, 230, 253, 0.58);
  font-size: 12px;
  overflow-wrap: anywhere;
  white-space: normal;
}

.mini-stats strong,
.dual-summary strong {
  display: block;
  margin-top: 5px;
  color: #e0faff;
  font-size: 15px;
  overflow-wrap: anywhere;
  white-space: normal;
}

.dual-summary em {
  margin-top: 5px;
  font-style: normal;
}

.location-list,
.event-list {
  padding-right: 0;
}

.location-row,
.insight-row,
.event-row,
.conclusion-card,
.alert-row {
  min-width: 0;
  border: 1px solid rgba(125, 211, 252, 0.11);
  border-radius: 5px;
  background: rgba(3, 15, 28, 0.42);
}

.location-row {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  gap: 9px;
  align-items: center;
  min-height: 46px;
  padding: 8px;
}

.location-row + .location-row,
.insight-row + .insight-row,
.event-row + .event-row {
  margin-top: 8px;
}

.location-row > span {
  color: rgba(103, 232, 249, 0.72);
  font-weight: 800;
}

.location-row div {
  min-width: 0;
}

.location-row strong,
.location-row em,
.location-row b {
  display: block;
  overflow-wrap: anywhere;
  white-space: normal;
}

.location-row strong {
  color: #f8fafc;
  font-size: 13px;
}

.location-row em {
  margin-top: 5px;
  color: rgba(226, 232, 240, 0.54);
  font-size: 12px;
  font-style: normal;
}

.location-row b {
  color: #67e8f9;
  font-size: 13px;
  text-align: right;
}

.insight-row {
  padding: 8px 10px;
}

.insight-row span,
.insight-row em {
  display: block;
  color: rgba(186, 230, 253, 0.58);
  font-size: 12px;
  overflow-wrap: anywhere;
  white-space: normal;
}

.insight-row strong {
  display: block;
  margin-top: 5px;
  color: #e0faff;
  font-size: 15px;
  overflow-wrap: anywhere;
  white-space: normal;
}

.insight-row em {
  margin-top: 6px;
  font-style: normal;
}

.event-row {
  display: grid;
  grid-template-columns: 46px 78px minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  min-height: 38px;
  padding: 7px 8px;
}

.event-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 23px;
  color: #06121e;
  font-size: 12px;
  font-weight: 800;
  border-radius: 4px;
}

.event-credit {
  background: #a78bfa;
}

.event-pos {
  background: #67e8f9;
}

.event-repay {
  background: #facc15;
}

.event-row strong,
.event-row em,
.event-row b {
  font-size: 12px;
  overflow-wrap: anywhere;
  white-space: normal;
}

.event-row strong {
  color: rgba(226, 232, 240, 0.72);
}

.event-row em {
  color: rgba(226, 232, 240, 0.58);
  font-style: normal;
}

.event-row b {
  color: #e0faff;
  text-align: right;
}

.conclusion-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.conclusion-card {
  position: relative;
  min-height: 82px;
  padding: 11px 12px 11px 14px;
}

.conclusion-card::before {
  position: absolute;
  left: 0;
  top: 10px;
  bottom: 10px;
  width: 3px;
  content: '';
  background: #67e8f9;
  border-radius: 0 99px 99px 0;
}

.conclusion-card.level-good::before {
  background: #86efac;
}

.conclusion-card.level-warning::before {
  background: #facc15;
}

.conclusion-card.level-danger::before {
  background: #fb7185;
}

.conclusion-card span,
.conclusion-card em {
  display: block;
  color: rgba(186, 230, 253, 0.58);
  font-size: 12px;
  line-height: 1.35;
  overflow-wrap: anywhere;
  white-space: normal;
}

.conclusion-card strong {
  display: block;
  margin-top: 6px;
  color: #e0faff;
  font-size: 15px;
  line-height: 1.35;
  overflow-wrap: anywhere;
  white-space: normal;
}

.conclusion-card em {
  margin-top: 7px;
  white-space: normal;
}

.forecast-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}

.forecast-grid div {
  min-width: 0;
  padding: 10px;
  background: rgba(3, 15, 28, 0.42);
  border: 1px solid rgba(125, 211, 252, 0.11);
  border-radius: 5px;
}

.forecast-grid span,
.forecast-grid em,
.alert-row span,
.alert-row em {
  display: block;
  color: rgba(186, 230, 253, 0.58);
  font-size: 12px;
  overflow-wrap: anywhere;
  white-space: normal;
}

.forecast-grid strong,
.alert-row strong {
  display: block;
  margin-top: 6px;
  color: #e0faff;
  font-size: 18px;
  overflow-wrap: anywhere;
  white-space: normal;
}

.forecast-grid em,
.alert-row em {
  margin-top: 6px;
  font-style: normal;
}

.alert-list {
  padding-right: 0;
}

.alert-row {
  position: relative;
  padding: 10px 11px 10px 14px;
}

.alert-row + .alert-row {
  margin-top: 8px;
}

.alert-row::before {
  position: absolute;
  left: 0;
  top: 9px;
  bottom: 9px;
  width: 3px;
  content: '';
  background: #67e8f9;
  border-radius: 0 99px 99px 0;
}

.alert-good::before {
  background: #86efac;
}

.alert-warning::before {
  background: #facc15;
}

.alert-danger::before {
  background: #fb7185;
}

.screen-loading {
  position: fixed;
  left: 50%;
  top: 50%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 18px;
  color: #e0f2fe;
  background: rgba(8, 20, 32, 0.9);
  border: 1px solid rgba(125, 211, 252, 0.38);
  border-radius: 6px;
  transform: translate(-50%, -50%);
}

:global(.analysis-screen-popper) {
  background: rgba(3, 15, 28, 0.96) !important;
  border: 1px solid rgba(103, 232, 249, 0.28) !important;
  border-radius: 6px !important;
}

:global(.analysis-screen-popper .el-popper__arrow::before) {
  background: rgba(3, 15, 28, 0.96) !important;
  border-color: rgba(103, 232, 249, 0.28) !important;
}

:global(.analysis-screen-popper .el-select-dropdown__item) {
  color: rgba(224, 250, 255, 0.82);
}

:global(.analysis-screen-popper .el-select-dropdown__item.hover),
:global(.analysis-screen-popper .el-select-dropdown__item:hover),
:global(.analysis-screen-popper .el-select-dropdown__item.selected) {
  color: #67e8f9;
  background: rgba(14, 165, 233, 0.18);
}

@media (max-width: 1500px) {
  .metric-grid {
    grid-template-columns: repeat(4, minmax(132px, 1fr));
  }

  .insight-grid,
  .analysis-grid,
  .bottom-grid,
  .decision-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .panel-span-2 {
    grid-column: span 2;
  }
}

@media (max-width: 980px) {
  .screen-header {
    align-items: flex-start;
    flex-direction: column;
  }

  .screen-actions {
    justify-content: flex-start;
  }

  .metric-grid,
  .insight-grid,
  .analysis-grid,
  .bottom-grid,
  .decision-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .panel-span-2 {
    grid-column: span 1;
  }

  .filter-date {
    width: min(100%, 260px);
  }

  .conclusion-list,
  .forecast-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
</style>
