<template>
  <div class="finance-page">
    <div class="finance-shell">
      <div class="finance-topbar">
        <div class="period-tabs" aria-label="统计周期">
          <button
            v-for="item in periodOptions"
            :key="item.value"
            type="button"
            class="period-tab"
            :class="{ active: period === item.value }"
            @click="setPeriod(item.value)"
          >
            {{ item.label }}
          </button>
        </div>

        <div class="toolbar-actions">
          <el-input
            v-model="keyword"
            class="search-input"
            clearable
            placeholder="搜索名称 / 类型 / 错误"
          >
            <template #prefix>
              <Search :size="16" />
            </template>
          </el-input>
          <el-date-picker
            v-model="selectedDate"
            type="date"
            placeholder="选择日期"
            :disabled-date="disabledDate"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
            class="date-picker"
          />
          <el-button :loading="loading" class="icon-button" @click="loadData">
            <RefreshCw :size="16" />
            刷新
          </el-button>
          <el-button :disabled="!summary" class="icon-button" @click="exportCsv">
            <Download :size="16" />
            导出
          </el-button>
          <el-button
            v-if="period === 'day' && summary"
            :loading="comparing"
            type="primary"
            class="icon-button compare-button"
            @click="handleCompare"
          >
            <DatabaseZap :size="16" />
            重新统计比对
          </el-button>
        </div>
      </div>

      <el-alert v-if="fetchError" :title="fetchError" type="error" show-icon :closable="false" class="page-alert" />
      <el-alert
        v-if="summary?.partial"
        :title="partialTitle"
        type="warning"
        show-icon
        :closable="false"
        class="page-alert"
      />

      <el-skeleton v-if="loading && !summary" :rows="10" animated class="loading-panel" />

      <template v-if="summary">
        <div class="metrics-grid">
          <div class="metric-card">
            <div class="metric-head">
              <span>总收入</span>
              <span class="metric-icon income"><TrendingUp :size="18" /></span>
            </div>
            <strong>{{ formatAmount(summary.total_revenue) }}</strong>
            <small>{{ dateRangeLabel }}</small>
          </div>
          <div class="metric-card">
            <div class="metric-head">
              <span>总消费</span>
              <span class="metric-icon cost"><ReceiptText :size="18" /></span>
            </div>
            <strong>{{ formatAmount(summary.total_cost) }}</strong>
            <small>{{ summary.upstream_items.length }} 个上游源</small>
          </div>
          <div class="metric-card">
            <div class="metric-head">
              <span>净收入</span>
              <span class="metric-icon net"><WalletCards :size="18" /></span>
            </div>
            <strong :class="summary.net_income >= 0 ? 'positive' : 'negative'">
              {{ formatAmount(summary.net_income) }}
            </strong>
            <small>毛利率 {{ formatPercent(summary.margin_percent) }}</small>
          </div>
          <div class="metric-card">
            <div class="metric-head">
              <span>{{ summary.partial ? '部分汇总' : '失败项' }}</span>
              <span class="metric-icon risk"><BadgeAlert :size="18" /></span>
            </div>
            <strong :class="summary.failed_count > 0 || summary.partial ? 'negative' : ''">
              {{ summary.failed_count }}
            </strong>
            <small>{{ summary.partial ? `缺失 ${summary.missing_dates.length} 天快照` : failureText }}</small>
          </div>
        </div>

        <div class="chart-grid">
          <section class="dashboard-panel trend-panel">
            <div class="panel-header">
              <div>
                <h2>收入 / 消费趋势</h2>
                <p>{{ trendCaption }}</p>
              </div>
              <span class="panel-chip">{{ summary.included_days }} 天已入库</span>
            </div>
            <div ref="trendChartRef" class="chart trend-chart" />
          </section>

          <section class="dashboard-panel share-panel">
            <div class="panel-header">
              <div>
                <h2>上游占比</h2>
                <p>按当前周期消费金额汇总</p>
              </div>
            </div>
            <div ref="shareChartRef" class="chart share-chart" />
          </section>
        </div>

        <section class="dashboard-panel detail-panel">
          <div class="panel-header detail-header">
            <div>
              <h2>收入 / 消费明细</h2>
              <p>{{ filteredWebsiteItems.length }} 个收入项，{{ filteredUpstreamItems.length }} 个消费项</p>
            </div>
            <div class="table-tabs">
              <button
                type="button"
                :class="{ active: activeTable === 'websites' }"
                @click="activeTable = 'websites'"
              >
                收入
              </button>
              <button
                type="button"
                :class="{ active: activeTable === 'upstreams' }"
                @click="activeTable = 'upstreams'"
              >
                消费
              </button>
            </div>
          </div>

          <div class="table-wrap">
            <el-table
              v-if="activeTable === 'websites'"
              :data="filteredWebsiteItems"
              class="finance-table"
              empty-text="暂无收入明细"
            >
              <el-table-column label="名称" prop="name" min-width="180" />
              <el-table-column label="收入" min-width="140" align="right">
                <template #default="{ row }">
                  <span class="amount income">{{ formatAmount(row.amount) }}</span>
                </template>
              </el-table-column>
              <el-table-column label="状态" width="100" align="center">
                <template #default="{ row }">
                  <el-tag :type="row.status === 'success' ? 'success' : 'danger'" size="small">
                    {{ row.status === 'success' ? '成功' : '失败' }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="错误信息" min-width="280">
                <template #default="{ row }">
                  <span v-if="row.error" class="error-text">{{ row.error }}</span>
                  <span v-else class="muted-text">-</span>
                </template>
              </el-table-column>
            </el-table>

            <el-table
              v-else
              :data="filteredUpstreamItems"
              class="finance-table"
              empty-text="暂无消费明细"
            >
              <el-table-column label="名称" prop="name" min-width="180" />
              <el-table-column label="类型" width="120" align="center">
                <template #default="{ row }">
                  <el-tag :type="upstreamTagType(row.upstream_type)" size="small">
                    {{ upstreamTypeLabel(row.upstream_type) }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="消费" min-width="140" align="right">
                <template #default="{ row }">
                  <span class="amount cost">{{ formatAmount(row.amount) }}</span>
                </template>
              </el-table-column>
              <el-table-column label="状态" width="100" align="center">
                <template #default="{ row }">
                  <el-tag :type="row.status === 'success' ? 'success' : 'danger'" size="small">
                    {{ row.status === 'success' ? '成功' : '失败' }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="错误信息" min-width="280">
                <template #default="{ row }">
                  <span v-if="row.error" class="error-text">{{ row.error }}</span>
                  <span v-else class="muted-text">-</span>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </section>
      </template>

      <el-empty v-else-if="!loading && !fetchError" description="暂无财务汇总数据" class="empty-state">
        <el-button type="primary" @click="loadData">加载数据</el-button>
      </el-empty>
    </div>

    <el-dialog
      v-model="compareDialogVisible"
      title="重新统计比对结果"
      width="760px"
      class="finance-compare-dialog"
      :close-on-click-modal="false"
    >
      <template v-if="compareResult">
        <el-alert
          v-if="!compareResult.has_difference"
          title="比对结果一致，与已存快照无差异"
          type="success"
          show-icon
          :closable="false"
          class="compare-alert"
        />
        <el-alert
          v-else
          title="发现差异，下方展示快照与实时统计的对比"
          type="warning"
          show-icon
          :closable="false"
          class="compare-alert"
        />

        <div class="compare-grid">
          <div class="compare-card">
            <h3>已存快照</h3>
            <div v-if="compareResult.stored" class="compare-stat">
              <span>收入 <strong>{{ formatAmount(compareResult.stored.total_revenue) }}</strong></span>
              <span>消费 <strong>{{ formatAmount(compareResult.stored.total_cost) }}</strong></span>
              <span>净收入 <strong>{{ formatAmount(compareResult.stored.net_income) }}</strong></span>
              <span>失败项 <strong>{{ compareResult.stored.failed_count }}</strong></span>
            </div>
            <div v-else class="compare-empty">无快照</div>
          </div>
          <div class="compare-card">
            <h3>实时统计</h3>
            <div class="compare-stat">
              <span>收入 <strong>{{ formatAmount(compareResult.current.total_revenue) }}</strong></span>
              <span>消费 <strong>{{ formatAmount(compareResult.current.total_cost) }}</strong></span>
              <span>净收入 <strong>{{ formatAmount(compareResult.current.net_income) }}</strong></span>
              <span>失败项 <strong>{{ compareResult.current.failed_count }}</strong></span>
            </div>
          </div>
        </div>

        <div v-if="compareResult.diff_items.length > 0" class="diff-section">
          <h3>变动明细（{{ compareResult.diff_items.length }} 项）</h3>
          <div class="table-wrap">
            <el-table :data="compareResult.diff_items" class="finance-table" size="small">
              <el-table-column label="名称" prop="name" min-width="120" />
              <el-table-column label="类型" width="80" align="center">
                <template #default="{ row }">
                  {{ row.side === 'website_items' ? '网站' : '上游' }}
                </template>
              </el-table-column>
              <el-table-column label="字段" width="80" align="center">
                <template #default="{ row }">
                  {{ diffFieldLabel(row) }}
                </template>
              </el-table-column>
              <el-table-column label="旧值" min-width="120" align="right">
                <template #default="{ row }">
                  <span class="diff-old">{{ formatDiffValue(row, 'old') }}</span>
                </template>
              </el-table-column>
              <el-table-column label="新值" min-width="120" align="right">
                <template #default="{ row }">
                  <span class="diff-new">{{ formatDiffValue(row, 'new') }}</span>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </div>
      </template>
      <template #footer>
        <el-button @click="compareDialogVisible = false">关闭</el-button>
        <el-button
          v-if="compareResult?.has_difference"
          type="primary"
          :loading="overwriting"
          @click="handleOverwrite"
        >
          确认覆盖快照
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { api } from '@/api'
import {
  BadgeAlert,
  DatabaseZap,
  Download,
  ReceiptText,
  RefreshCw,
  Search,
  TrendingUp,
  WalletCards,
} from 'lucide-vue-next'
import * as echarts from 'echarts/core'
import { LineChart, PieChart } from 'echarts/charts'
import { GridComponent, LegendComponent, TooltipComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'

echarts.use([LineChart, PieChart, GridComponent, LegendComponent, TooltipComponent, CanvasRenderer])

type Period = 'day' | 'week' | 'month'
type DiffField = 'amount' | 'status' | 'error'
type DiffSide = 'old' | 'new'

interface FinanceItem {
  id: number | string
  name: string
  upstream_type: string
  amount: number
  status: 'success' | 'failed'
  error: string | null
}

interface FinanceChart {
  labels: string[]
  revenue: number[]
  cost: number[]
}

interface FinanceSummary {
  period: Period
  date: string
  start_date: string
  end_date: string
  total_revenue: number
  total_cost: number
  net_income: number
  margin_percent: number
  website_items: FinanceItem[]
  upstream_items: FinanceItem[]
  failed_count: number
  success: boolean
  chart: FinanceChart
  missing_dates: string[]
  included_days: number
  partial: boolean
  computed_at?: string
  from_snapshot?: boolean
}

interface DiffItem {
  side: 'website_items' | 'upstream_items'
  id: number
  name: string
  upstream_type: string
  old_status: string | null
  new_status: string | null
  old_amount: number | null
  new_amount: number | null
  old_error: string | null
  new_error: string | null
}

interface CompareResponse {
  stored: FinanceSummary | null
  current: FinanceSummary
  has_difference: boolean
  diff_items: DiffItem[]
}

const periodOptions: Array<{ value: Period; label: string }> = [
  { value: 'day', label: '日' },
  { value: 'week', label: '周' },
  { value: 'month', label: '月' },
]

const period = ref<Period>('day')
const selectedDate = ref<string | null>(null)
const keyword = ref('')
const loading = ref(false)
const comparing = ref(false)
const overwriting = ref(false)
const fetchError = ref<string | null>(null)
const summary = ref<FinanceSummary | null>(null)
const activeTable = ref<'websites' | 'upstreams'>('websites')
const compareDialogVisible = ref(false)
const compareResult = ref<CompareResponse | null>(null)

const trendChartRef = ref<HTMLElement | null>(null)
const shareChartRef = ref<HTMLElement | null>(null)
let trendChart: echarts.ECharts | null = null
let shareChart: echarts.ECharts | null = null

const dateRangeLabel = computed(() => {
  if (!summary.value) return ''
  if (summary.value.start_date === summary.value.end_date) return summary.value.start_date
  return `${summary.value.start_date} 至 ${summary.value.end_date}`
})

const trendCaption = computed(() => {
  if (!summary.value) return ''
  if (period.value === 'day') return '近 7 天已入库日快照'
  return `${dateRangeLabel.value} 已入库快照`
})

const partialTitle = computed(() => {
  if (!summary.value?.partial) return ''
  const dates = summary.value.missing_dates.slice(0, 5).join('、')
  const more = summary.value.missing_dates.length > 5 ? ' 等' : ''
  return `部分汇总：缺失 ${summary.value.missing_dates.length} 天快照（${dates}${more}）`
})

const failureText = computed(() => {
  if (!summary.value) return ''
  return summary.value.failed_count > 0 ? '数据不完整，净收入仅供参考' : '全部统计成功'
})

const normalizedKeyword = computed(() => keyword.value.trim().toLowerCase())

const filteredWebsiteItems = computed(() => filterItems(summary.value?.website_items ?? []))
const filteredUpstreamItems = computed(() => filterItems(summary.value?.upstream_items ?? []))

function setPeriod(nextPeriod: Period) {
  if (period.value === nextPeriod) return
  period.value = nextPeriod
  compareDialogVisible.value = false
  void loadData()
}

function disabledDate(d: Date) {
  const today = new Date()
  today.setHours(23, 59, 59, 999)
  return d > today
}

function filterItems(items: FinanceItem[]) {
  const q = normalizedKeyword.value
  if (!q) return items
  return items.filter(item => {
    return [
      item.name,
      item.upstream_type,
      upstreamTypeLabel(item.upstream_type),
      item.status === 'success' ? '成功' : '失败',
      item.error ?? '',
    ].some(value => value.toLowerCase().includes(q))
  })
}

function formatAmount(val: number): string {
  return '$' + Number(val || 0).toFixed(6)
}

function formatPercent(val: number): string {
  return `${Number(val || 0).toFixed(2)}%`
}

function upstreamTypeLabel(type: string): string {
  if (type === 'sub2api') return 'Sub2API'
  if (type === 'new_api') return 'New-API'
  return '未知'
}

function upstreamTagType(type: string): 'primary' | 'warning' | 'info' {
  if (type === 'sub2api') return 'primary'
  if (type === 'new_api') return 'warning'
  return 'info'
}

function buildParams(extra?: Record<string, string>) {
  const params = new URLSearchParams({ period: period.value, ...(extra ?? {}) })
  if (selectedDate.value) params.set('date', selectedDate.value)
  return params
}

async function loadData() {
  loading.value = true
  fetchError.value = null
  try {
    const { data } = await api.get<FinanceSummary>('/api/finance/summary', {
      params: Object.fromEntries(buildParams()),
    })
    summary.value = data
    await nextTick()
    renderCharts()
    if (data.partial) {
      ElMessage.warning(`当前周期缺失 ${data.missing_dates.length} 天快照，已按入库数据部分汇总`)
    } else if (data.failed_count > 0) {
      ElMessage.warning(`${data.failed_count} 个数据源统计失败，净收入仅供参考`)
    }
  } catch (e: any) {
    fetchError.value = e.response?.data?.detail || e.message || '请求失败'
    ElMessage.error(fetchError.value ?? '请求失败')
  } finally {
    loading.value = false
  }
}

async function handleCompare() {
  if (period.value !== 'day') return
  comparing.value = true
  try {
    const params = new URLSearchParams()
    if (selectedDate.value) params.set('date', selectedDate.value)
    const { data } = await api.post<CompareResponse>('/api/finance/daily-summary/compare', null, {
      params: Object.fromEntries(params),
    })
    compareResult.value = data
    compareDialogVisible.value = true
    if (!data.has_difference) ElMessage.info('比对结果一致，无差异')
  } catch (e: any) {
    ElMessage.error('比对失败: ' + (e.response?.data?.detail || e.message || '请求失败'))
  } finally {
    comparing.value = false
  }
}

async function handleOverwrite() {
  overwriting.value = true
  try {
    const params = new URLSearchParams()
    if (selectedDate.value) params.set('date', selectedDate.value)
    await api.post('/api/finance/daily-summary/overwrite', null, {
      params: Object.fromEntries(params),
    })
    compareDialogVisible.value = false
    ElMessage.success('快照已覆盖更新')
    await loadData()
  } catch (e: any) {
    ElMessage.error('覆盖失败: ' + (e.response?.data?.detail || e.message || '请求失败'))
  } finally {
    overwriting.value = false
  }
}

function renderCharts() {
  renderTrendChart()
  renderShareChart()
}

function renderTrendChart() {
  if (!trendChartRef.value || !summary.value) return
  trendChart ??= echarts.init(trendChartRef.value)
  const labels = summary.value.chart.labels.map(label => label.slice(5))
  trendChart.setOption({
    color: ['#1f9d7a', '#d97706'],
    grid: { left: 12, right: 18, top: 24, bottom: 12, containLabel: true },
    tooltip: {
      trigger: 'axis',
      valueFormatter: (value: number) => formatAmount(value),
    },
    legend: {
      top: 0,
      right: 0,
      icon: 'circle',
      textStyle: { color: '#64748b', fontSize: 12 },
      data: ['收入', '消费'],
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: labels,
      axisLine: { lineStyle: { color: '#e2e8f0' } },
      axisTick: { show: false },
      axisLabel: { color: '#64748b' },
    },
    yAxis: {
      type: 'value',
      axisLabel: { color: '#64748b', formatter: (value: number) => `$${value}` },
      splitLine: { lineStyle: { color: '#eef2f7' } },
    },
    series: [
      {
        name: '收入',
        type: 'line',
        smooth: true,
        symbolSize: 7,
        data: summary.value.chart.revenue,
        areaStyle: { color: 'rgba(31, 157, 122, 0.12)' },
        lineStyle: { width: 3 },
      },
      {
        name: '消费',
        type: 'line',
        smooth: true,
        symbolSize: 7,
        data: summary.value.chart.cost,
        areaStyle: { color: 'rgba(217, 119, 6, 0.12)' },
        lineStyle: { width: 3 },
      },
    ],
  })
}

function renderShareChart() {
  if (!shareChartRef.value || !summary.value) return
  shareChart ??= echarts.init(shareChartRef.value)
  const data = summary.value.upstream_items
    .filter(item => item.amount > 0)
    .map(item => ({ name: item.name, value: Number(item.amount.toFixed(6)) }))
  shareChart.setOption({
    color: ['#1f9d7a', '#2563eb', '#d97706', '#9333ea', '#dc2626', '#0891b2'],
    tooltip: {
      trigger: 'item',
      formatter: (params: any) => `${params.name}<br/>${formatAmount(params.value)} (${params.percent}%)`,
    },
    legend: {
      bottom: 0,
      type: 'scroll',
      icon: 'circle',
      textStyle: { color: '#64748b', fontSize: 12 },
    },
    series: [
      {
        name: '上游消费',
        type: 'pie',
        radius: ['54%', '74%'],
        center: ['50%', '43%'],
        avoidLabelOverlap: true,
        minAngle: 4,
        label: {
          color: '#334155',
          formatter: '{b}\n{d}%',
        },
        itemStyle: {
          borderColor: '#fff',
          borderWidth: 3,
        },
        data: data.length ? data : [{ name: '暂无消费', value: 1, itemStyle: { color: '#e2e8f0' } }],
      },
    ],
  })
}

function exportCsv() {
  if (!summary.value) return
  const rows: Array<Array<string | number>> = [
    ['周期', periodLabel(period.value)],
    ['日期范围', dateRangeLabel.value],
    ['总收入', summary.value.total_revenue],
    ['总消费', summary.value.total_cost],
    ['净收入', summary.value.net_income],
    ['毛利率', summary.value.margin_percent],
    ['入库天数', summary.value.included_days],
    ['缺失日期', summary.value.missing_dates.join(' ')],
    [],
    ['类型', '名称', '上游类型', '金额', '状态', '错误信息'],
    ...filteredWebsiteItems.value.map(item => ['收入', item.name, item.upstream_type, item.amount, item.status, item.error ?? '']),
    ...filteredUpstreamItems.value.map(item => ['消费', item.name, item.upstream_type, item.amount, item.status, item.error ?? '']),
  ]
  const csv = rows.map(row => row.map(csvCell).join(',')).join('\n')
  const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = `finance-${period.value}-${summary.value.start_date}-${summary.value.end_date}.csv`
  link.click()
  URL.revokeObjectURL(url)
}

function csvCell(value: string | number): string {
  const text = String(value ?? '')
  return /[",\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text
}

function periodLabel(value: Period): string {
  const item = periodOptions.find(option => option.value === value)
  return item?.label ?? value
}

function diffField(row: DiffItem): DiffField {
  if (row.old_amount !== row.new_amount) return 'amount'
  if (row.old_status !== row.new_status) return 'status'
  return 'error'
}

function diffFieldLabel(row: DiffItem): string {
  const labels: Record<DiffField, string> = {
    amount: '金额',
    status: '状态',
    error: '错误',
  }
  return labels[diffField(row)]
}

function diffRawValue(row: DiffItem, side: DiffSide): number | string | null {
  const field = diffField(row)
  if (field === 'amount') return side === 'old' ? row.old_amount : row.new_amount
  if (field === 'status') return side === 'old' ? row.old_status : row.new_status
  return side === 'old' ? row.old_error : row.new_error
}

function formatDiffValue(row: DiffItem, side: DiffSide): string {
  const value = diffRawValue(row, side)
  if (value === null || value === undefined || value === '') return '-'
  if (diffField(row) === 'amount') return formatAmount(Number(value))
  return String(value)
}

function resizeCharts() {
  trendChart?.resize()
  shareChart?.resize()
}

watch(selectedDate, () => {
  void loadData()
})

watch([filteredWebsiteItems, filteredUpstreamItems], () => {
  if (summary.value) renderShareChart()
})

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

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeCharts)
  trendChart?.dispose()
  shareChart?.dispose()
})
</script>

<style scoped>
.finance-page {
  --finance-bg: #f4f7fb;
  --finance-card: #ffffff;
  --finance-border: #e2e8f0;
  --finance-border-strong: #cbd5e1;
  --finance-text: #0f172a;
  --finance-muted: #64748b;
  --finance-soft: #94a3b8;
  --finance-green: #1f9d7a;
  --finance-orange: #d97706;
  --finance-blue: #2563eb;
  --finance-red: #dc2626;

  width: 100%;
  color: var(--finance-text);
  font-family: Inter, "Noto Sans SC", system-ui, sans-serif;
}

.finance-shell {
  display: grid;
  gap: 18px;
  max-width: 1600px;
  margin: 0 auto;
  padding: 18px;
  border-radius: 18px;
  background: var(--finance-bg);
}

.finance-topbar,
.dashboard-panel,
.metric-card,
.loading-panel,
.empty-state {
  background: var(--finance-card);
  border: 1px solid var(--finance-border);
  border-radius: 8px;
  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.06);
}

.finance-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px;
}

