<script lang="ts" setup>
import type { Dayjs } from 'dayjs';

import type { DashboardStatItem } from './components/DashboardStatGrid.vue';

import { computed, onMounted, ref, watch } from 'vue';

import { AnalysisChartCard, Page } from '@vben/common-ui';
import {
  SvgBellIcon,
  SvgCakeIcon,
  SvgCardIcon,
  SvgDownloadIcon,
} from '@vben/icons';
import { useUserStore } from '@vben/stores';

import { Card, DatePicker, Radio, Spin, Tag } from 'ant-design-vue';
import dayjs from 'dayjs';

import { ROLE_SALESPERSON } from '#/views/system/admin/_shared/role-meta';

import CompareTrendChart from './components/CompareTrendChart.vue';
import DashboardStatGrid from './components/DashboardStatGrid.vue';
import InactiveStoreWarningList from './components/InactiveStoreWarningList.vue';
import InputCountTrendChart from './components/InputCountTrendChart.vue';
import RankingList from './components/RankingList.vue';
import RegionDistributionChart from './components/RegionDistributionChart.vue';
import StoreAmountRankingList from './components/StoreAmountRankingList.vue';
import {
  getSalespersonDashboardApi,
  type DashboardPeriod,
  type SalespersonDashboardResult,
} from './api';
import {
  defaultCustomRange,
  loadPeriodFilter,
  savePeriodFilter,
} from './utils/periodStorage';

const ALL_PERIOD_VALUES: DashboardPeriod[] = [
  'today',
  'last7days',
  'this_month',
  'last30days',
  'this_year',
  'last365days',
  'last_year',
  'custom',
];

const shortPeriodOptions: { label: string; value: DashboardPeriod }[] = [
  { label: '今日', value: 'today' },
  { label: '近7天', value: 'last7days' },
  { label: '本月', value: 'this_month' },
  { label: '近30天', value: 'last30days' },
];

const longPeriodOptions: { label: string; value: DashboardPeriod }[] = [
  { label: '今年', value: 'this_year' },
  { label: '近一年', value: 'last365days' },
  { label: '去年', value: 'last_year' },
];

const storedFilter = loadPeriodFilter();
const period = ref<DashboardPeriod>(storedFilter.period);
const customRange = ref<[Dayjs, Dayjs]>(
  storedFilter.customRange ?? defaultCustomRange(),
);

const loading = ref(false);
const dashboardData = ref<SalespersonDashboardResult | null>(null);

const userStore = useUserStore();
const isSalespersonView = computed(() => {
  const roleId = Number(userStore.userInfo?.role_id ?? userStore.userInfo?.roles?.id);
  return roleId === ROLE_SALESPERSON;
});

/** 当前生效的时间区间文案（预设用 API 返回，自定义用本地选择） */
const activeRangeText = computed(() => {
  if (period.value === 'custom') {
    return `${customRange.value[0].format('YYYY-MM-DD')} ~ ${customRange.value[1].format('YYYY-MM-DD')}`;
  }
  if (!dashboardData.value) return '';
  const start = dayjs.unix(dashboardData.value.start_at).format('YYYY-MM-DD');
  const end = dayjs.unix(dashboardData.value.end_at).format('YYYY-MM-DD');
  return `${start} ~ ${end}`;
});

function formatMomRate(rate: number | null | undefined) {
  if (rate === null || rate === undefined) return '—';
  const prefix = rate > 0 ? '+' : '';
  return `${prefix}${rate}%`;
}

function momTagColor(rate: number | null | undefined) {
  if (rate === null || rate === undefined || rate === 0) return 'default';
  return rate > 0 ? 'success' : 'error';
}

const statItems = computed<DashboardStatItem[]>(() => {
  const summary = dashboardData.value?.summary;
  if (!summary) return [];

  return [
    {
      title: '录入总数',
      value: summary.input_total,
      valueType: 'count',
      footerLabel: '环比',
      footerValue: formatMomRate(summary.input_mom_rate),
      decorationIcon: SvgCardIcon,
    },
    {
      title: '录入诊所',
      value: summary.clinic_input_count,
      valueType: 'count',
      footerLabel: '当前周期',
      footerValue: summary.clinic_input_count,
      decorationIcon: SvgCakeIcon,
    },
    {
      title: '录入药店',
      value: summary.pharmacy_input_count,
      valueType: 'count',
      footerLabel: '当前周期',
      footerValue: summary.pharmacy_input_count,
      decorationIcon: SvgDownloadIcon,
    },
    {
      title: '待审核',
      value: summary.pending_count,
      valueType: 'count',
      footerLabel: '当前周期',
      footerValue: summary.pending_count,
      decorationIcon: SvgBellIcon,
    },
    {
      title: '绑定门店营业额',
      value: Number(summary.valid_amount_total || 0),
      valueType: 'money',
      footerLabel: '环比',
      footerValue: formatMomRate(summary.amount_mom_rate),
      decorationIcon: SvgCardIcon,
    },
  ];
});

/**
 * 拉取看板数据；自定义周期附带 start_at/end_at（当天起止 unix 秒）
 */
async function loadDashboard() {
  loading.value = true;
  try {
    const params: {
      period: DashboardPeriod;
      start_at?: number;
      end_at?: number;
    } = { period: period.value };

    if (period.value === 'custom') {
      params.start_at = customRange.value[0].startOf('day').unix();
      params.end_at = customRange.value[1].endOf('day').unix();
    }

    dashboardData.value = await getSalespersonDashboardApi(params);
  } finally {
    loading.value = false;
  }
}

