/**
 * 业务运行上下文 / 沙箱设置页面。
 *
 * 仅限超级管理员：列出门店当前模式，支持切换到 sandbox 指定历史日期或切回 live。
 * 切换会按 site_id 暂停或恢复 biz.trigger_jobs，确保多门店隔离。
 */

import React, { useEffect, useMemo, useState, useCallback } from "react";
import {
  Alert, Button, Card, DatePicker, Form, Input, Modal, Popconfirm, Space,
  Switch, Table, Tag, Tooltip, Typography, message,
} from "antd";
import { ReloadOutlined, SwapOutlined } from "@ant-design/icons";
import type { ColumnsType } from "antd/es/table";
import dayjs, { type Dayjs } from "dayjs";
import {
  fetchRuntimeSites, switchRuntimeContext,
  type RuntimeSiteItem, type RuntimeMode, type RuntimeTransitionStep,
} from "../api/runtimeContext";
import { useAuthStore } from "../store/authStore";

const { Title, Text } = Typography;

interface SwitchFormValues {
  mode: RuntimeMode;
  sandbox_date: Dayjs | null;
  reset_sandbox: boolean;
  reason: string;
}

const stepStatusColor: Record<RuntimeTransitionStep["status"], string> = {
  success: "green",
  skipped: "default",
  warning: "orange",
  failed: "red",
};