.period-tabs,
.table-tabs {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  border-radius: 8px;
  background: #eef2f7;
  border: 1px solid var(--finance-border);
}

.period-tab,
.table-tabs button {
  min-width: 54px;
  height: 32px;
  padding: 0 14px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--finance-muted);
  font-weight: 700;
  cursor: pointer;
}

.period-tab.active,
.table-tabs button.active {
  color: var(--finance-text);
  background: #fff;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.12);
}

.toolbar-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 10px;
}

.search-input {
  width: 240px;
}

.date-picker {
  width: 170px;
}

.icon-button {
  border-radius: 8px;
  font-weight: 700;
}

.icon-button :deep(svg) {
  margin-right: 6px;
}

.compare-button {
  color: #fff;
}

.page-alert {
  border-radius: 8px;
}

.metrics-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}

.metric-card {
  min-height: 136px;
  padding: 18px;
  display: grid;
  align-content: space-between;
}

.metric-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  color: var(--finance-muted);
  font-size: 13px;
  font-weight: 700;
}

.metric-icon {
  width: 34px;
  height: 34px;
  display: inline-grid;
  place-items: center;
  border-radius: 8px;
}

.metric-icon.income {
  color: var(--finance-green);
  background: rgba(31, 157, 122, 0.1);
}

.metric-icon.cost {
  color: var(--finance-orange);
  background: rgba(217, 119, 6, 0.12);
}

