import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
import {
  Button, Card, Col, DatePicker, Descriptions, Form, Modal, Row, Segmented, Select, Space, Statistic, Table, Typography, message,
} from 'antd';
import { CloudUploadOutlined, DownloadOutlined, ReloadOutlined } from '@ant-design/icons';
import dayjs, { type Dayjs } from 'dayjs';
import ReactECharts from 'echarts-for-react';
import { getInstanceByDom, type EChartsOption } from 'echarts';
import {
  addShanghaiDays,
  defaultShanghaiRangeYmds,
  shanghaiMonthRange,
  shanghaiQuarterIndex,
  shanghaiQuarterRange,
  shanghaiWeekRange,
  shanghaiYearMonth,
  shanghaiYmd,
} from '@dukang/domain';
import type { DashboardGranularity, DashboardLineChart, DashboardLineHref } from '@dukang/shared-types';
import {
  request,
  type DashboardAnalytics,
  type DashboardStats,
  type DeployTriggerResult,
  type HqProfile,
  type Paginated,
  type SystemVersion,
} from '../lib/api';
import { ADMIN_OPTIONS_PAGE_SIZE, fmtTime } from '../lib/constants';
import { downloadDashboardChartsPdf } from '../lib/dashboard-charts-pdf';

const STATUS_LABELS: Record<string, string> = {
  PENDING_PAY: '待付款',
  PENDING_SHIP: '待发货',
  OUT_WAREHOUSE: '已出库',
  SHIPPING: '配送中',
  PENDING_RECEIVE: '待收货',
  COMPLETED: '已完成',
  CANCELLED: '已取消',
  REFUNDING: '退款中',
  REFUNDED: '已退款',
};

const DEPLOYED_BY_LABELS: Record<string, string> = {
  webhook: 'Webhook',
  manual: '手动脚本',
  admin: 'Admin 发布',
};

const GRAIN_OPTIONS: Array<{ label: string; value: DashboardGranularity }> = [
  { label: '日', value: 'day' },
  { label: '周', value: 'week' },
  { label: '月', value: 'month' },
  { label: '季', value: 'quarter' },
  { label: '年', value: 'year' },
];

type ChartMetric = 'total' | 'increment';

const METRIC_OPTIONS: Array<{ label: string; value: ChartMetric }> = [
  { label: '总量', value: 'total' },
  { label: '增量', value: 'increment' },
];

function toDayjsRange(from: Date, toInclusive: Date): [Dayjs, Dayjs] {
  return [dayjs(shanghaiYmd(from)), dayjs(shanghaiYmd(toInclusive))];
}

/** 完整上一自然周 / 上月 / 上季（北京日历） */
function datePresetRange(kind: 'lastWeek' | 'lastMonth' | 'lastQuarter'): [Dayjs, Dayjs] {
  const today = new Date();
  if (kind === 'lastWeek') {
    const thisMonday = shanghaiWeekRange(today).start;
    return toDayjsRange(addShanghaiDays(thisMonday, -7), addShanghaiDays(thisMonday, -1));
  }
  if (kind === 'lastMonth') {
    const { year, month } = shanghaiYearMonth(today);
    const prev = month === 1 ? { year: year - 1, month: 12 } : { year, month: month - 1 };
    const r = shanghaiMonthRange(prev.year, prev.month);
    return toDayjsRange(r.start, addShanghaiDays(r.endExclusive, -1));
  }
  const { year, quarter } = shanghaiQuarterIndex(today);
  const prev = quarter === 1 ? { year: year - 1, quarter: 4 } : { year, quarter: quarter - 1 };
  const r = shanghaiQuarterRange(prev.year, prev.quarter);
  return toDayjsRange(r.start, addShanghaiDays(r.endExclusive, -1));
}

const DATE_PRESETS: Array<{ key: 'lastWeek' | 'lastMonth' | 'lastQuarter'; label: string }> = [
  { key: 'lastWeek', label: '上周' },
  { key: 'lastMonth', label: '上月' },
  { key: 'lastQuarter', label: '上季度' },
];

