<script lang="ts" setup>
import type {
  CountryDashboardResult,
} from '#/api/legacy/datav';

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

import { useAccessStore } from '@vben/stores';

import {
  Button,
  DateRangePicker,
  Empty,
  Input,
  message,
  Select,
  Space,
  Spin,
  Table,
  Tooltip,
} from 'antdv-next';
import dayjs from 'dayjs';

import { countryDashboard } from '#/api/legacy/datav';
import SysOriginSelect from '#/components/sys-origin-select.vue';
import { getAllowedSysOrigins } from '#/views/system/shared';

import LatestPurchaseList from './components/latest-purchase-list.vue';
import PurchaseCount from './components/purchase-count.vue';

defineOptions({ name: 'StatisticsDatav' });

const accessStore = useAccessStore();

const datavFullscreen = ref<HTMLElement>();
const fullscreen = ref(false);
const loading = ref(false);
const dashboard = ref<CountryDashboardResult | null>(null);
const dateRange = ref<[string, string] | null>([
  dayjs().subtract(6, 'day').format('YYYY-MM-DD'),
  dayjs().format('YYYY-MM-DD'),
]);

const query = reactive({
  countryKeyword: '',
  periodType: 'DAY',
  sysOrigin: '',
});

const accessCodes = computed(() => accessStore.accessCodes || []);
const sysOriginOptions = computed(() => {
  const options = getAllowedSysOrigins(accessCodes.value);
  return options.length > 0 ? options : getAllowedSysOrigins([]);
});
const permissionsSysOriginCode = computed(() =>
  sysOriginOptions.value.map((item) => String(item.value || '')),
);

const periodTypeOptions = [
  { label: '日', value: 'DAY' },
  { label: '周', value: 'WEEK' },
  { label: '月', value: 'MONTH' },
  { label: '全部', value: 'ALL' },
];

const metricColumns = new Set([
  'countryNewUser',
  'dealerRecharge',
  'gamePayout',
  'gameProfit',
  'gameTotalFlow',
  'giftConsume',
  'luckyGiftPayout',
  'luckyGiftProfit',
  'luckyGiftTotalFlow',
  'newUserRecharge',
  'salaryExchange',
  'totalRecharge',
]);

const columns: any[] = [
  { dataIndex: 'countryName', fixed: 'left' as const, key: 'countryName', title: '国家', width: 150 },
  { dataIndex: 'countryCode', key: 'countryCode', title: 'Code', width: 86 },
  { dataIndex: 'periodName', key: 'periodName', title: '周期', width: 110 },
  { align: 'right', dataIndex: 'countryNewUser', key: 'countryNewUser', title: '新增', width: 110 },
  { align: 'right', dataIndex: 'newUserRecharge', key: 'newUserRecharge', title: '新增充值', width: 130 },
  { align: 'right', dataIndex: 'dealerRecharge', key: 'dealerRecharge', title: '币商充值', width: 130 },
  { align: 'right', dataIndex: 'salaryExchange', key: 'salaryExchange', title: '工资兑换', width: 130 },
  { align: 'right', dataIndex: 'totalRecharge', key: 'totalRecharge', title: '总充值', width: 130 },
  { align: 'right', dataIndex: 'giftConsume', key: 'giftConsume', title: '礼物消耗', width: 130 },
  { align: 'right', dataIndex: 'luckyGiftTotalFlow', key: 'luckyGiftTotalFlow', title: '幸运礼物流水', width: 150 },
  { align: 'right', dataIndex: 'luckyGiftPayout', key: 'luckyGiftPayout', title: '幸运礼物返奖', width: 150 },
  { align: 'right', dataIndex: 'luckyGiftProfit', key: 'luckyGiftProfit', title: '幸运礼物利润', width: 150 },
  { align: 'right', dataIndex: 'gameTotalFlow', key: 'gameTotalFlow', title: '游戏流水', width: 130 },
  { align: 'right', dataIndex: 'gamePayout', key: 'gamePayout', title: '游戏返奖', width: 130 },
  { align: 'right', dataIndex: 'gameProfit', key: 'gameProfit', title: '游戏利润', width: 130 },
];

const total = computed(() => dashboard.value?.total || null);
const records = computed(() => dashboard.value?.records || []);
const summaryCards = computed(() => {
  const item = total.value;
  return [
    { label: '新增用户', value: formatInteger(item?.countryNewUser) },
    { label: '总充值', value: formatAmount(item?.totalRecharge) },
    { label: '礼物消耗', value: formatAmount(item?.giftConsume) },
    { label: '幸运礼物利润', value: formatAmount(item?.luckyGiftProfit) },
    { label: '游戏流水', value: formatAmount(item?.gameTotalFlow) },
    { label: '游戏利润', value: formatAmount(item?.gameProfit) },
  ];
});