.metric-icon.net {
  color: var(--finance-blue);
  background: rgba(37, 99, 235, 0.1);
}

.metric-icon.risk {
  color: var(--finance-red);
  background: rgba(220, 38, 38, 0.1);
}

.metric-card strong {
  color: var(--finance-text);
  font-family: "JetBrains Mono", Consolas, monospace;
  font-size: clamp(22px, 2vw, 32px);
  font-weight: 800;
  line-height: 1.12;
  word-break: break-word;
  font-variant-numeric: tabular-nums;
}

.metric-card small {
  color: var(--finance-muted);
  font-size: 12px;
}

.positive {
  color: var(--finance-green) !important;
}

.negative {
  color: var(--finance-red) !important;
}

.chart-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(320px, 0.8fr);
  gap: 14px;
}

.dashboard-panel {
  padding: 18px;
  min-width: 0;
}

.panel-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 12px;
}

.panel-header h2 {
  margin: 0;
  color: var(--finance-text);
  font-size: 17px;
  line-height: 1.2;
}

.panel-header p {
  margin: 5px 0 0;
  color: var(--finance-muted);
  font-size: 12px;
}

.panel-chip {
  flex: 0 0 auto;
  padding: 5px 9px;
  border-radius: 999px;
  background: #eef2f7;
  color: var(--finance-muted);
  font-size: 12px;
  font-weight: 700;
}