function chartIsMetric(key: string, metric: ChartMetric): boolean {
  const isInc = key.includes('.increment');
  return metric === 'increment' ? isInc : !isInc;
}

const HREF_PATH: Record<DashboardLineHref, string> = {
  users: '/users',
  partners: '/city-partners',
  stores: '/stores',
  orders: '/orders',
  redeems: '/redeem-records',
};

type CityOption = { id: string; name: string; code: string };

type AnalyticsFilters = {
  granularity: DashboardGranularity;
  range: [Dayjs, Dayjs];
  cityId?: string;
};

function defaultRange(grain: DashboardGranularity): [Dayjs, Dayjs] {
  const y = defaultShanghaiRangeYmds(grain);
  return [dayjs(y.from), dayjs(y.to)];
}

function buildAnalyticsQs(f: AnalyticsFilters) {
  const qs = new URLSearchParams();
  qs.set('granularity', f.granularity);
  qs.set('dateFrom', f.range[0].format('YYYY-MM-DD'));
  qs.set('dateTo', f.range[1].format('YYYY-MM-DD'));
  if (f.cityId) qs.set('cityId', f.cityId);
  return qs.toString();
}

function listHref(kind: DashboardLineHref, f: AnalyticsFilters): string {
  const qs = new URLSearchParams();
  qs.set('createdFrom', f.range[0].format('YYYY-MM-DD'));
  qs.set('createdTo', f.range[1].format('YYYY-MM-DD'));
  if (f.cityId && f.cityId !== 'none') qs.set('cityId', f.cityId);
  const s = qs.toString();
  return s ? `${HREF_PATH[kind]}?${s}` : HREF_PATH[kind];
}

function lineOption(
  periods: Array<{ key: string; label: string }>,
  chart: DashboardLineChart,
): EChartsOption {
  return {
    tooltip: { trigger: 'axis' },
    legend: { type: 'scroll', top: 0 },
    grid: { left: 56, right: 28, top: 48, bottom: periods.length > 14 ? 64 : 36 },
    xAxis: {
      type: 'category',
      data: periods.map((p) => p.label),
      axisLabel: { rotate: periods.length > 14 ? 45 : 0 },
    },
    yAxis: {
      type: 'value',
      minInterval: chart.unit === 'count' ? 1 : undefined,
    },
    series: chart.series.map((s) => ({
      name: s.name,
      type: 'line' as const,
      smooth: true,
      showSymbol: periods.length <= 24,
      data: s.values,
    })),
  };
}

