'use client';

import { useEffect, useState } from 'react';
import {
  Button,
  Card,
  Checkbox,
  Col,
  InputNumber,
  Popconfirm,
  Radio,
  Row,
  Select,
  Space,
  Spin,
  Tag,
  Tooltip,
  message,
} from 'antd';
import { api, errMsg } from '@/lib/api';

interface StatItem {
  metric: string; // help_users / total_compares / total_saved
  label: string; // 帮助用户 / 完成比价 / 累计节省
  unit: string; // 人 / 次 / 分
  mode: 'real' | 'manual' | 'random';
  manual_value: number | null;
  random_mult_min: number; // 千分比 1000=1.0
  random_mult_max: number;
  random_tick_seconds: number;
  random_anchor_minutes: number; // 触发时刻对齐偏移(距 0 点分钟数)
  random_kind: 'mult' | 'add'; // 自增长方式:×倍率 / +绝对增量
  random_step_min: number; // 绝对增量区间(基础单位)
  random_step_max: number;
  real_offset: number; // 真实值基数偏移(基础单位)
  allow_decrease: boolean; // 是否允许展示值下降
  random_current: number | null;
  random_last_tick_at: string | null;
  real_value: number; // 当前真实值(基础单位:total_saved 为分;不含偏移)
  updated_at: string | null;
}

type IntervalUnit = 'minute' | 'hour' | 'day';
const UNIT_SECONDS: Record<IntervalUnit, number> = { minute: 60, hour: 3600, day: 86400 };

// 间隔秒数 → 数值 + 单位(取最大的整除单位)
function decomposeInterval(sec: number): { num: number; unit: IntervalUnit } {
  if (sec % 86400 === 0) return { num: sec / 86400, unit: 'day' };
  if (sec % 3600 === 0) return { num: sec / 3600, unit: 'hour' };
  return { num: Math.max(1, Math.round(sec / 60)), unit: 'minute' };
}

// 每个指标的本地编辑态(均以「展示单位」存:倍率用浮点,total_saved 用元)
interface Edit {
  mode: 'real' | 'manual' | 'random';
  manual: number | null; // 展示单位
  realOffset: number; // 真实值偏移(展示单位)
  growthKind: 'mult' | 'add'; // 自增长方式
  multMin: number; // 1.0 ~
  multMax: number;
  stepMin: number; // 绝对增量下限(展示单位)
  stepMax: number;
  intervalNum: number; // 更新间隔数值
  intervalUnit: IntervalUnit; // 分钟/小时/天
  anchorHour: number; // 单位=天时的「每日时刻」时(0-23)
  anchorMinute: number; // 天:每日时刻分 / 小时:每小时第几分(0-59)
  allowDecrease: boolean; // 允许展示值下降(默认 false)
  initial: number | null; // 切 random 的初始基数(展示单位),留空=用真实值播种
}

const isMoney = (metric: string) => metric === 'total_saved';
const dispUnit = (metric: string) => (isMoney(metric) ? '元' : '');

// 基础单位 → 展示单位
function baseToDisp(metric: string, v: number | null): number | null {
  if (v == null) return null;
  return isMoney(metric) ? v / 100 : v;
}
// 展示单位 → 基础单位(整数)
function dispToBase(metric: string, v: number | null): number | null {
  if (v == null) return null;
  return isMoney(metric) ? Math.round(v * 100) : Math.round(v);
}

function toEdit(it: StatItem): Edit {
  const { num, unit } = decomposeInterval(it.random_tick_seconds);
  const anchor = it.random_anchor_minutes || 0;
  return {
    mode: it.mode,
    manual: baseToDisp(it.metric, it.manual_value),
    realOffset: (baseToDisp(it.metric, it.real_offset) as number) ?? 0,
    growthKind: it.random_kind === 'add' ? 'add' : 'mult',
    multMin: it.random_mult_min / 1000,
    multMax: it.random_mult_max / 1000,
    stepMin: (baseToDisp(it.metric, it.random_step_min) as number) ?? 0,
    stepMax: (baseToDisp(it.metric, it.random_step_max) as number) ?? 0,
    intervalNum: num,
    intervalUnit: unit,
    anchorHour: Math.floor(anchor / 60),
    anchorMinute: anchor % 60,
    allowDecrease: it.allow_decrease,
    initial: null,
  };
}