.chart {
  width: 100%;
}

.trend-chart {
  height: 326px;
}

.share-chart {
  height: 326px;
}

.detail-header {
  align-items: center;
}

.table-wrap {
  width: 100%;
  overflow-x: auto;
  border: 1px solid var(--finance-border);
  border-radius: 8px;
}

.finance-table {
  min-width: 760px;
}

.amount,
.diff-old,
.diff-new,
.compare-stat strong {
  font-family: "JetBrains Mono", Consolas, monospace;
  font-variant-numeric: tabular-nums;
}

.amount.income,
.diff-new {
  color: var(--finance-green);
  font-weight: 800;
}

.amount.cost {
  color: var(--finance-orange);
  font-weight: 800;
}

.diff-old {
  color: var(--finance-red);
}

.error-text {
  color: var(--finance-red);
  font-size: 12px;
  word-break: break-word;
}

.muted-text {
  color: var(--finance-soft);
}

.empty-state,
.loading-panel {
  padding: 44px 18px;
}

.compare-alert {
  margin-bottom: 16px;
}

.compare-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.compare-card {
  padding: 14px;
  border: 1px solid var(--finance-border);
  border-radius: 8px;
  background: #fff;
}

.compare-card h3,
.diff-section h3 {
  margin: 0 0 12px;
  color: var(--finance-text);
  font-size: 15px;
}

