const { useEffect, useMemo, useState } = React;
const {
  Button, Input, InputNumber, Select, Table, Modal, Form, Pagination,
  DatePicker, Checkbox, Space, Tag,
} = antd;
const { RangePicker } = DatePicker;
const { TextArea } = Input;

const OP_CONFIRM = {
  delete: { title: "删除确认", okText: "删除", message: (r) => "确认删除活动「" + r.name + "」？删除后列表不再展示。" },
  pause: { title: "暂停确认", okText: "暂停", message: (r) => "确认暂停活动「" + r.name + "」？暂停后规则将停止执行。" },
  offline: { title: "下线确认", okText: "下线", message: (r) => "确认下线活动「" + r.name + "」？下线后状态变为已结束。" },
  enable: { title: "启用确认", okText: "启用", message: (r) => "确认启用活动「" + r.name + "」？启用后将恢复为进行中。" },
};

function toDayjs(v) {
  if (!v) return null;
  const d = dayjs(String(v).replace(" ", "T"));
  return d.isValid() ? d : null;
}

function toDatetimeLocal(v) {
  if (!v) return "";
  return String(v).replace(" ", "T").slice(0, 16);
}

function fromDatetimeLocal(v) {
  if (!v) return "";
  let s = String(v).replace("T", " ");
  if (/^\d{4}-\d{2}-\d{2}$/.test(s)) s += " 00:00:00";
  else if (s.length === 16) s += ":00";
  return s;
}

function formatCycleRange(start, end) {
  if (!start && !end) return "-";
  return (start || "-") + " - " + (end || "-");
}

function blankForm() {
  return {
    name: "",
    type: "",
    cycleStart: "",
    cycleEnd: "",
    subsidyCap: "",
    scopePay: true,
    scopeCoupon: false,
    formPoint: true,
    formCoupon: false,
    groups: [SPData.emptyGroup()],
  };
}

function activityToForm(a) {
  const groups = a.groups && a.groups.length
    ? structuredClone(a.groups).map((g) => ({
        ...g,
        plazaRatio: g.plazaRatio != null ? g.plazaRatio : 100,
        merchantRatio: g.merchantRatio != null ? Number(g.merchantRatio) : 0,
        thirdRatio: g.thirdRatio != null ? Number(g.thirdRatio) : 0,
        stores: (g.stores || []).map((s) => ({
          ...s,
          plazaCap: s.plazaCap != null ? s.plazaCap : "",
          orderCapRate: s.orderCapRate != null ? s.orderCapRate : "",
        })),
      }))
    : [SPData.emptyGroup()];
  return {
    name: a.name || "",
    type: a.type || "档期活动",
    cycleStart: toDatetimeLocal(a.cycleStart),
    cycleEnd: toDatetimeLocal(a.cycleEnd),
    subsidyCap: a.subsidyCap != null ? a.subsidyCap : "",
    scopePay: a.scopePay !== false,
    scopeCoupon: !!a.scopeCoupon,
    formPoint: a.formPoint !== false,
    formCoupon: !!a.formCoupon,
    groups,
  };
}