function fmtReal(it: StatItem): string {
  const v = baseToDisp(it.metric, it.real_value);
  return isMoney(it.metric) ? `${(v as number).toFixed(1)} 元` : `${v} ${it.unit}`;
}

function fmtDisp(metric: string, base: number, unit: string): string {
  const v = baseToDisp(metric, base);
  return `${v} ${dispUnit(metric) || unit}`;
}

// 下次刷新「预计值」(基于已保存配置,经只增不减护栏):自增长给区间,真实/自定义给目标值。
function predictNext(it: StatItem): string | null {
  const cur = it.random_current;
  if (cur == null) return null;
  const u = dispUnit(it.metric) || it.unit;
  const d = (v: number) => baseToDisp(it.metric, v);
  if (it.mode === 'random') {
    if (it.random_kind === 'add') {
      return `${d(cur + it.random_step_min)} ~ ${d(cur + it.random_step_max)} ${u}`;
    }
    const lo = Math.floor((cur * it.random_mult_min) / 1000);
    const hi = Math.floor((cur * it.random_mult_max) / 1000);
    return `${d(lo)} ~ ${d(hi)} ${u}`;
  }
  const target = it.mode === 'real' ? it.real_value + it.real_offset : it.manual_value ?? cur;
  const eff = !it.allow_decrease && target < cur ? cur : target;
  return `${it.mode === 'real' ? '≈ ' : ''}${d(eff)} ${u}`;
}

// 下个「更新时刻」(北京时间)文案:边界 = 北京时间 anchor + k*interval(与后端 _refresh 对齐)
function nextRefreshLabel(tickSeconds: number, anchorMinutes: number): string {
  const BJ = 8 * 3600;
  const interval = Math.max(60, tickSeconds);
  const anchorSec = ((anchorMinutes * 60) % interval + interval) % interval;
  const bjNow = Math.floor(Date.now() / 1000) + BJ;
  const k = Math.floor((bjNow - anchorSec) / interval) + 1;
  const nextUtcMs = (anchorSec + k * interval - BJ) * 1000;
  return new Date(nextUtcMs).toLocaleString('zh-CN', {
    timeZone: 'Asia/Shanghai',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
  });
}