function hasPermission(code: string) {
  const codes = accessCodes.value;
  return codes.length === 0 || codes.includes(code);
}

const canQuery = computed(() => hasPermission('datav:query'));
const canPaidPreview = computed(() => hasPermission('datav:paid:preview'));

function syncFullscreenState() {
  fullscreen.value = document.fullscreenElement === datavFullscreen.value;
}

async function screen() {
  const element = datavFullscreen.value;
  if (!element) {
    return;
  }
  if (document.fullscreenElement === element) {
    await document.exitFullscreen();
    return;
  }
  if (document.fullscreenElement) {
    await document.exitFullscreen();
  }
  await element.requestFullscreen();
}

function defaultRange(periodType: string): [string, string] | null {
  const now = dayjs();
  if (periodType === 'ALL') {
    return null;
  }
  if (periodType === 'MONTH') {
    return [now.startOf('month').format('YYYY-MM-DD'), now.format('YYYY-MM-DD')];
  }
  if (periodType === 'WEEK') {
    const daysSinceMonday = now.day() === 0 ? 6 : now.day() - 1;
    return [now.subtract(daysSinceMonday, 'day').format('YYYY-MM-DD'), now.format('YYYY-MM-DD')];
  }
  return [now.subtract(6, 'day').format('YYYY-MM-DD'), now.format('YYYY-MM-DD')];
}

function handlePeriodChange(value: string) {
  dateRange.value = defaultRange(value);
  loadDashboard();
}

function buildParams() {
  const params: Record<string, any> = {
    countryKeyword: query.countryKeyword || undefined,
    periodType: query.periodType,
    sysOrigin: query.sysOrigin || undefined,
  };
  if (dateRange.value?.[0] && dateRange.value?.[1]) {
    params.startDate = dateRange.value[0];
    params.endDate = dateRange.value[1];
  }
  return params;
}

async function loadDashboard() {
  if (!canQuery.value) {
    return;
  }
  loading.value = true;
  try {
    dashboard.value = await countryDashboard(buildParams());
  } catch (error) {
    dashboard.value = null;
    message.error('数据大屏加载失败');
    throw error;
  } finally {
    loading.value = false;
  }
}

function formatInteger(value?: null | number | string) {
  const number = Number(value || 0);
  return Number.isFinite(number) ? number.toLocaleString('en-US', { maximumFractionDigits: 0 }) : '0';
}

function formatAmount(value?: null | number | string) {
  const number = Number(value || 0);
  return Number.isFinite(number)
    ? number.toLocaleString('en-US', {
        maximumFractionDigits: 2,
        minimumFractionDigits: 0,
      })
    : '0';
}

function tableCellText(record: Record<string, any>, key: string) {
  if (key === 'countryNewUser') {
    return formatInteger(record.countryNewUser);
  }
  return formatAmount(record[key] as number | string);
}

function rowKey(record: Record<string, any>) {
  return `${record.countryCode}-${record.periodKey}`;
}

watch(
  sysOriginOptions,
  (options) => {
    if (!query.sysOrigin && options[0]?.value) {
      query.sysOrigin = String(options[0].value);
    }
  },
  { immediate: true },
);

onMounted(() => {
  document.addEventListener('fullscreenchange', syncFullscreenState);
  loadDashboard();
});

onBeforeUnmount(() => {
  document.removeEventListener('fullscreenchange', syncFullscreenState);
});
</script>