function ActivityListPage({ state, update, toast }) {
  const emptyQ = { id: "", name: "", plaza: null, status: "all", cycleStart: "", cycleEnd: "", createdStart: "", createdEnd: "" };
  const [draft, setDraft] = useState(emptyQ);
  const [q, setQ] = useState(emptyQ);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(10);

  const filtered = useMemo(() => {
    return SPData.visibleActivities(state.activities).filter((a) => {
      if (q.id && !a.id.toLowerCase().includes(q.id.trim().toLowerCase())) return false;
      if (q.name && !a.name.includes(q.name.trim())) return false;
      if (q.plaza) {
        const matchId = q.plaza.plazaId && a.plazaId === q.plaza.plazaId;
        const matchName = q.plaza.label && a.plazaName === q.plaza.label;
        if (!matchId && !matchName) return false;
      }
      if (q.status !== "all" && a.status !== q.status) return false;
      if (q.cycleStart && a.cycleEnd < q.cycleStart) return false;
      if (q.cycleEnd && a.cycleStart > q.cycleEnd + " 23:59:59") return false;
      if (q.createdStart && a.createdAt < q.createdStart) return false;
      if (q.createdEnd && a.createdAt > q.createdEnd + " 23:59:59") return false;
      return true;
    });
  }, [state.activities, q]);

  const rows = filtered.slice((page - 1) * pageSize, page * pageSize);

  const patchStatus = (row, status, tip) => {
    update((s) => ({
      ...s,
      activities: s.activities.map((a) => (a.id === row.id ? { ...a, status } : a)),
    }));
    toast(tip);
  };

  const askConfirm = (type, row) => {
    const meta = OP_CONFIRM[type];
    Modal.confirm({
      title: meta.title,
      content: meta.message(row),
      okText: meta.okText,
      cancelText: "取消",
      onOk: () => {
        if (type === "delete") patchStatus(row, "deleted", "活动已删除");
        else if (type === "pause") patchStatus(row, "paused", "活动已暂停");
        else if (type === "offline") patchStatus(row, "ended", "活动已下线");
        else if (type === "enable") patchStatus(row, "active", "活动已启用");
      },
    });
  };

  const columns = [
    { title: "活动ID", dataIndex: "id", key: "id", width: 170, ellipsis: true },
    { title: "活动名称", dataIndex: "name", key: "name", width: 180, ellipsis: true },
    {
      title: "活动周期",
      key: "cycle",
      width: 320,
      ellipsis: true,
      render: (_, row) => row.cycleStart + " 至 " + row.cycleEnd,
    },
    { title: "活动类型", dataIndex: "type", key: "type", width: 100 },
    { title: "广场ID", dataIndex: "plazaId", key: "plazaId", width: 100 },
    { title: "广场名称", dataIndex: "plazaName", key: "plazaName", width: 150, ellipsis: true },
    {
      title: "关联门店数",
      key: "storeCount",
      width: 110,
      render: (_, row) => (row.groups || []).reduce((n, g) => n + (g.stores || []).length, 0) || row.storeCount || 0,
    },
    { title: "状态", dataIndex: "status", key: "status", width: 100, render: (s) => <StatusTag status={s} /> },
    { title: "创建时间", dataIndex: "createdAt", key: "createdAt", width: 180 },
    { title: "创建人", dataIndex: "creator", key: "creator", width: 90 },
    {
      title: "操作",
      key: "ops",
      fixed: "right",
      width: 200,
      render: (_, row) => {
        const ops = SPData.opsForStatus(row.status);
        return (
          <div className="table-ops">
            {ops.includes("view") ? <Button type="link" size="small" onClick={() => navigate("sp/activity/view/" + row.id)}>查看</Button> : null}
            {ops.includes("edit") ? <Button type="link" size="small" onClick={() => navigate("sp/activity/edit/" + row.id)}>修改</Button> : null}
            {ops.includes("delete") ? <Button type="link" size="small" onClick={() => askConfirm("delete", row)}>删除</Button> : null}
            {ops.includes("pause") ? <Button type="link" size="small" onClick={() => askConfirm("pause", row)}>暂停</Button> : null}
            {ops.includes("enable") ? <Button type="link" size="small" onClick={() => askConfirm("enable", row)}>启用</Button> : null}
            {ops.includes("offline") ? <Button type="link" size="small" onClick={() => askConfirm("offline", row)}>下线</Button> : null}
            {ops.includes("data") ? (
              <Button type="link" size="small" onClick={() => navigate("sp/activity-data/board/" + row.id)}>活动数据</Button>
            ) : null}
            {ops.includes("recon") ? (
              <Button type="link" size="small" onClick={() => { navigate("sp/recon"); toast("已跳转对账单管理"); }}>查看对账</Button>
            ) : null}
          </div>
        );
      },
    },
  ];

  return (
    <div data-screen-label="page-activity-list">
      <div className="panel search-panel">
        <div className="filters">
          <div className="field">
            <label>活动ID</label>
            <Input value={draft.id} placeholder="请输入活动ID" onChange={(e) => setDraft({ ...draft, id: e.target.value })} />
          </div>
          <div className="field">
            <label>活动名称</label>
            <Input value={draft.name} placeholder="请输入活动名称" onChange={(e) => setDraft({ ...draft, name: e.target.value })} />
          </div>
          <div className="field">
            <label>活动周期</label>
            <RangePicker
              style={{ width: "100%" }}
              value={[toDayjs(draft.cycleStart), toDayjs(draft.cycleEnd)]}
              onChange={(dates) => {
                setDraft({
                  ...draft,
                  cycleStart: dates && dates[0] ? dates[0].format("YYYY-MM-DD") : "",
                  cycleEnd: dates && dates[1] ? dates[1].format("YYYY-MM-DD") : "",
                });
              }}
            />
          </div>
          <div className="field">
            <label>创建时间</label>
            <RangePicker
              style={{ width: "100%" }}
              value={[toDayjs(draft.createdStart), toDayjs(draft.createdEnd)]}
              onChange={(dates) => {
                setDraft({
                  ...draft,
                  createdStart: dates && dates[0] ? dates[0].format("YYYY-MM-DD") : "",
                  createdEnd: dates && dates[1] ? dates[1].format("YYYY-MM-DD") : "",
                });
              }}
            />
          </div>
          <div className="field">
            <label>广场名称</label>
            <PlazaCascader value={draft.plaza} onChange={(plaza) => setDraft({ ...draft, plaza })} placeholder="请选择" />
          </div>
          <div className="field">
            <label>状态</label>
            <Select
              style={{ width: "100%" }}
              value={draft.status}
              onChange={(v) => setDraft({ ...draft, status: v })}
              options={[
                { value: "all", label: "请选择状态" },
                ...Object.entries(SPData.STATUS_FILTER).map(([k, v]) => ({ value: k, label: v.label })),
              ]}
            />
          </div>
          <Space className="filter-actions">
            <Button onClick={() => { setDraft(emptyQ); setQ(emptyQ); setPage(1); }}>重 置</Button>
            <Button type="primary" onClick={() => { setQ(draft); setPage(1); toast("查询完成"); }}>查 询</Button>
          </Space>
        </div>
      </div>

      <div className="toolbar">
        <Button onClick={() => navigate("sp/activity-data/tasks")}>我的任务</Button>
        <Button type="primary" onClick={() => navigate("sp/activity/create")}>新建SP活动</Button>
      </div>

      <div className="table-panel">
        <Table
          rowKey="id"
          size="middle"
          columns={columns}
          dataSource={rows}
          pagination={false}
          scroll={{ x: 1640 }}
          locale={{ emptyText: "暂无数据" }}
          className="activity-list-table"
        />
        <div className="pager-bar">
          <Pagination
            current={page}
            pageSize={pageSize}
            total={filtered.length}
            showTotal={(t) => `共 ${t} 条记录`}
            showSizeChanger
            showQuickJumper
            pageSizeOptions={["10", "20", "50"]}
            onChange={(p, ps) => {
              setPage(p);
              if (ps !== pageSize) {
                setPageSize(ps);
                setPage(1);
              }
            }}
          />
        </div>
      </div>
    </div>
  );
}