/** 首页三门面数字(帮助用户/完成比价/累计节省)的展示模式配置。作为「数据大盘」页的一个区块。 */
export default function HomeStatsConfig() {
  const [items, setItems] = useState<StatItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [edits, setEdits] = useState<Record<string, Edit>>({});
  const [saving, setSaving] = useState<string | null>(null);

  // 首次加载:带 Spin,并初始化输入态 edits。
  const load = async () => {
    setLoading(true);
    try {
      const { data } = await api.get<StatItem[]>('/admin/api/dashboard-display');
      setItems(data);
      setEdits(Object.fromEntries(data.map((i) => [i.metric, toEdit(i)])));
    } finally {
      setLoading(false);
    }
  };

  // 静默刷新:只更新展示数据(items),不动 edits(不覆盖正在输入的内容)、不弹 Spin。
  const silentLoad = async () => {
    try {
      const { data } = await api.get<StatItem[]>('/admin/api/dashboard-display');
      setItems(data);
    } catch {
      /* 轮询失败忽略,下次再拉 */
    }
  };

  useEffect(() => {
    load();
    const timer = setInterval(silentLoad, 3000); // 每 3s 静默刷新展示值
    return () => clearInterval(timer);
  }, []);

  const patch = (metric: string, p: Partial<Edit>) =>
    setEdits((s) => ({ ...s, [metric]: { ...s[metric], ...p } }));

  // immediate=true:点「立即更新」,保存配置 + 马上刷新展示值(不等更新钟点)。
  const save = async (it: StatItem, immediate = false) => {
    const e = edits[it.metric];
    // 自定义不暴露间隔,固定为每天(每日「更新时间」刷新一次);其余模式用所选间隔。
    const intervalSec =
      e.mode === 'manual'
        ? 86400
        : Math.max(60, Math.round(e.intervalNum) * UNIT_SECONDS[e.intervalUnit]);
    const anchorMin = e.anchorHour * 60 + e.anchorMinute; // 更新时间(全天 HH:MM),后端按间隔取相位
    const body: Record<string, number | string | boolean> = {
      mode: e.mode,
      random_mult_min: Math.round(e.multMin * 1000),
      random_mult_max: Math.round(e.multMax * 1000),
      random_tick_seconds: intervalSec,
      random_anchor_minutes: anchorMin,
      random_kind: e.growthKind,
      random_step_min: (dispToBase(it.metric, e.stepMin) as number) ?? 0,
      random_step_max: (dispToBase(it.metric, e.stepMax) as number) ?? 0,
      real_offset: (dispToBase(it.metric, e.realOffset) as number) ?? 0,
      allow_decrease: e.allowDecrease,
    };
    if (e.manual != null) body.manual_value = dispToBase(it.metric, e.manual) as number;
    if (e.initial != null) body.random_initial = dispToBase(it.metric, e.initial) as number;
    if (immediate) body.apply_now = true;

    setSaving(it.metric);
    try {
      // PATCH 返回更新后的该指标;只就地替换这一项 + 重置它的输入态,不整页 reload(消除闪烁)。
      const { data } = await api.patch<StatItem>(`/admin/api/dashboard-display/${it.metric}`, body);
      setItems((prev) => prev.map((x) => (x.metric === it.metric ? data : x)));
      setEdits((s) => ({ ...s, [it.metric]: toEdit(data) }));
      if (immediate) {
        message.success('已立即更新,客户端下次进首页即可见');
      } else {
        const lastTickMs = data.random_last_tick_at ? new Date(data.random_last_tick_at).getTime() : 0;
        const effectiveNow = Date.now() - lastTickMs < 10_000;
        message.success(
          effectiveNow
            ? '已保存,客户端下次进首页即可见'
            : `已保存,展示值将于北京时间 ${nextRefreshLabel(data.random_tick_seconds, data.random_anchor_minutes)} 刷新后生效`,
        );
      }
    } catch (err) {
      message.error(errMsg(err));
    } finally {
      setSaving(null);
    }
  };

  return (
    <div style={{ marginTop: 24 }}>
      <h3 style={{ marginBottom: 4 }}>首页数据配置</h3>
      <p style={{ color: '#999', marginTop: 0 }}>
        客户端首页三个门面数字。每个指标独立选模式:<b>真实值</b>(实时查库,可加基数偏移)/{' '}
        <b>自定义</b>(固定值)/ <b>自增长</b>(到对齐钟点按倍率或固定增量增长)。
        默认<b>只增不减</b>(防门面缩水);每次改动进审计日志。
      </p>
      {loading ? (
        <Spin style={{ display: 'block', marginTop: 24 }} />
      ) : (
        <Row gutter={[16, 16]} align="top">
          {items.map((it) => {
            const e = edits[it.metric];
            if (!e) return null;
            const u = dispUnit(it.metric) || it.unit;
            // manual 下调但未允许下降 → 提示会被护栏挡住
            const manualBlocked =
              e.mode === 'manual' &&
              !e.allowDecrease &&
              e.manual != null &&
              it.random_current != null &&
              (dispToBase(it.metric, e.manual) as number) < it.random_current;
            return (
              <Col key={it.metric} xs={24} md={12} xl={8}>
                <Card
                  size="small"
                  title={
                    <span>
                      {it.label}
                      <span style={{ color: '#999', fontWeight: 400, marginLeft: 8, fontSize: 13 }}>
                        当前真实值:{fmtReal(it)}
                      </span>
                    </span>
                  }
                  style={{ height: '100%' }}
                >
                  <Space direction="vertical" size="middle" style={{ width: '100%' }}>
                    <Radio.Group
                      value={e.mode}
                      onChange={(ev) => patch(it.metric, { mode: ev.target.value })}
                      optionType="button"
                      buttonStyle="solid"
                    >
                      <Radio.Button value="real">真实值</Radio.Button>
                      <Radio.Button value="manual">自定义</Radio.Button>
                      <Radio.Button value="random">自增长</Radio.Button>
                    </Radio.Group>

                    {e.mode === 'manual' && (
                      <div>
                        <Space>
                          <span>固定值:</span>
                          <InputNumber
                            value={e.manual}
                            min={0}
                            onChange={(v) => patch(it.metric, { manual: v })}
                            style={{ width: 200 }}
                          />
                          <span style={{ color: '#666' }}>{u}</span>
                        </Space>
                        {manualBlocked && (
                          <div style={{ color: '#fa8c16', fontSize: 12, marginTop: 4 }}>
                            低于当前展示值,默认不下调(如需下调请勾「允许数字下降」)
                          </div>
                        )}
                      </div>
                    )}

                    {e.mode === 'real' && (
                      <Space wrap>
                        <span>基数偏移:</span>
                        <InputNumber
                          value={e.realOffset}
                          min={0}
                          onChange={(v) => patch(it.metric, { realOffset: v ?? 0 })}
                          style={{ width: 160 }}
                        />
                        <span style={{ color: '#666' }}>{u}</span>
                        <Tooltip title="展示值 = 真实值 + 此基数。冷启动期真实数字小,加个体面的基数,且仍随真实增长。">
                          <span style={{ color: '#999', cursor: 'help' }}>ⓘ</span>
                        </Tooltip>
                      </Space>
                    )}

                    {e.mode === 'random' && (
                      <>
                        <Space wrap>
                          <span>增长方式:</span>
                          <Radio.Group
                            value={e.growthKind}
                            size="small"
                            onChange={(ev) => patch(it.metric, { growthKind: ev.target.value })}
                            optionType="button"
                          >
                            <Radio.Button value="mult">百分比</Radio.Button>
                            <Radio.Button value="add">固定增量</Radio.Button>
                          </Radio.Group>
                        </Space>
                        {e.growthKind === 'mult' ? (
                          <Space wrap>
                            <span>倍率区间:</span>
                            <InputNumber
                              value={e.multMin}
                              min={1.0}
                              max={1.5}
                              step={0.01}
                              onChange={(v) => patch(it.metric, { multMin: v ?? 1.0 })}
                              style={{ width: 90 }}
                            />
                            <span>~</span>
                            <InputNumber
                              value={e.multMax}
                              min={1.0}
                              max={1.5}
                              step={0.01}
                              onChange={(v) => patch(it.metric, { multMax: v ?? 1.0 })}
                              style={{ width: 90 }}
                            />
                            <Tooltip title="倍率 1.0~1.5,每次更新随机取区间内一个倍率相乘(只增不减)。">
                              <span style={{ color: '#999', cursor: 'help' }}>ⓘ</span>
                            </Tooltip>
                          </Space>
                        ) : (
                          <Space wrap>
                            <span>每次新增:</span>
                            <InputNumber
                              value={e.stepMin}
                              min={0}
                              onChange={(v) => patch(it.metric, { stepMin: v ?? 0 })}
                              style={{ width: 90 }}
                            />
                            <span>~</span>
                            <InputNumber
                              value={e.stepMax}
                              min={0}
                              onChange={(v) => patch(it.metric, { stepMax: v ?? 0 })}
                              style={{ width: 90 }}
                            />
                            <span style={{ color: '#666' }}>{u}</span>
                            <Tooltip title="每个更新周期随机 +[下限,上限](绝对增量),比百分比更可控、更像真实日增。">
                              <span style={{ color: '#999', cursor: 'help' }}>ⓘ</span>
                            </Tooltip>
                          </Space>
                        )}
                      </>
                    )}

                    {/* 到「更新时间」按「更新间隔」刷新一次。自定义不显示间隔(固定每天该时刻)。 */}
                    {e.mode !== 'manual' && (
                      <Space wrap>
                        <span>更新间隔:每</span>
                        <InputNumber
                          value={e.intervalNum}
                          min={1}
                          onChange={(v) => patch(it.metric, { intervalNum: v ?? 1 })}
                          style={{ width: 80 }}
                        />
                        <Select
                          value={e.intervalUnit}
                          style={{ width: 90 }}
                          onChange={(unit) => patch(it.metric, { intervalUnit: unit as IntervalUnit })}
                          options={[
                            { value: 'minute', label: '分钟' },
                            { value: 'hour', label: '小时' },
                            { value: 'day', label: '天' },
                          ]}
                        />
                      </Space>
                    )}
                    <Space wrap>
                      <span>更新时间:</span>
                      <InputNumber
                        value={e.anchorHour}
                        min={0}
                        max={23}
                        onChange={(v) => patch(it.metric, { anchorHour: v ?? 0 })}
                        style={{ width: 64 }}
                      />
                      <span>时</span>
                      <InputNumber
                        value={e.anchorMinute}
                        min={0}
                        max={59}
                        onChange={(v) => patch(it.metric, { anchorMinute: v ?? 0 })}
                        style={{ width: 64 }}
                      />
                      <span>分</span>
                      <Tooltip title="到北京时间这个钟点(按间隔重复)刷新一次。按天=每日该时刻;按时/分=该时刻在周期内的相位。">
                        <span style={{ color: '#999', cursor: 'help' }}>ⓘ</span>
                      </Tooltip>
                    </Space>

                    {e.mode === 'random' && (
                      <Space wrap>
                        <span>初始基数:</span>
                        <InputNumber
                          value={e.initial}
                          min={0}
                          onChange={(v) => patch(it.metric, { initial: v })}
                          style={{ width: 200 }}
                          placeholder="留空=用真实值播种"
                        />
                        <span style={{ color: '#666' }}>{u}</span>
                      </Space>
                    )}

                    <Checkbox
                      checked={e.allowDecrease}
                      onChange={(ev) => patch(it.metric, { allowDecrease: ev.target.checked })}
                    >
                      允许数字下降{' '}
                      <span style={{ color: '#999' }}>(默认关闭 = 只增不减,防门面缩水)</span>
                    </Checkbox>

                    <Space direction="vertical" size={2} style={{ color: '#888', fontSize: 12 }}>
                      <Space wrap size="large">
                        <span>
                          当前展示值:
                          {it.random_current == null ? '未启动' : fmtDisp(it.metric, it.random_current, it.unit)}
                        </span>
                        {it.updated_at && (
                          <span style={{ color: '#bbb' }}>
                            更新于 {new Date(it.updated_at).toLocaleString('zh-CN')}
                          </span>
                        )}
                      </Space>
                      {predictNext(it) && (
                        <span>
                          下次预计:{predictNext(it)}
                          <span style={{ color: '#bbb' }}>
                            {'  '}(北京 {nextRefreshLabel(it.random_tick_seconds, it.random_anchor_minutes)} 刷新)
                          </span>
                        </span>
                      )}
                    </Space>

                    <Space>
                      <Button type="primary" loading={saving === it.metric} onClick={() => save(it)}>
                        保存
                      </Button>
                      <Popconfirm
                        title="立即更新会马上推进一次(自增长走一档),不等更新时间。确定?"
                        onConfirm={() => save(it, true)}
                      >
                        <Button loading={saving === it.metric}>立即更新</Button>
                      </Popconfirm>
                      <Tag color={it.mode === 'real' ? 'green' : it.mode === 'manual' ? 'orange' : 'blue'}>
                        线上当前:
                        {it.mode === 'real' ? '真实值' : it.mode === 'manual' ? '自定义' : '自增长'}
                      </Tag>
                    </Space>
                  </Space>
                </Card>
              </Col>
            );
          })}
        </Row>
      )}
    </div>
  );
}