export default function DashboardPage() {
  const [stats, setStats] = useState<DashboardStats | null>(null);
  const [version, setVersion] = useState<SystemVersion | null>(null);
  const [loading, setLoading] = useState(true);
  const [versionLoading, setVersionLoading] = useState(true);
  const [profile, setProfile] = useState<HqProfile | null>(null);
  const [deploying, setDeploying] = useState(false);
  const isSuperAdmin = profile?.adminRole === 'SUPER_ADMIN';
  const keys = profile?.permissionKeys ?? [];
  const has = (k: string) => keys.includes(k);
  const cityScoped = !!profile?.cityScoped;
  const canUsers = has('users');
  const canOrders = has('orders');
  const canStores = has('stores');
  const canStoreAudits = has('store_audits');
  const canPartners = has('partners');
  const canFinance = has('finance');
  const canBenefit = has('benefit');
  const canDeliveries = has('deliveries');
  const canTickets = has('tickets');
  const permsReady = profile !== null;
  const hasAnalytics = canUsers || canOrders || canPartners || canStores || canBenefit;

  const [filterForm] = Form.useForm<{
    range: [Dayjs, Dayjs];
    cityId?: string;
  }>();
  const [filters, setFilters] = useState<AnalyticsFilters>({
    granularity: 'day',
    range: defaultRange('day'),
  });
  const [analytics, setAnalytics] = useState<DashboardAnalytics | null>(null);
  const [analyticsLoading, setAnalyticsLoading] = useState(true);
  const [cities, setCities] = useState<CityOption[]>([]);
  const [metric, setMetric] = useState<ChartMetric>('total');
  const [pdfLoading, setPdfLoading] = useState(false);
  const chartsWrapRef = useRef<HTMLDivElement>(null);

  const loadVersion = useCallback(() => {
    setVersionLoading(true);
    return request<SystemVersion | null>('/admin/dashboard/version')
      .then(setVersion)
      .catch(() => setVersion(null))
      .finally(() => setVersionLoading(false));
  }, []);

  const loadAnalytics = useCallback((f: AnalyticsFilters) => {
    setAnalyticsLoading(true);
    return request<DashboardAnalytics>(`/admin/dashboard/analytics?${buildAnalyticsQs(f)}`)
      .then(setAnalytics)
      .catch((e) => {
        message.error(e instanceof Error ? e.message : '加载统计失败');
        setAnalytics(null);
      })
      .finally(() => setAnalyticsLoading(false));
  }, []);

  useEffect(() => {
    request<DashboardStats>('/admin/dashboard/stats')
      .then(setStats)
      .finally(() => setLoading(false));
    request<HqProfile>('/admin/auth/me')
      .then((p) => {
        setProfile(p);
        if (p.adminRole === 'SUPER_ADMIN') {
          void loadVersion();
        } else {
          setVersionLoading(false);
        }
      })
      .catch(() => {
        setVersionLoading(false);
      });
  }, [loadVersion]);

  useEffect(() => {
    if (!profile) return;
    void request<Paginated<CityOption>>(`/admin/cities?pageSize=${ADMIN_OPTIONS_PAGE_SIZE}`)
      .then((res) => setCities(res.items ?? []))
      .catch(() => setCities([]));
  }, [profile]);

  useEffect(() => {
    void loadAnalytics(filters);
  }, [filters, loadAnalytics]);

  function applyFilters(values: {
    range?: [Dayjs, Dayjs];
    cityId?: string;
  }) {
    setFilters((prev) => ({
      ...prev,
      range: values.range ?? prev.range,
      cityId: values.cityId || undefined,
    }));
  }

  function setGranularity(granularity: DashboardGranularity) {
    setFilters((prev) => ({ ...prev, granularity }));
  }

  function applyDatePreset(kind: 'lastWeek' | 'lastMonth' | 'lastQuarter') {
    const range = datePresetRange(kind);
    filterForm.setFieldsValue({ range });
    setFilters((prev) => ({ ...prev, range }));
  }

  function handleDeploy() {
    Modal.confirm({
      title: '确认发布更新？',
      content: '将触发服务器 webhook，拉取 auto-release.env 中配置的 GIT_BRANCH 并执行发版。发版通常需要数分钟，完成后可刷新版本信息。',
      okText: '开始发布',
      cancelText: '取消',
      onOk: async () => {
        setDeploying(true);
        try {
          const result = await request<DeployTriggerResult>('/admin/deploy/trigger', { method: 'POST' });
          message.success(result.message || '已触发发布');
        } catch (e) {
          message.error(e instanceof Error ? e.message : '触发发布失败');
          throw e;
        } finally {
          setDeploying(false);
        }
      },
    });
  }

  const shortSha = version?.commitId ? version.commitId.slice(0, 7) : '—';
  const periods = analytics?.periods ?? [];
  const chartOptions = useMemo(
    () =>
      (analytics?.charts ?? [])
        .filter((chart) => chartIsMetric(chart.key, metric))
        .map((chart) => ({
          chart,
          option: lineOption(periods, chart),
        })),
    [analytics, periods, metric],
  );

  async function handleDownloadPdf() {
    if (analyticsLoading || chartOptions.length === 0) {
      message.warning('暂无可下载的图');
      return;
    }
    const grainLabel = GRAIN_OPTIONS.find((o) => o.value === filters.granularity)?.label ?? filters.granularity;
    const metricLabel = metric === 'increment' ? '增量' : '总量';
    const cityLabel = !filters.cityId
      ? (cityScoped ? '全部负责城市' : '全部开城')
      : filters.cityId === 'none'
        ? '未选城'
        : (cities.find((c) => c.id === filters.cityId)?.name ?? '城市');
    const from = filters.range[0].format('YYYY-MM-DD');
    const to = filters.range[1].format('YYYY-MM-DD');
    setPdfLoading(true);
    try {
      const doms = [
        ...(chartsWrapRef.current?.querySelectorAll<HTMLElement>('[_echarts_instance_]') ?? []),
      ];
      await downloadDashboardChartsPdf({
        filename: `数据概览-${metricLabel}-${grainLabel}-${from}_${to}.pdf`,
        subtitle: `${metricLabel} · ${grainLabel} · ${from} ~ ${to} · ${cityLabel}`,
        charts: chartOptions.map(({ chart }, index) => ({
          title: chart.title,
          instance: doms[index] ? getInstanceByDom(doms[index]) : undefined,
        })),
      });
    } catch (e) {
      message.error(e instanceof Error ? e.message : '下载 PDF 失败');
    } finally {
      setPdfLoading(false);
    }
  }

  return (
    <div>
      <Typography.Title level={4}>
        {cityScoped ? '数据概览（负责城市）' : '数据概览'}
      </Typography.Title>

      {isSuperAdmin ? (
      <Card
        title="系统版本"
        loading={versionLoading}
        style={{ marginBottom: 24 }}
        extra={
          <Space>
            <Button icon={<ReloadOutlined />} onClick={() => void loadVersion()}>
              刷新版本
            </Button>
            <Button
              type="primary"
              icon={<CloudUploadOutlined />}
              loading={deploying}
              onClick={handleDeploy}
            >
              发布更新
            </Button>
          </Space>
        }
      >
        {version ? (
          <Descriptions column={{ xs: 1, sm: 2, lg: 3 }} size="small">
            <Descriptions.Item label="分支">{version.branch || '—'}</Descriptions.Item>
            <Descriptions.Item label="Tag">{version.gitTag || '—'}</Descriptions.Item>
            <Descriptions.Item label="Commit">
              <Typography.Text copyable={{ text: version.commitId }}>{shortSha}</Typography.Text>
            </Descriptions.Item>
            <Descriptions.Item label="提交说明" span={3}>{version.commitMessage}</Descriptions.Item>
            <Descriptions.Item label="发布时间">{fmtTime(version.deployedAt)}</Descriptions.Item>
            <Descriptions.Item label="触发来源">
              {DEPLOYED_BY_LABELS[version.deployedBy || ''] || version.deployedBy || '—'}
            </Descriptions.Item>
          </Descriptions>
        ) : (
          <Typography.Text type="secondary">尚未记录发版信息</Typography.Text>
        )}
      </Card>
      ) : null}

      <Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
        {!permsReady ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading />
          </Col>
        ) : null}
        {permsReady && canUsers ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading}>
              <Statistic title="有效用户" value={stats?.usersTotal ?? 0} />
            </Card>
          </Col>
        ) : null}
        {permsReady && canUsers ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading}>
              <Statistic title="访客（未验手机）" value={stats?.guestUsers ?? 0} valueStyle={{ color: '#faad14' }} />
            </Card>
          </Col>
        ) : null}
        {permsReady && canUsers ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading}>
              <Statistic title="已验手机" value={stats?.verifiedUsers ?? 0} valueStyle={{ color: '#52c41a' }} />
            </Card>
          </Col>
        ) : null}
        {permsReady && canOrders ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading}>
              <Statistic title="今日下单" value={stats?.ordersToday ?? 0} />
            </Card>
          </Col>
        ) : null}
        {permsReady && canStores ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading}>
              <Statistic title="门店" value={stats?.storesTotal ?? 0} />
            </Card>
          </Col>
        ) : null}
        {permsReady && canStores ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading} extra={<Link to="/stores?auditStatus=PENDING">去处理</Link>}>
              <Statistic
                title="待入驻审核"
                value={stats?.pendingStoreOnboard ?? 0}
                valueStyle={{ color: (stats?.pendingStoreOnboard ?? 0) > 0 ? '#fa8c16' : undefined }}
              />
            </Card>
          </Col>
        ) : null}
        {permsReady && canStoreAudits ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading} extra={<Link to="/store-package-audits">去处理</Link>}>
              <Statistic
                title="待套餐/信息审核"
                value={(stats?.pendingStorePackageAudits ?? 0) + (stats?.pendingStoreInfoChanges ?? 0)}
                valueStyle={{
                  color:
                    (stats?.pendingStorePackageAudits ?? 0) + (stats?.pendingStoreInfoChanges ?? 0) > 0
                      ? '#fa8c16'
                      : undefined,
                }}
              />
            </Card>
          </Col>
        ) : null}
        {permsReady && canPartners ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading}>
              <Statistic title="合伙人" value={stats?.partnersTotal ?? 0} />
            </Card>
          </Col>
        ) : null}
        {permsReady && canBenefit ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading}>
              <Statistic title="今日核销" value={stats?.redeemToday ?? 0} />
            </Card>
          </Col>
        ) : null}
        {permsReady && canDeliveries ? (
          <Col xs={24} sm={12} lg={6}>
            <Card loading={loading}>
              <Statistic title="配送单" value={stats?.deliveriesTotal ?? 0} />
            </Card>
          </Col>
        ) : null}
      </Row>

      <Card
        title="全局筛选"
        style={{ marginBottom: 24 }}
        extra={
          <Button
            icon={<ReloadOutlined />}
            size="small"
            onClick={() => void loadAnalytics(filters)}
          >
            刷新
          </Button>
        }
      >
        <Form
          form={filterForm}
          layout="inline"
          initialValues={{ range: filters.range }}
          onFinish={applyFilters}
        >
          <Form.Item label="粒度">
            <Segmented
              options={GRAIN_OPTIONS}
              value={filters.granularity}
              onChange={(v) => setGranularity(v as DashboardGranularity)}
            />
          </Form.Item>
          <Form.Item label="日期" required>
            <Space size={8} wrap>
              <Form.Item name="range" noStyle rules={[{ required: true, message: '请选择日期' }]}>
                <DatePicker.RangePicker allowClear={false} />
              </Form.Item>
              {DATE_PRESETS.map((preset) => (
                <Button key={preset.key} autoInsertSpace={false} onClick={() => applyDatePreset(preset.key)}>
                  {preset.label}
                </Button>
              ))}
            </Space>
          </Form.Item>
          <Form.Item name="cityId" label="城市">
            <Select
              allowClear
              placeholder={cityScoped ? '全部负责城市' : '全部开城'}
              style={{ width: 160 }}
              options={[
                ...(cityScoped ? [] : [{ value: 'none', label: '未选城' }]),
                ...cities.map((c) => ({ value: c.id, label: c.name })),
              ]}
            />
          </Form.Item>
          <Form.Item label="指标">
            <Segmented
              options={METRIC_OPTIONS}
              value={metric}
              onChange={(v) => setMetric(v as ChartMetric)}
            />
          </Form.Item>
          <Form.Item>
            <Button type="primary" htmlType="submit">查询</Button>
          </Form.Item>
          <Form.Item>
            <Button
              icon={<DownloadOutlined />}
              loading={pdfLoading}
              disabled={!hasAnalytics || analyticsLoading || chartOptions.length === 0}
              onClick={() => void handleDownloadPdf()}
            >
              下载PDF
            </Button>
          </Form.Item>
        </Form>
      </Card>

      {permsReady && !hasAnalytics ? (
        <Card style={{ marginBottom: 24 }}>
          <Typography.Text type="secondary">当前账号无可视指标</Typography.Text>
        </Card>
      ) : null}

      {hasAnalytics ? (
        <div ref={chartsWrapRef} style={{ marginBottom: 24 }}>
          {chartOptions.map(({ chart, option }) => (
            <Card
              key={chart.key}
              title={chart.title}
              extra={<Link to={listHref(chart.href, filters)}>查看</Link>}
              loading={analyticsLoading}
              style={{ marginBottom: 16 }}
            >
              <ReactECharts option={option} style={{ height: 320, width: '100%' }} notMerge />
            </Card>
          ))}
        </div>
      ) : null}

      {canFinance || canTickets ? (
      <Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
        {canFinance ? (
        <Col xs={24} sm={12} lg={8}>
          <Card
            loading={loading}
            title="待审核合伙人打款"
            extra={<Link to="/finance/partner-bills">去处理</Link>}
          >
            <Statistic
              value={stats?.pendingBills ?? 0}
              suffix="笔"
              valueStyle={{ color: (stats?.pendingBills ?? 0) > 0 ? '#fa8c16' : undefined }}
            />
            <Typography.Text type="secondary">
              合伙人已确认申请，待总部通过或驳回
              {(stats?.pendingPartnerDraftBills ?? 0) > 0
                ? `（另有 ${stats?.pendingPartnerDraftBills} 笔待合伙人确认）`
                : ''}
            </Typography.Text>
          </Card>
        </Col>
        ) : null}
        {canFinance ? (
        <Col xs={24} sm={12} lg={8}>
          <Card
            loading={loading}
            title="待打款门店结算"
            extra={<Link to="/finance/store-bills">去处理</Link>}
          >
            <Statistic
              value={stats?.pendingPayouts ?? 0}
              suffix="笔"
              valueStyle={{ color: (stats?.pendingPayouts ?? 0) > 0 ? '#fa8c16' : undefined }}
            />
          </Card>
        </Col>
        ) : null}
        {canFinance ? (
        <Col xs={24} sm={12} lg={8}>
          <Card
            loading={loading}
            title="待审门店提现"
            extra={<Link to="/finance/store-bills?kind=WITHDRAW">去处理</Link>}
          >
            <Statistic
              value={stats?.pendingStoreWithdrawals ?? 0}
              suffix="笔"
              valueStyle={{
                color: (stats?.overdueStoreWithdrawals ?? 0) > 0 ? '#cf1322' : (stats?.pendingStoreWithdrawals ?? 0) > 0 ? '#fa8c16' : undefined,
              }}
            />
            <Typography.Text type="secondary">
              {(stats?.overdueStoreWithdrawals ?? 0) > 0
                ? `超时未审 ${stats?.overdueStoreWithdrawals} 笔（FIN-003）`
                : '工作日 T+0 审完'}
            </Typography.Text>
          </Card>
        </Col>
        ) : null}
        {canTickets ? (
        <Col xs={24} sm={12} lg={8}>
          <Card loading={loading} title="待处理工单">
            <Statistic value={stats?.openTickets ?? 0} suffix="个" />
          </Card>
        </Col>
        ) : null}
      </Row>
      ) : null}

      {canUsers || canOrders ? (
      <Row gutter={[16, 16]}>
        {canUsers ? (
        <Col xs={24} lg={canOrders ? 12 : 24}>
          <Card title="已合并访客账号" loading={loading}>
            <Statistic value={stats?.mergedUsers ?? 0} suffix="个" />
          </Card>
        </Col>
        ) : null}
        {canOrders ? (
        <Col xs={24} lg={canUsers ? 12 : 24}>
          <Card title="订单状态分布" loading={loading}>
            <Table
              size="small"
              pagination={false}
              rowKey="status"
              dataSource={stats?.ordersByStatus ?? []}
              columns={[
                {
                  title: '状态',
                  dataIndex: 'status',
                  render: (s: string) => STATUS_LABELS[s] || s,
                },
                { title: '数量', dataIndex: 'count' },
              ]}
            />
          </Card>
        </Col>
        ) : null}
      </Row>
      ) : null}
    </div>
  );
}