.compare-stat {
  display: grid;
  gap: 8px;
}

.compare-stat span {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  color: var(--finance-muted);
}

.compare-stat strong {
  color: var(--finance-text);
}

.compare-empty {
  padding: 26px 0;
  color: var(--finance-soft);
  text-align: center;
}

.diff-section {
  margin-top: 18px;
}

.finance-page :deep(.el-input__wrapper) {
  min-height: 34px;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 0 0 1px var(--finance-border) inset;
}

.finance-page :deep(.el-input__wrapper:hover),
.finance-page :deep(.el-input__wrapper.is-focus) {
  box-shadow: 0 0 0 1px var(--finance-border-strong) inset;
}

.finance-page :deep(.el-input__inner) {
  color: var(--finance-text);
}

.finance-page :deep(.el-input__inner::placeholder),
.finance-page :deep(.el-input__prefix) {
  color: var(--finance-soft);
}

.finance-page :deep(.el-button--primary) {
  --el-button-bg-color: #0f172a;
  --el-button-border-color: #0f172a;
  --el-button-hover-bg-color: #263449;
  --el-button-hover-border-color: #263449;
}

.finance-page :deep(.el-button:not(.el-button--primary)) {
  --el-button-bg-color: #fff;
  --el-button-border-color: var(--finance-border);
  --el-button-text-color: var(--finance-text);
  --el-button-hover-bg-color: #f8fafc;
  --el-button-hover-border-color: var(--finance-border-strong);
  --el-button-hover-text-color: var(--finance-text);
}