const RuntimeContextPage: React.FC = () => {
  const user = useAuthStore((s) => s.user);
  const isSuperAdmin = user?.roles?.includes("super_admin") ?? false;

  const [sites, setSites] = useState<RuntimeSiteItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [switchTarget, setSwitchTarget] = useState<RuntimeSiteItem | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [stepsModal, setStepsModal] = useState<{ siteName: string; steps: RuntimeTransitionStep[] } | null>(null);
  const [form] = Form.useForm<SwitchFormValues>();

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const data = await fetchRuntimeSites();
      setSites(data);
    } catch {
      message.error("加载门店运行上下文失败");
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    if (isSuperAdmin) {
      load();
    }
  }, [isSuperAdmin, load]);

  const openSwitch = (record: RuntimeSiteItem, mode: RuntimeMode) => {
    setSwitchTarget(record);
    form.resetFields();
    form.setFieldsValue({
      mode,
      sandbox_date: record.sandbox_date ? dayjs(record.sandbox_date) : null,
      reset_sandbox: true,
      reason: "",
    });
  };

  const handleSubmit = async () => {
    if (!switchTarget) return;
    let values: SwitchFormValues;
    try {
      values = await form.validateFields();
    } catch {
      return;
    }
    setSubmitting(true);
    try {
      const resp = await switchRuntimeContext({
        site_id: switchTarget.site_id,
        mode: values.mode,
        sandbox_date: values.mode === "sandbox" ? values.sandbox_date?.format("YYYY-MM-DD") : null,
        reset_sandbox: values.mode === "sandbox" ? values.reset_sandbox : true,
        reason: values.reason || null,
      });
      message.success(values.mode === "sandbox" ? "已切换为沙箱模式" : "已切回 live 模式");
      setStepsModal({
        siteName: switchTarget.site_name || `#${switchTarget.site_id}`,
        steps: resp.steps,
      });
      setSwitchTarget(null);
      form.resetFields();
      load();
    } catch (err: unknown) {
      const msg = (err as { response?: { data?: { detail?: string } } })?.response?.data?.detail;
      message.error(msg || "切换失败");
    } finally {
      setSubmitting(false);
    }
  };

  const columns: ColumnsType<RuntimeSiteItem> = useMemo(
    () => [
      {
        title: "门店",
        key: "site",
        width: 200,
        render: (_: unknown, r) => (
          <Space direction="vertical" size={0}>
            <Text strong>{r.site_name || `#${r.site_id}`}</Text>
            <Text type="secondary" style={{ fontSize: 12 }}>
              {r.site_code ? `${r.site_code} · ` : ""}site_id={r.site_id}
            </Text>
          </Space>
        ),
      },
      {
        title: "运行模式",
        key: "mode",
        width: 140,
        render: (_: unknown, r) => {
          const mode = (r.mode ?? "live") as RuntimeMode;
          return mode === "sandbox" ? (
            <Tag color="purple">沙箱模式</Tag>
          ) : (
            <Tag color="blue">正式 live</Tag>
          );
        },
      },
      {
        title: "业务日期",
        key: "business_date",
        width: 160,
        render: (_: unknown, r) =>
          r.mode === "sandbox" && r.sandbox_date ? (
            <Tooltip title="沙箱模拟的业务日期">
              <Tag color="purple">{r.sandbox_date}</Tag>
            </Tooltip>
          ) : (
            <Text type="secondary">真实日期</Text>
          ),
      },
      {
        title: "沙箱实例",
        dataIndex: "sandbox_instance_id",
        key: "sandbox_instance_id",
        width: 240,
        render: (v: string | null) => (v ? <Text code>{v}</Text> : "—"),
      },
      {
        title: "AI 模式",
        dataIndex: "ai_mode",
        key: "ai_mode",
        width: 100,
        render: (v: string | null) => v ?? "live",
      },
      {
        title: "更新时间",
        dataIndex: "updated_at",
        key: "updated_at",
        width: 170,
        render: (v: string | null) => (v ? dayjs(v).format("YYYY-MM-DD HH:mm") : "—"),
      },
      {
        title: "操作",
        key: "action",
        fixed: "right",
        width: 220,
        render: (_: unknown, r) => {
          const mode = (r.mode ?? "live") as RuntimeMode;
          if (mode === "sandbox") {
            return (
              <Space>
                <Button size="small" icon={<SwapOutlined />} onClick={() => openSwitch(r, "sandbox")}>
                  调整沙箱
                </Button>
                <Popconfirm
                  title="确认切回 live 模式？"
                  description="将恢复该门店触发器并清理沙箱状态。"
                  okText="切回 live"
                  cancelText="取消"
                  onConfirm={() => openSwitch(r, "live")}
                >
                  <Button size="small" danger>
                    切回 live
                  </Button>
                </Popconfirm>
              </Space>
            );
          }
          return (
            <Button size="small" type="primary" icon={<SwapOutlined />} onClick={() => openSwitch(r, "sandbox")}>
              进入沙箱
            </Button>
          );
        },
      },
    ],
    [form],
  );

  if (!isSuperAdmin) {
    return (
      <Alert
        type="warning"
        showIcon
        message="无权限"
        description="业务运行上下文/沙箱设置仅对超级管理员开放。"
      />
    );
  }

  const target = switchTarget;
  const targetMode = Form.useWatch("mode", form) ?? "live";

  return (
    <Card
      title={<Title level={4} style={{ margin: 0 }}>业务运行上下文 / 沙箱</Title>}
      extra={
        <Button icon={<ReloadOutlined />} onClick={load} loading={loading}>
          刷新
        </Button>
      }
    >
      <Alert
        type="info"
        showIcon
        style={{ marginBottom: 16 }}
        message="按门店隔离的业务时钟"
        description={
          <Space direction="vertical" size={2}>
            <Text>live 模式：使用真实系统日期，正常生产逻辑。</Text>
            <Text>
              sandbox 模式：业务上假设是 sandbox_date，按 sandbox_instance_id 隔离写入；
              切换会终止当前 ETL、取消未完成 AI 触发记录，但不会暂停全局 biz.trigger_jobs（多门店共用）。
            </Text>
            <Text type="secondary">
              真实预算、AI tokens 计费、运行日志写入时间、调度元数据仍按真实系统时间，不受沙箱影响。
            </Text>
            <Text type="warning">
              本次改造目标是让看板 / 任务 / 会员 / AI 等数据读取也按 sandbox_date 截断，
              进度详见 <Text code>docs/database/changes/2026-05-02__sandbox_no_future_data_plan.md</Text>。
            </Text>
          </Space>
        }
      />
      <Table
        rowKey="site_id"
        loading={loading}
        dataSource={sites}
        columns={columns}
        size="middle"
        pagination={false}
        scroll={{ x: 1100 }}
      />
      <Modal
        open={!!target}
        title={target ? `切换运行上下文 — ${target.site_name || `#${target.site_id}`}` : ""}
        onCancel={() => {
          if (!submitting) {
            setSwitchTarget(null);
            form.resetFields();
          }
        }}
        onOk={handleSubmit}
        okText="确认切换"
        cancelText="取消"
        confirmLoading={submitting}
        destroyOnClose
        width={640}
      >
        <Form
          layout="vertical"
          form={form}
          initialValues={{ mode: "sandbox", reset_sandbox: true, reason: "" }}
        >
          <Form.Item label="目标模式" name="mode" rules={[{ required: true }]}>
            <Input disabled />
          </Form.Item>
          {targetMode === "sandbox" && (
            <>
              <Form.Item
                label="沙箱业务日期"
                name="sandbox_date"
                rules={[{ required: true, message: "沙箱模式需要选择历史业务日期" }]}
              >
                <DatePicker
                  style={{ width: "100%" }}
                  disabledDate={(d) => d && d.isAfter(dayjs(), "day")}
                />
              </Form.Item>
              <Form.Item label="重置沙箱实例" name="reset_sandbox" valuePropName="checked">
                <Switch checkedChildren="新实例" unCheckedChildren="沿用原实例" />
              </Form.Item>
            </>
          )}
          <Form.Item label="操作原因（可选）" name="reason">
            <Input.TextArea rows={2} maxLength={500} showCount placeholder="例如：演示按 2026-03-15 重放任务分发" />
          </Form.Item>
        </Form>
      </Modal>
      <Modal
        open={!!stepsModal}
        title={stepsModal ? `切换执行结果 — ${stepsModal.siteName}` : ""}
        onCancel={() => setStepsModal(null)}
        onOk={() => setStepsModal(null)}
        okText="知道了"
        cancelButtonProps={{ style: { display: "none" } }}
        width={640}
        destroyOnClose
      >
        <Space direction="vertical" size={8} style={{ width: "100%" }}>
          {(stepsModal?.steps ?? []).map((s) => (
            <div key={s.key}>
              <Tag color={stepStatusColor[s.status]}>{s.title}</Tag>
              {s.count ? <Text type="secondary">影响 {s.count} 条</Text> : null}
              <Text style={{ marginLeft: 8 }}>{s.detail}</Text>
            </div>
          ))}
        </Space>
      </Modal>
    </Card>
  );
};

export default RuntimeContextPage;