function StorePicker({ selectedIds, existingStores, onClose, onConfirm }) {
  const [nameQ, setNameQ] = useState("");
  const [idQ, setIdQ] = useState("");
  const [applied, setApplied] = useState({ name: "", id: "" });
  const [picked, setPicked] = useState(selectedIds || []);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(10);

  const filtered = useMemo(() => {
    return SPData.STORES.filter((s) => {
      if (applied.name && !s.name.includes(applied.name)) return false;
      if (applied.id && !String(s.id).includes(applied.id)) return false;
      return true;
    });
  }, [applied]);

  const pageRows = useMemo(() => {
    const start = (page - 1) * pageSize;
    return filtered.slice(start, start + pageSize);
  }, [filtered, page, pageSize]);

  const doSearch = () => {
    setApplied({ name: nameQ.trim(), id: idQ.trim() });
    setPage(1);
  };

  const confirmPick = () => {
    const prevMap = {};
    (existingStores || []).forEach((s) => { prevMap[s.storeId] = s; });
    const stores = SPData.STORES.filter((s) => picked.includes(s.id)).map((s) => prevMap[s.id] || ({
      storeId: s.id,
      storeName: s.name,
      plazaCap: 5000,
      orderCapRate: 50,
    }));
    onConfirm(stores);
  };

  const columns = [
    {
      title: "所属广场",
      dataIndex: "plazaId",
      key: "plaza",
      render: (id) => (SPData.PLAZAS.find((p) => p.id === id) || {}).name || id,
    },
    { title: "门店名称", dataIndex: "name", key: "name" },
    { title: "门店ID", dataIndex: "id", key: "id" },
    { title: "业态", dataIndex: "category", key: "category", render: (v) => v || "-" },
  ];

  return (
    <Modal
      title="选择门店"
      open
      onCancel={onClose}
      onOk={confirmPick}
      width={860}
      okText="确定"
      cancelText="取消"
      destroyOnClose
      data-screen-label="store-picker"
      className="store-picker-modal"
    >
      <Space style={{ marginBottom: 16 }} wrap>
        <Space>
          <span>门店名称</span>
          <Input
            style={{ width: 180 }}
            value={nameQ}
            placeholder="请输入门店名称"
            onChange={(e) => setNameQ(e.target.value)}
            onPressEnter={doSearch}
          />
        </Space>
        <Space>
          <span>门店ID</span>
          <Input
            style={{ width: 180 }}
            value={idQ}
            placeholder="请输入门店ID"
            onChange={(e) => setIdQ(e.target.value)}
            onPressEnter={doSearch}
          />
        </Space>
        <Button type="primary" onClick={doSearch}>查询</Button>
      </Space>
      <Table
        rowKey="id"
        size="small"
        columns={columns}
        dataSource={pageRows}
        pagination={false}
        locale={{ emptyText: "暂无数据" }}
        rowSelection={{
          selectedRowKeys: picked,
          onChange: (keys) => setPicked(keys),
          preserveSelectedRowKeys: true,
        }}
        onRow={(record) => ({
          onClick: () => {
            setPicked((prev) => (
              prev.includes(record.id) ? prev.filter((x) => x !== record.id) : prev.concat(record.id)
            ));
          },
        })}
      />
      <div className="pager-bar" style={{ marginTop: 12 }}>
        <Pagination
          current={page}
          pageSize={pageSize}
          total={filtered.length}
          showTotal={(t) => `共 ${t} 条记录`}
          showSizeChanger
          pageSizeOptions={["10", "20", "50"]}
          onChange={(p, ps) => {
            setPage(p);
            if (ps !== pageSize) {
              setPageSize(ps);
              setPage(1);
            }
          }}
        />
      </div>
    </Modal>
  );
}