function persistFilter() {
  savePeriodFilter({
    period: period.value,
    customRange: period.value === 'custom' ? customRange.value : undefined,
  });
}

watch(period, (val) => {
  if (!ALL_PERIOD_VALUES.includes(val)) {
    period.value = 'today';
    return;
  }
  persistFilter();
  loadDashboard();
});

watch(
  customRange,
  () => {
    if (period.value !== 'custom') return;
    persistFilter();
    loadDashboard();
  },
  { deep: true },
);

onMounted(() => {
  loadDashboard();
});
</script>

<template>
  <Page auto-content-height title="业务员看板">
    <Spin :spinning="loading">
      <div class="salesperson-dashboard">
        <Card class="mb-4">
          <div class="dashboard-filter">
            <div>
              <div class="dashboard-filter__title">门店录入业绩分析</div>
              <div v-if="activeRangeText" class="dashboard-filter__range">
                统计区间：{{ activeRangeText }}
              </div>
              <div v-if="dashboardData" class="dashboard-filter__tags">
                <Tag :color="momTagColor(dashboardData.summary.input_mom_rate)">
                  录入环比 {{ formatMomRate(dashboardData.summary.input_mom_rate) }}
                </Tag>
                <Tag :color="momTagColor(dashboardData.summary.amount_mom_rate)">
                  营业额环比 {{ formatMomRate(dashboardData.summary.amount_mom_rate) }}
                </Tag>
              </div>
            </div>

            <div class="dashboard-filter__groups">
              <Radio.Group v-model:value="period" button-style="solid" size="small">
                <Radio.Button
                  v-for="item in shortPeriodOptions"
                  :key="item.value"
                  :value="item.value"
                >
                  {{ item.label }}
                </Radio.Button>
              </Radio.Group>

              <Radio.Group v-model:value="period" button-style="solid" size="small">
                <Radio.Button
                  v-for="item in longPeriodOptions"
                  :key="item.value"
                  :value="item.value"
                >
                  {{ item.label }}
                </Radio.Button>
                <Radio.Button value="custom">自定义</Radio.Button>
              </Radio.Group>

              <DatePicker.RangePicker
                v-if="period === 'custom'"
                v-model:value="customRange"
                class="dashboard-filter__picker"
                :allow-clear="false"
                format="YYYY-MM-DD"
              />
            </div>
          </div>
        </Card>

        <DashboardStatGrid :items="statItems" />

        <template v-if="dashboardData">
          <AnalysisChartCard class="mt-4" title="录入门店数量趋势">
            <InputCountTrendChart :data="dashboardData.trend" />
          </AnalysisChartCard>

          <div class="dashboard-two-col mt-4">
            <AnalysisChartCard class="dashboard-two-col__item" title="录入环比对比">
              <CompareTrendChart
                :current="dashboardData.trend"
                :previous="dashboardData.compare_trend"
              />
            </AnalysisChartCard>

            <AnalysisChartCard class="dashboard-two-col__item" title="地区录入分布">
              <RegionDistributionChart :data="dashboardData.region_stats" />
            </AnalysisChartCard>
          </div>

          <div v-if="!isSalespersonView" class="dashboard-two-col mt-4">
            <RankingList
              class="dashboard-two-col__item"
              title="录入门店数量排行"
              :items="dashboardData.input_ranking"
              value-key="count"
            />

            <RankingList
              class="dashboard-two-col__item"
              title="绑定门店营业额排行"
              subtitle="统计业务员名下门店的有效支付金额（已支付且无退款）"
              :items="dashboardData.amount_ranking"
              value-key="amount"
            />
          </div>

          <div class="dashboard-two-col mt-4">
            <StoreAmountRankingList
              class="dashboard-two-col__item"
              title="门店营业额排行"
              subtitle="当前筛选周期内各门店有效支付金额（诊所+药店）"
              :items="dashboardData.store_amount_ranking"
              :show-promoter="!isSalespersonView"
            />

            <InactiveStoreWarningList
              class="dashboard-two-col__item"
              title="长期未活跃警示"
              subtitle="本月（自然月）营业额为 0 的绑定门店"
              :items="dashboardData.inactive_store_warnings"
              :show-promoter="!isSalespersonView"
            />
          </div>
        </template>
      </div>
    </Spin>
  </Page>
</template>

<style scoped>
.dashboard-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: flex-start;
  justify-content: space-between;
}

.dashboard-filter__title {
  margin-bottom: 8px;
  font-size: 16px;
  font-weight: 600;
  color: #1d2129;
}

.dark .dashboard-filter__title {
  color: #f3f4f6;
}

.dashboard-filter__range {
  margin-bottom: 8px;
  font-size: 13px;
  color: #86909c;
}

.dashboard-filter__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.dashboard-filter__groups {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
}

.dashboard-filter__picker {
  min-width: 260px;
}

.dashboard-two-col {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}

@media (min-width: 1280px) {
  .dashboard-two-col {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.dashboard-two-col__item {
  width: 100%;
  min-width: 0;
}

.dashboard-two-col :deep(.ranking-card),
.dashboard-two-col :deep(.warning-card) {
  width: 100%;
  min-width: 0;
}
</style>