<template>
  <div class="app-container-datav">
    <div
      ref="datavFullscreen"
      class="datav-shell" :class="[
        fullscreen ? 'datav-shell--fullscreen' : '',
      ]"
      @dblclick="screen"
    >
      <div class="datav-header">
        <div>
          <div class="datav-title">数据大屏</div>
          <div class="datav-subtitle">
            国家维度 · {{ dashboard?.computedAt || '-' }}
          </div>
        </div>
        <Space wrap>
          <Button ghost @click="screen">
            {{ fullscreen ? '退出全屏' : '全屏' }}
          </Button>
          <Button :loading="loading" type="primary" @click="loadDashboard">
            查询
          </Button>
        </Space>
      </div>

      <div v-if="canQuery" class="datav-content">
        <section class="panel filter-panel">
          <Space wrap>
            <SysOriginSelect
              v-model:value="query.sysOrigin"
              :options="sysOriginOptions"
              allow-clear
              placeholder="系统"
              style="width: 150px"
              @change="loadDashboard"
            />
            <Select
              v-model:value="query.periodType"
              :options="periodTypeOptions"
              style="width: 110px"
              @change="handlePeriodChange"
            />
            <DateRangePicker
              v-model:value="dateRange"
              allow-clear
              style="width: 260px"
              value-format="YYYY-MM-DD"
              @change="loadDashboard"
            />
            <Input
              v-model:value="query.countryKeyword"
              allow-clear
              placeholder="国家编码 / 名称"
              style="width: 180px"
              @press-enter="loadDashboard"
            />
            <Button :loading="loading" type="primary" @click="loadDashboard">
              查询
            </Button>
          </Space>
        </section>

        <div class="summary-grid">
          <section
            v-for="item in summaryCards"
            :key="item.label"
            class="summary-card"
          >
            <div class="summary-card__label">{{ item.label }}</div>
            <div class="summary-card__value">{{ item.value }}</div>
          </section>
        </div>

        <section class="panel dashboard-panel">
          <Spin :spinning="loading">
            <Table
              v-if="records.length > 0"
              :columns="columns"
              :data-source="records"
              :pagination="{ pageSize: 20, showSizeChanger: true }"
              :row-key="rowKey"
              :scroll="{ x: 1900 }"
              size="small"
            >
              <template #bodyCell="{ column, record }">
                <template v-if="metricColumns.has(String(column.dataIndex))">
                  <Tooltip v-if="column.dataIndex === 'luckyGiftProfit'">
                    <template #title>
                      主播分成：{{ formatAmount(record.luckyGiftAnchorShare) }}
                    </template>
                    <span class="number-cell">
                      {{ tableCellText(record, String(column.dataIndex)) }}
                    </span>
                  </Tooltip>
                  <span v-else class="number-cell">
                    {{ tableCellText(record, String(column.dataIndex)) }}
                  </span>
                </template>
              </template>
            </Table>
            <Empty v-else />
          </Spin>
        </section>

        <div class="legacy-grid">
          <section class="panel">
            <div class="panel-title">购买用户</div>
            <LatestPurchaseList :sys-origin-codes="permissionsSysOriginCode" />
          </section>
          <section v-if="canPaidPreview" class="panel">
            <div class="panel-title">今日付费预览</div>
            <PurchaseCount />
          </section>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.app-container-datav {
  background: #111827;
  min-height: calc(100vh - 120px);
  overflow: hidden;
}

.datav-shell {
  background:
    linear-gradient(180deg, rgba(15, 23, 42, 0.96), rgba(17, 24, 39, 0.98)),
    #111827;
  color: #f8fafc;
  min-height: inherit;
  padding: 20px;
}

.datav-shell--fullscreen {
  min-height: 100vh;
  padding: 24px;
}

.datav-header {
  align-items: center;
  display: flex;
  gap: 16px;
  justify-content: space-between;
}

.datav-title {
  color: #f8fafc;
  font-size: 28px;
  font-weight: 700;
  line-height: 1.3;
}

.datav-subtitle {
  color: #94a3b8;
  font-size: 13px;
  line-height: 1.8;
}

.datav-content {
  display: grid;
  gap: 16px;
  margin-top: 18px;
}

.panel {
  background: rgba(30, 41, 59, 0.82);
  border: 1px solid rgba(148, 163, 184, 0.18);
  border-radius: 8px;
  overflow: hidden;
}

.filter-panel {
  padding: 14px;
}

.summary-grid {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(6, minmax(0, 1fr));
}

.summary-card {
  background: #18212f;
  border: 1px solid rgba(45, 212, 191, 0.22);
  border-radius: 8px;
  min-height: 92px;
  padding: 14px;
}

.summary-card__label {
  color: #cbd5e1;
  font-size: 13px;
}

.summary-card__value {
  color: #f8fafc;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.dashboard-panel {
  padding: 12px;
}

.number-cell {
  color: #e2e8f0;
  font-variant-numeric: tabular-nums;
}

.legacy-grid {
  display: grid;
  gap: 16px;
  grid-template-columns: minmax(300px, 1fr) minmax(300px, 1fr);
}

.panel-title {
  color: #2dd4bf;
  font-size: 18px;
  font-weight: 700;
  padding: 16px 16px 8px;
}

.panel :deep(.ant-table) {
  background: transparent;
}

.panel :deep(.ant-table-cell) {
  background: #111827;
  color: #e2e8f0;
}

.panel :deep(.ant-table-thead > tr > th) {
  background: #1f2937;
  color: #f8fafc;
}

.panel :deep(.ant-empty-description) {
  color: #cbd5e1;
}

@media (max-width: 1200px) {
  .summary-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 768px) {
  .app-container-datav {
    min-height: calc(100vh - 88px);
  }

  .datav-shell {
    padding: 14px;
  }

  .datav-header {
    align-items: flex-start;
    flex-direction: column;
  }

  .datav-title {
    font-size: 24px;
  }

  .summary-grid,
  .legacy-grid {
    grid-template-columns: 1fr;
  }
}
</style>