function ApproverSearchSelect({ value, onChange, placeholder = "请选择审批人" }) {
  const [search, setSearch] = useState("");
  const hasHan = /[\u4e00-\u9fff]/.test(search);

  const options = useMemo(() => {
    if (hasHan) return [];
    const k = search.trim().toLowerCase();
    return SPData.APPROVERS
      .filter((u) => {
        if (!k) return true;
        return (u.wx || "").toLowerCase().includes(k) || (u.name || "").toLowerCase().includes(k);
      })
      .map((u) => ({ value: u.id, label: u.name, wx: u.wx }));
  }, [search, hasHan]);

  return (
    <Select
      showSearch
      allowClear
      style={{ width: 200 }}
      placeholder={placeholder}
      value={value || undefined}
      onChange={(v) => onChange(v || "")}
      options={options}
      filterOption={false}
      onSearch={setSearch}
      notFoundContent={hasHan ? "不支持输入汉字搜索" : "无法搜索到审批人"}
      optionFilterProp="label"
    />
  );
}

function ApprovalLaunchModal({ initiator, onCancel, onOk }) {
  const nodes = SPData.APPROVAL_NODES || [
    { id: "node-1", name: "会员负责人" },
    { id: "node-2", name: "招商营运副总" },
  ];
  const [nodeUsers, setNodeUsers] = useState(() => Object.fromEntries(nodes.map((n) => [n.id, undefined])));
  const [ccIds, setCcIds] = useState([]);
  const [ccOpen, setCcOpen] = useState(false);
  const [comment, setComment] = useState("");
  const [error, setError] = useState("");

  const submit = () => {
    for (const n of nodes) {
      if (!nodeUsers[n.id]) {
        setError("请选择审批人");
        return;
      }
    }
    if (!comment.trim()) {
      setError("请输入申请原因");
      return;
    }
    if (/(^\s+)|(\s+$)/.test(comment)) {
      setError("前后不能有空格");
      return;
    }
    const assignees = nodes.map((n) => ({
      nodeId: n.id,
      nodeName: n.name,
      user: SPData.APPROVERS.find((u) => u.id === nodeUsers[n.id]),
    }));
    const cc = SPData.APPROVERS.filter((u) => ccIds.includes(u.id));
    onOk({
      approver: assignees[0].user,
      assignees,
      cc,
      comment: comment.trim(),
    });
  };

  return (
    <Modal
      title="发起审批"
      open
      onCancel={onCancel}
      onOk={submit}
      width={740}
      okText="确定"
      cancelText="取消"
      destroyOnClose
      centered
      className="approval-modal"
      data-screen-label="approver-modal"
      footer={
        <div style={{ textAlign: "center" }}>
          <Space>
            <Button onClick={onCancel}>取消</Button>
            <Button type="primary" onClick={submit}>确定</Button>
          </Space>
        </div>
      }
    >
      <div className="approval-form">
        <div className="approval-tips-float" aria-hidden="true">
          <div className="approval-tip-main">请输入万信号搜索</div>
          <div className="approval-tip-sub">不支持输入汉字搜索</div>
          <div className="approval-tip-note">注：</div>
          <div className="approval-tip-note">1、审批人需已开通小程序后台账号，并登录后台绑定万信号</div>
          <div className="approval-tip-note">2、如无法搜索到审批人，请联系会员小程序运营添加</div>
        </div>

        <Form layout="horizontal" labelCol={{ flex: "90px" }} colon>
          <Form.Item label="发起人">
            <span>{initiator}</span>
          </Form.Item>

          {nodes.map((n, idx) => (
            <Form.Item
              key={n.id}
              label={"审批节点" + (idx + 1)}
              required
            >
              <Space align="start">
                <span className="approval-node-name">{n.name}</span>
                <ApproverSearchSelect
                  value={nodeUsers[n.id]}
                  onChange={(id) => {
                    setNodeUsers((prev) => ({ ...prev, [n.id]: id }));
                    setError("");
                  }}
                />
              </Space>
            </Form.Item>
          ))}

          <Form.Item label="抄送人">
            <div>
              <Button type="link" style={{ padding: 0 }} onClick={() => setCcOpen((v) => !v)}>
                请选择抄送人
              </Button>
              {ccOpen ? (
                <div className="cc-picker">
                  <Checkbox.Group
                    value={ccIds}
                    onChange={setCcIds}
                    options={SPData.APPROVERS.map((u) => ({ label: u.name, value: u.id }))}
                  />
                </div>
              ) : null}
              <div style={{ marginTop: 4 }}>
                {ccIds.map((id) => {
                  const u = SPData.APPROVERS.find((x) => x.id === id);
                  if (!u) return null;
                  return (
                    <Tag
                      key={id}
                      closable
                      onClose={() => setCcIds((prev) => prev.filter((x) => x !== id))}
                    >{u.name}</Tag>
                  );
                })}
              </div>
            </div>
          </Form.Item>

          <Form.Item label="申请原因" required>
            <div>
              <TextArea
                rows={3}
                maxLength={200}
                showCount
                placeholder="请输入申请原因"
                value={comment}
                style={{ width: 270 }}
                onChange={(e) => { setComment(e.target.value); setError(""); }}
              />
              <div>
                <Button type="link" style={{ padding: 0 }} onClick={() => setComment("请领导审批")}>
                  请领导审批
                </Button>
              </div>
            </div>
          </Form.Item>
          {error ? <div className="field-error approval-error">{error}</div> : null}
        </Form>
      </div>
    </Modal>
  );
}