.finance-page :deep(.el-table) {
  --el-table-bg-color: #fff;
  --el-table-tr-bg-color: #fff;
  --el-table-header-bg-color: #f8fafc;
  --el-table-header-text-color: #475569;
  --el-table-text-color: var(--finance-text);
  --el-table-row-hover-bg-color: #f8fafc;
  --el-table-border-color: var(--finance-border);
}

.finance-page :deep(.el-table th.el-table__cell) {
  background: #f8fafc;
  color: #475569;
  font-size: 12px;
  font-weight: 800;
}

.finance-page :deep(.el-table td.el-table__cell) {
  border-bottom-color: #eef2f7;
}

.finance-page :deep(.el-table__inner-wrapper::before),
.finance-page :deep(.el-table__border-left-patch) {
  background: var(--finance-border);
}

.finance-page :deep(.el-tag) {
  border-radius: 4px;
  font-weight: 800;
}

:global(.finance-compare-dialog) {
  --el-dialog-bg-color: #fff;
  --el-text-color-primary: #0f172a;
  --el-text-color-regular: #0f172a;
  border-radius: 8px;
}

:global(.finance-compare-dialog .el-dialog__body) {
  color: #0f172a;
}

:global(.finance-compare-dialog .el-table) {
  --el-table-bg-color: #fff;
  --el-table-tr-bg-color: #fff;
  --el-table-header-bg-color: #f8fafc;
  --el-table-text-color: #0f172a;
  --el-table-border-color: #e2e8f0;
}

@media (max-width: 1180px) {
  .metrics-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .chart-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 760px) {
  .finance-shell {
    padding: 12px;
    gap: 12px;
  }

  .finance-topbar {
    align-items: stretch;
    flex-direction: column;
  }

  .period-tabs,
  .toolbar-actions,
  .search-input,
  .date-picker,
  .icon-button {
    width: 100%;
  }

  .period-tab {
    flex: 1;
  }

  .toolbar-actions {
    display: grid;
    grid-template-columns: 1fr;
  }

  .metrics-grid {
    grid-template-columns: 1fr;
  }

  .panel-header,
  .detail-header,
  .compare-grid {
    display: grid;
    grid-template-columns: 1fr;
  }

  .table-tabs {
    width: 100%;
  }

  .table-tabs button {
    flex: 1;
  }

  :global(.finance-compare-dialog) {
    width: calc(100vw - 24px) !important;
  }
}
</style>