function ActivityFormPage({ mode, activityId, state, update, toast }) {
  const existing = activityId ? state.activities.find((a) => a.id === activityId) : null;
  const editableStatuses = ["draft", "rejected"];
  const canEdit = mode === "create" || (existing && editableStatuses.includes(existing.status));
  const readonly = mode === "view" || (mode === "edit" && existing && !editableStatuses.includes(existing.status));
  const [form, setForm] = useState(() => (existing ? activityToForm(existing) : blankForm()));
  const [storePickGroup, setStorePickGroup] = useState(null);
  const [errors, setErrors] = useState({});
  const [submitOpen, setSubmitOpen] = useState(false);

  useEffect(() => {
    if (existing) setForm(activityToForm(existing));
  }, [activityId]);

  const setField = (key, value) => setForm((f) => ({ ...f, [key]: value }));

  const updateGroup = (gid, patch) => {
    setForm((f) => ({
      ...f,
      groups: f.groups.map((g) => (g.id === gid ? { ...g, ...patch } : g)),
    }));
  };

  const validate = (forSubmit) => {
    const e = {};
    if (!form.name.trim()) e.name = "请输入活动名称";
    if (form.name.length > 50) e.name = "最多 50 字";
    if (!form.type) e.type = "请选择活动类型";
    if (!form.cycleStart || !form.cycleEnd) e.cycle = "请选择活动周期";
    if (form.cycleStart && form.cycleEnd && form.cycleStart > form.cycleEnd) e.cycle = "结束时间不能早于开始时间";
    if (mode === "create" && form.cycleStart) {
      const today = new Date().toISOString().slice(0, 10);
      if (form.cycleStart.slice(0, 10) < today) e.cycle = "活动开始日期不能早于今天";
    }
    if (form.subsidyCap === "" || Number(form.subsidyCap) < 1) e.subsidyCap = "请输入活动补贴上限";
    if (Number(form.subsidyCap) > 999999) e.subsidyCap = "活动补贴上限不能超过 999999";
    if (!form.scopePay && !form.scopeCoupon) e.scope = "请选择补贴范围";
    if (!form.formPoint && !form.formCoupon) e.form = "请选择补贴形式";

    if (forSubmit) {
      const emptyGroupIdx = form.groups.findIndex((g) => !g.stores || !g.stores.length);
      if (emptyGroupIdx > -1) {
        toast("请在 分摊比例组" + (emptyGroupIdx + 1) + " 中添加门店");
        setErrors(e);
        return false;
      }
      for (let i = 0; i < form.groups.length; i++) {
        const g = form.groups[i];
        for (const s of g.stores || []) {
          if (s.plazaCap === "" || s.plazaCap == null || Number(s.plazaCap) <= 0) {
            toast("分摊比例组" + (i + 1) + " 中的门店" + s.storeName + "的单门店-广场补贴上限不能为空");
            setErrors(e);
            return false;
          }
          if (s.orderCapRate === "" || s.orderCapRate == null) {
            toast("分摊比例组" + (i + 1) + " 中的门店" + s.storeName + "的单笔积分抵扣比例上限不能为空");
            setErrors(e);
            return false;
          }
        }
      }
    }

    setErrors(e);
    if (Object.keys(e).length) {
      toast(Object.values(e)[0]);
      return false;
    }
    return true;
  };

  const resolvePlaza = () => {
    for (const g of form.groups) {
      for (const st of g.stores || []) {
        const store = SPData.STORES.find((s) => s.id === st.storeId);
        if (store) {
          const plaza = SPData.PLAZAS.find((p) => p.id === store.plazaId);
          if (plaza) return plaza;
        }
      }
    }
    if (existing) return { id: existing.plazaId, name: existing.plazaName };
    return SPData.PLAZAS[1];
  };

  const buildActivity = (status, extra) => {
    const plaza = resolvePlaza();
    const storeCount = form.groups.reduce((n, g) => n + (g.stores || []).length, 0);
    const groups = form.groups.map((g, i) => ({
      ...g,
      plazaRatio: 100,
      merchantRatio: 0,
      thirdRatio: 0,
      gName: "分摊比例组" + (i + 1),
    }));
    return {
      id: existing ? existing.id : SPData.nextActivityId(),
      name: form.name.trim(),
      type: form.type,
      cycleStart: fromDatetimeLocal(form.cycleStart) || (form.cycleStart.slice(0, 10) + " 00:00:00"),
      cycleEnd: fromDatetimeLocal(form.cycleEnd) || (form.cycleEnd.slice(0, 10) + " 23:59:59"),
      plazaId: plaza.id,
      plazaName: plaza.name,
      storeCount,
      status,
      createdAt: existing ? existing.createdAt : new Date().toISOString().slice(0, 19).replace("T", " "),
      creator: existing ? existing.creator : "韩金宇",
      subsidyCap: Number(form.subsidyCap) || 0,
      scopePay: form.scopePay,
      scopeCoupon: form.scopeCoupon,
      formPoint: form.formPoint,
      formCoupon: form.formCoupon,
      groups,
      rejectReason: status === "rejected" ? (existing && existing.rejectReason) || "" : "",
      processInstanceId: existing && existing.processInstanceId,
      ...(extra || {}),
    };
  };

  const persist = (item, tip) => {
    update((s) => {
      const idx = s.activities.findIndex((a) => a.id === item.id);
      const activities = idx >= 0
        ? s.activities.map((a) => (a.id === item.id ? { ...a, ...item } : a))
        : [item, ...s.activities];
      return { ...s, activities };
    });
    toast(tip);
    navigate("sp/activity");
  };

  const saveDraft = () => {
    if (!validate(false)) return;
    const nextStatus = existing && existing.status === "rejected" ? "rejected" : "draft";
    persist(buildActivity(nextStatus), existing ? "修改成功" : "新增成功");
  };

  const openSubmit = () => {
    if (!validate(true)) return;
    setSubmitOpen(true);
  };

  const submitReview = ({ approver, assignees, cc, comment }) => {
    persist(
      buildActivity("reviewing", {
        approver: approver ? approver.name : "",
        assignees: (assignees || []).map((a) => ({
          nodeId: a.nodeId,
          nodeName: a.nodeName,
          userName: a.user && a.user.name,
          wx: a.user && a.user.wx,
        })),
        cc: (cc || []).map((u) => u.name),
        applyComment: comment,
        rejectReason: "",
        processInstanceId: existing && existing.processInstanceId
          ? existing.processInstanceId
          : "PI-" + Date.now(),
      }),
      "提交成功"
    );
  };

  const approve = () => {
    if (!existing) return;
    const next = SPData.resolveApprovedStatus(existing);
    const tipMap = { pending: "审核通过，活动待开始", active: "审核通过，活动已开始", ended: "审核通过，活动已结束" };
    persist({ ...existing, status: next, rejectReason: "" }, tipMap[next] || "审核通过");
  };

  const reject = () => {
    if (!existing) return;
    persist({ ...existing, status: "rejected", rejectReason: "审批未通过，请修改后重新提交" }, "已驳回，可修改后重新提交");
  };

  if (mode !== "create" && !existing) {
    return (
      <div className="panel" style={{ padding: 40, textAlign: "center" }}>
        <p>未找到活动</p>
        <Button type="primary" onClick={() => navigate("sp/activity")}>返回列表</Button>
      </div>
    );
  }

  if (mode === "edit" && existing && !canEdit) {
    return (
      <div className="panel" style={{ padding: 40, textAlign: "center" }}>
        <p>当前状态「{(SPData.STATUS[existing.status] || {}).label || existing.status}」不可修改</p>
        <Button type="primary" onClick={() => navigate("sp/activity/view/" + existing.id)}>查看详情</Button>
      </div>
    );
  }

  const nameTypeLocked = mode === "edit";
  const cycleDisplay = formatCycleRange(
    fromDatetimeLocal(form.cycleStart) || form.cycleStart,
    fromDatetimeLocal(form.cycleEnd) || form.cycleEnd
  );

  const storeColumns = (g, gi) => {
    const cols = [
      { title: "门店ID", dataIndex: "storeId", key: "storeId" },
      { title: "门店名称", dataIndex: "storeName", key: "storeName" },
      {
        title: "单门店-广场补贴上限",
        key: "plazaCap",
        render: (_, s, si) => (
          readonly ? (s.plazaCap + " 元") : (
            <InputNumber
              min={0}
              value={s.plazaCap}
              addonAfter="元"
              style={{ width: 140 }}
              onChange={(v) => {
                const stores = g.stores.map((x, i) => (i === si ? { ...x, plazaCap: v } : x));
                updateGroup(g.id, { stores });
              }}
            />
          )
        ),
      },
      {
        title: "单笔积分抵扣比例上限",
        key: "orderCapRate",
        render: (_, s, si) => (
          readonly ? (s.orderCapRate + "%") : (
            <InputNumber
              min={0}
              max={100}
              value={s.orderCapRate}
              addonAfter="%"
              style={{ width: 120 }}
              onChange={(v) => {
                const stores = g.stores.map((x, i) => (i === si ? { ...x, orderCapRate: v } : x));
                updateGroup(g.id, { stores });
              }}
            />
          )
        ),
      },
    ];
    if (!readonly) {
      cols.push({
        title: "操作",
        key: "op",
        width: 80,
        render: (_, __, si) => (
          <Button
            type="link"
            danger
            onClick={() => updateGroup(g.id, { stores: g.stores.filter((_, i) => i !== si) })}
          >删除</Button>
        ),
      });
    }
    return cols;
  };

  return (
    <div className="activity-form" data-screen-label={"page-activity-" + mode}>
      {existing && existing.status === "rejected" && existing.rejectReason ? (
        <div className="reject-banner" data-screen-label="reject-banner">
          驳回原因：{existing.rejectReason}
        </div>
      ) : null}

      <div className="activity-form-panel">
        <h3 className="form-section-title">活动基础信息</h3>
        <div className="form-grid-2">
          <div className="form-item required">
            <label>活动名称</label>
            <div className="form-control-wrap">
              {readonly ? (
                <div className="form-readonly">{form.name || "-"}</div>
              ) : (
                <Input
                  className="control-w"
                  maxLength={50}
                  disabled={nameTypeLocked}
                  placeholder="请输入活动名称"
                  value={form.name}
                  showCount={!nameTypeLocked}
                  onChange={(e) => setField("name", e.target.value)}
                />
              )}
              {errors.name ? <div className="field-error">{errors.name}</div> : null}
            </div>
          </div>
          <div className="form-item required">
            <label>活动类型</label>
            <div className="form-control-wrap">
              {readonly ? (
                <div className="form-readonly">{form.type || "-"}</div>
              ) : (
                <Select
                  className="control-w"
                  style={{ width: "100%" }}
                  disabled={nameTypeLocked}
                  placeholder="请选择"
                  value={form.type || undefined}
                  onChange={(v) => setField("type", v)}
                  options={[{ value: "档期活动", label: "档期活动" }]}
                />
              )}
              {errors.type ? <div className="field-error">{errors.type}</div> : null}
            </div>
          </div>
          <div className="form-item required">
            <label>活动周期</label>
            <div className="form-control-wrap">
              {readonly ? (
                <div className="form-readonly">{cycleDisplay}</div>
              ) : (
                <RangePicker
                  className="control-w"
                  style={{ width: "100%" }}
                  showTime={{ format: "HH:mm" }}
                  format="YYYY-MM-DD HH:mm"
                  value={[toDayjs(form.cycleStart), toDayjs(form.cycleEnd)]}
                  onChange={(dates) => {
                    setForm((f) => ({
                      ...f,
                      cycleStart: dates && dates[0] ? dates[0].format("YYYY-MM-DDTHH:mm") : "",
                      cycleEnd: dates && dates[1] ? dates[1].format("YYYY-MM-DDTHH:mm") : "",
                    }));
                  }}
                />
              )}
              {errors.cycle ? <div className="field-error">{errors.cycle}</div> : null}
            </div>
          </div>
          <div className="form-item required">
            <label>活动补贴上限</label>
            <div className="form-control-wrap">
              {readonly ? (
                <div className="form-readonly">{form.subsidyCap === "" ? "-" : form.subsidyCap + " 元"}</div>
              ) : (
                <InputNumber
                  className="control-w"
                  style={{ width: "100%" }}
                  min={1}
                  max={999999}
                  placeholder="请输入金额"
                  value={form.subsidyCap === "" ? null : form.subsidyCap}
                  addonAfter="元"
                  onChange={(v) => setField("subsidyCap", v == null ? "" : v)}
                />
              )}
              {errors.subsidyCap ? <div className="field-error">{errors.subsidyCap}</div> : null}
            </div>
          </div>
        </div>

        <h3 className="form-section-title">补贴配置规则</h3>
        <div className="form-item required form-item-full">
          <label>补贴范围</label>
          <div className="form-control-wrap check-row">
            <Checkbox disabled={readonly} checked={form.scopePay} onChange={(e) => setField("scopePay", e.target.checked)}>买单积分抵现</Checkbox>
            <Checkbox disabled checked={!!form.scopeCoupon}>线上购券</Checkbox>
            {errors.scope ? <div className="field-error">{errors.scope}</div> : null}
          </div>
        </div>
        <div className="form-item required form-item-full">
          <label>补贴形式</label>
          <div className="form-control-wrap check-row">
            <Checkbox disabled={readonly} checked={form.formPoint} onChange={(e) => setField("formPoint", e.target.checked)}>积分补贴</Checkbox>
            <Checkbox disabled checked={!!form.formCoupon}>券补贴</Checkbox>
            {errors.form ? <div className="field-error">{errors.form}</div> : null}
          </div>
        </div>

        <h3 className="store-manage-title">
          <span className="store-manage-name">参活门店管理</span>
          <span className="store-manage-desc">配置广场补贴比例、商户补贴比例、其他第三方比例(总和须为100%)，并为每个门店设置补贴上限</span>
          {!readonly ? (
            <Button
              disabled={form.groups.length >= 10}
              onClick={() => setForm((f) => ({ ...f, groups: [...f.groups, SPData.emptyGroup()] }))}
            >+ 添加分摊比例组</Button>
          ) : null}
        </h3>

        {form.groups.map((g, gi) => (
          <div className="ratio-group" key={g.id}>
            <div className="ratio-group-hd">
              <div>分摊比例组{gi + 1}</div>
              {!readonly ? (
                <Button
                  type="link"
                  disabled={form.groups.length <= 1}
                  onClick={() => setForm((f) => ({ ...f, groups: f.groups.filter((x) => x.id !== g.id) }))}
                >删除</Button>
              ) : null}
            </div>

            <div className="ratio-group-body">
              <div className="form-item required form-item-full ratio-title-item">
                <label>补贴分摊比例</label>
                <div className="form-control-wrap"></div>
              </div>
              <div className="ratio-fields-row">
                <div className="form-item ratio-field-item">
                  <label>广场补贴比例</label>
                  <div className="form-control-wrap">
                    <InputNumber disabled value={100} addonAfter="%" style={{ width: "100%" }} />
                  </div>
                </div>
                <div className="form-item ratio-field-item">
                  <label>商户补贴比例</label>
                  <div className="form-control-wrap">
                    <InputNumber disabled value={0} precision={2} addonAfter="%" style={{ width: "100%" }} />
                  </div>
                </div>
                <div className="form-item ratio-field-item">
                  <label>其他第三方比例</label>
                  <div className="form-control-wrap">
                    <InputNumber disabled value={0} precision={2} addonAfter="%" style={{ width: "100%" }} />
                  </div>
                </div>
              </div>

              <div className="store-block">
                {!readonly ? (
                  <div className="store-block-hd">
                    <div className="form-item required store-label-item">
                      <label>关联门店及补贴上限</label>
                    </div>
                    <Button onClick={() => setStorePickGroup(g.id)}>添加门店</Button>
                  </div>
                ) : null}
                <Table
                  rowKey="storeId"
                  size="small"
                  columns={storeColumns(g, gi)}
                  dataSource={g.stores || []}
                  pagination={false}
                  locale={{ emptyText: "暂无数据" }}
                  style={{ marginTop: 8 }}
                />
              </div>
            </div>
          </div>
        ))}
      </div>

      <div className="form-footer">
        <Button onClick={() => navigate("sp/activity")}>返 回</Button>
        {!readonly ? (
          <>
            <Button type="primary" className="form-footer-save" onClick={saveDraft}>保 存</Button>
            <Button type="primary" onClick={openSubmit}>提交审批</Button>
          </>
        ) : null}
        {mode === "view" && existing && existing.status === "reviewing" ? (
          <>
            <Button className="form-footer-save" onClick={reject}>驳 回</Button>
            <Button type="primary" onClick={approve}>审核通过</Button>
          </>
        ) : null}
      </div>

      {submitOpen ? (
        <ApprovalLaunchModal
          initiator="韩金宇"
          onCancel={() => setSubmitOpen(false)}
          onOk={submitReview}
        />
      ) : null}

      {storePickGroup ? (
        <StorePicker
          selectedIds={(form.groups.find((g) => g.id === storePickGroup).stores || []).map((s) => s.storeId)}
          existingStores={(form.groups.find((g) => g.id === storePickGroup).stores || [])}
          onClose={() => setStorePickGroup(null)}
          onConfirm={(stores) => {
            updateGroup(storePickGroup, { stores });
            setStorePickGroup(null);
            toast("已更新门店");
          }}
        />
      ) : null}
    </div>
  );
}

Object.assign(window, {
  ActivityListPage,
  ActivityFormPage,
});
