<template>
  <section class="section-container">
    <a-card
      :bordered="false"
      class="query-card"
      :body-style="queryCardBodyStyle"
    >
      <div ref="queryContainer" class="section-query-container">
        <a-form ref="formRef" :model="queryParam" layout="inline">
          <a-row :gutter="16" style="width: 100%">
            <a-col :md="6" :sm="24">
              <a-form-item label="合同名称">
                <a-input
                  v-model:value="queryParam.contractName"
                  allow-clear
                  placeholder="请输入合同名称"
                />
              </a-form-item>
            </a-col>
            <a-col :md="6" :sm="24">
              <a-form-item label="合同编码">
                <a-input
                  v-model:value="queryParam.contractCode"
                  allow-clear
                  placeholder="请输入合同编码"
                />
              </a-form-item>
            </a-col>
            <a-col :md="6" :sm="24">
              <a-form-item label="合同类型">
                <a-select
                  v-model:value="queryParam.contractType"
                  allow-clear
                  placeholder="请选择合同类型"
                  :options="contractTypeOptions"
                />
              </a-form-item>
            </a-col>
            <a-col :md="6" :sm="24">
              <a-form-item label="当前状态">
                <a-select
                  v-model:value="queryParam.status"
                  allow-clear
                  placeholder="请选择状态"
                  :options="contractRecordStatusOptions"
                />
              </a-form-item>
            </a-col>
            <a-col :md="12" :sm="24">
              <a-form-item label="发起日期">
                <a-range-picker
                  v-model:value="queryParam.dateRange"
                  value-format="YYYY-MM-DD"
                  style="width: 100%"
                />
              </a-form-item>
            </a-col>
          </a-row>
        </a-form>
      </div>
    </a-card>

    <a-card
      :bordered="false"
      class="table-card"
      :body-style="tableCardBodyStyle"
    >
      <vxe-toolbar ref="toolbarRef" custom>
        <template #buttons>
          <a-space wrap>
            <a-button
              type="primary"
              :icon="h(SearchOutlined)"
              @click="handleQuery"
              >查询</a-button
            >
            <a-button :icon="h(RedoOutlined)" @click="handleReset"
              >重置</a-button
            >
            <a-button
              type="primary"
              ghost
              :icon="h(PlusOutlined)"
              @click="handleCreate"
              >发起合同</a-button
            >
            <a-button
              type="primary"
              ghost
              :icon="h(PlusOutlined)"
              @click="handleCreateSingleAgreement"
              >发起单方协议</a-button
            >
            <a-button
              danger
              :icon="h(DeleteOutlined)"
              :disabled="!selectedRowKeys.length"
              @click="handleBatchDelete"
              >删除</a-button
            >
          </a-space>
        </template>
      </vxe-toolbar>

      <vxe-table
        ref="tableRef"
        border
        :height="tableHeight"
        :row-config="{ isHover: true, height: 44 }"
        :column-config="{ resizable: true, minWidth: 120 }"
        :custom-config="{ storage: true }"
        :scroll-y="{ enabled: true, gt: 0, mode: 'wheel' }"
        :checkbox-config="{ range: true }"
        :data="tableData"
        :loading="loading"
        :loading-config="{
          icon: 'vxe-icon-indicator roll',
          text: '正在拼命加载中...',
        }"
        @checkbox-range-change="selectChangeEvent"
        @checkbox-change="selectChangeEvent"
        @checkbox-all="selectChangeEvent"
      >
        <vxe-column type="checkbox" width="56" />
        <vxe-column type="seq" title="序号" width="68" />
        <vxe-column
          field="contractCode"
          title="合同编码"
          width="160"
          show-overflow="title"
        />
        <vxe-column
          field="lawContractCode"
          title="法务合同编号"
          width="160"
          show-overflow="title"
        />
        <vxe-column
          field="contractName"
          title="合同名称"
          width="220"
          show-overflow="title"
        />
        <vxe-column
          field="contractType"
          title="合同类型"
          width="160"
          show-overflow="title"
        >
          <template #default="{ row }">
            {{
              getContractTypeSimpleLabel(
                row.contractTypeCode || row.contractType,
              )
            }}
          </template>
        </vxe-column>
        <vxe-column
          field="templateName"
          title="所选模板"
          width="180"
          show-overflow="title"
        />
        <vxe-column
          field="counterpartySummary"
          title="合同相对方"
          width="260"
          show-overflow="title"
        />
        <vxe-column field="status" title="状态" width="120">
          <template #default="{ row }">
            <a-tag :color="getStatusColor(row.status)">{{
              getStatusLabelByRow(row)
            }}</a-tag>
          </template>
        </vxe-column>
        <vxe-column
          field="approveMessage"
          title="审批说明"
          width="220"
          show-overflow="title"
        />
        <vxe-column
          field="initiator"
          title="发起人"
          width="100"
          show-overflow="title"
        />
        <vxe-column
          field="initiatorDept"
          title="所属部门"
          width="140"
          show-overflow="title"
        />
        <vxe-column
          field="createTime"
          title="发起时间"
          width="170"
          show-overflow="title"
        />
        <vxe-column
          field="updateTime"
          title="最后更新时间"
          width="170"
          show-overflow="title"
        />
        <vxe-column title="操作" width="720" fixed="right">
          <template #default="{ row }">
            <div class="table-actions">
              <a @click="handleView(row)">查看</a>
              <a @click="handleCopy(row)">复制</a>
              <a v-if="canChange(row)" @click="handleChange(row)">变更</a>
              <a v-if="canEdit(row)" @click="handleEdit(row)">编辑</a>
              <a v-if="canSubmit(row)" @click="handleSubmit(row)">{{
                isSingleAgreementRecord(row) ? "提交审批" : "提交法务"
              }}</a>
              <a v-if="canViewApprove(row)" @click="handleViewApprove(row)"
                >审批记录</a
              >
              <a
                v-if="canViewLawCallback(row)"
                @click="handleViewLawCallback(row)"
                >回调data</a
              >
              <a v-if="canMockApprove(row)" @click="handleMockApprove(row)">{{
                isSingleAgreementRecord(row) ? "审批通过" : "测试通过"
              }}</a>
              <a v-if="canMockReject(row)" @click="handleMockReject(row)">{{
                isSingleAgreementRecord(row) ? "审批驳回" : "测试驳回"
              }}</a>
              <a v-if="canOnlineSign(row)" @click="handleOnlineSign(row)">{{
                isSingleAgreementRecord(row) ? "发起盖章" : "在线签订"
              }}</a>
              <a
                v-if="canDownloadSigned(row)"
                @click="handleDownloadSigned(row)"
                >下载签署文件</a
              >
              <a v-if="canUploadSigned(row)" @click="handleUploadSigned(row)">{{
                isSingleAgreementRecord(row) ? "上传盖章版" : "上传已签署版本"
              }}</a>
              <a
                v-if="canMockFinishSign(row)"
                @click="handleMockFinishSign(row)"
                >{{
                  isSingleAgreementRecord(row) ? "测试盖章完成" : "测试签署完成"
                }}</a
              >
              <a v-if="canCollect(row)" @click="handleMockCollect(row)">{{
                isSingleAgreementRecord(row) ? "测试生效" : "测试采集"
              }}</a>
              <a v-if="canArchive(row)" @click="handleArchive(row)">{{
                isSingleAgreementRecord(row) ? "办结" : "归档"
              }}</a>
              <a v-if="canTerminate(row)" @click="handleTerminate(row)">终止</a>
              <a v-if="canDelete(row)" @click="handleDelete(row)">删除</a>
            </div>
          </template>
        </vxe-column>
      </vxe-table>

      <a-pagination
        id="pageWrapper"
        ref="pageWrapperRef"
        v-model:pageSize="queryParam.pageSize"
        v-model:current="queryParam.pageNo"
        class="table-pagination"
        show-size-changer
        :page-size-options="['10', '20', '50', '100']"
        :total="total"
        :show-total="(value) => `共 ${value} 条`"
        @change="onShowSizeChange"
        @show-size-change="onShowSizeChange"
      />
    </a-card>

    <ContractPartyPlaceholderModal
      ref="contractModalRef"
      @save="handleModalSave"
    />
    <MixedSignModal
      ref="mixedSignModalRef"
      @business-updated="handleSignBusinessUpdated"
    />
    <UploadSignedModal
      ref="uploadSignedModalRef"
      @done="handleSignBusinessUpdated"
    />
    <ContractArchiveModal
      ref="contractArchiveModalRef"
      @done="handleArchiveDone"
    />
  </section>
</template>

<script setup>
import { h, nextTick, onBeforeUnmount, onMounted, ref } from "vue";
import {
  DeleteOutlined,
  PlusOutlined,
  RedoOutlined,
  SearchOutlined,
} from "@ant-design/icons-vue";
import { Input, message, Modal } from "ant-design-vue";
import ContractPartyPlaceholderModal from "./components/ContractPartyPlaceholderModal.vue";
import MixedSignModal from "./components/mixedSignModal.vue";
import UploadSignedModal from "./components/UploadSignedModal.vue";
import ContractArchiveModal from "./components/ContractArchiveModal.vue";
import {
  contractTypeOptions,
  getContractTypeSimpleLabel,
} from "./contractLaunchOptions.js";
import {
  copyLaunchDraft,
  createLaunchChangeDraft,
  createLaunchDraft,
  deleteLaunchRecord,
  getLaunchDetail,
  getLawApproveCallbackSample,
  mockApproveLaunch,
  mockCollectLaunch,
  mockRejectLaunch,
  finishLaunchSeal,
  queryApproveViewUrl,
  queryLaunchList,
  submitLaunchRecord,
  downloadLaunchFile,
  terminateLaunchRecord,
  updateLaunchDraft,
} from "@/api/launch.js";

const contractRecordStatusOptions = [
  { label: "草稿", value: "draft" },
  { label: "审批中", value: "reviewing" },
  { label: "审批驳回", value: "rejected" },
  { label: "待签署", value: "pending_sign" },
  { label: "签署中", value: "signing" },
  { label: "待采集", value: "pending_collect" },
  { label: "待归档", value: "pending_archive" },
  { label: "已完成", value: "completed" },
  { label: "已终止", value: "terminated" },
];

const formRef = ref(null);
const queryContainer = ref(null);
const pageWrapperRef = ref(null);
const tableRef = ref(null);
const toolbarRef = ref(null);
const contractModalRef = ref(null);
const mixedSignModalRef = ref(null);
const uploadSignedModalRef = ref(null);
const contractArchiveModalRef = ref(null);

const total = ref(0);
const loading = ref(false);
const tableHeight = ref(420);
const tableData = ref([]);
const selectedRows = ref([]);
const selectedRowKeys = ref([]);

const queryParam = ref({
  pageNo: 1,
  pageSize: 10,
  contractName: undefined,
  contractCode: undefined,
  contractType: undefined,
  status: undefined,
  dateRange: [],
});

const queryCardBodyStyle = {
  padding: "20px 24px 6px",
};

const tableCardBodyStyle = {
  display: "flex",
  flexFlow: "column nowrap",
  minHeight: "0",
  padding: "8px 12px 6px",
};

const statusLabelMap = {
  draft: "草稿",
  reviewing: "审批中",
  rejected: "审批驳回",
  pending_sign: "待签署",
  signing: "签署中",
  pending_collect: "待采集",
  pending_archive: "待归档",
  completed: "已完成",
  terminated: "已终止",
};

const statusColorMap = {
  draft: "default",
  reviewing: "processing",
  rejected: "error",
  pending_sign: "warning",
  signing: "purple",
  pending_collect: "cyan",
  pending_archive: "orange",
  completed: "success",
  terminated: "default",
};

function isSuccessResponse(res) {
  return String(res?.code || "") === "0000";
}

function getPageResult(res) {
  return res?.result || {};
}

function getDataResult(res) {
  return res?.result || null;
}

function getResponseMessage(res, fallback = "操作失败") {
  return res?.message || res?.msg || fallback;
}

function sliceDateValue(value) {
  return value ? String(value).slice(0, 10) : "";
}

function todayString() {
  const now = new Date();
  const month = String(now.getMonth() + 1).padStart(2, "0");
  const day = String(now.getDate()).padStart(2, "0");
  return `${now.getFullYear()}-${month}-${day}`;
}

function formatDateTimeValue(value) {
  return value ? `${value} 00:00:00` : null;
}

function connectToolbar() {
  const table = tableRef.value;
  const toolbar = toolbarRef.value;
  if (table && toolbar && table.connect) {
    table.connect(toolbar);
  }
}

function getStatusLabel(status) {
  return statusLabelMap[status] || status;
}

function getStatusColor(status) {
  return statusColorMap[status] || "default";
}

function getStatusLabelByRow(row) {
  if (isSingleAgreementRecord(row) && row?.status === "pending_sign") {
    return "待盖章";
  }
  return getStatusLabel(row?.status);
}

function canEdit(row) {
  return ["draft", "rejected"].includes(row.status);
}

function canDelete(row) {
  return ["draft", "rejected"].includes(row.status);
}

function canSubmit(row) {
  return ["draft", "rejected"].includes(row.status);
}

function canChange(row) {
  // 变更/补充协议：仅已完成/待采集/待归档的合同允许基于它发起变更
  return ["completed", "pending_archive", "pending_collect"].includes(
    row.status,
  );
}

function canMockApprove(row) {
  return row.status === "reviewing";
}

function canMockReject(row) {
  return row.status === "reviewing";
}

function canOnlineSign(row) {
  // 在线签订只对电子合同开放；纸质/线下签署走“上传已签署版本”兜底。
  return (
    !isSingleAgreementRecord(row) &&
    String(row.isElectron || "1") === "1" &&
    ["pending_sign", "signing"].includes(row.status)
  );
}

function canMockFinishSign(row) {
  if (isSingleAgreementRecord(row)) {
    return row.status === "pending_sign";
  }
  return (
    String(row.isElectron || "1") === "1" &&
    ["pending_sign", "signing"].includes(row.status)
  );
}

function canUploadSigned(row) {
  return ["pending_sign", "signing"].includes(row.status);
}

function canCollect(row) {
  return !isSingleAgreementRecord(row) && row.status === "pending_collect";
}

function canArchive(row) {
  return !isSingleAgreementRecord(row) && row.status === "pending_archive";
}

function isSingleAgreementRecord(row) {
  return String(row?.isSingleAgreement || "0") === "1";
}

function canViewApprove(row) {
  return (
    !isSingleAgreementRecord(row) &&
    Boolean(row.lawContractId) &&
    [
      "reviewing",
      "rejected",
      "pending_sign",
      "signing",
      "pending_collect",
      "pending_archive",
      "completed",
    ].includes(row.status)
  );
}

function canViewLawCallback(row) {
  return (
    !isSingleAgreementRecord(row) &&
    [
      "reviewing",
      "rejected",
      "pending_sign",
      "signing",
      "pending_collect",
      "pending_archive",
      "completed",
    ].includes(row.status)
  );
}

function canDownloadSigned(row) {
  return Boolean(row.signedFilePath);
}

function canTerminate(row) {
  return row.status !== "completed" && row.status !== "terminated";
}

function selectChangeEvent({ records }) {
  selectedRows.value = records;
  selectedRowKeys.value = records.map((item) => item.id);
}

function buildQueryPayload() {
  return {
    pageNo: queryParam.value.pageNo,
    pageSize: queryParam.value.pageSize,
    contractName: queryParam.value.contractName,
    contractCode: queryParam.value.contractCode,
    contractType: queryParam.value.contractType,
    status: queryParam.value.status,
    dateStart: queryParam.value.dateRange?.[0],
    dateEnd: queryParam.value.dateRange?.[1],
  };
}

function getList() {
  loading.value = true;
  queryLaunchList(buildQueryPayload())
    .then((res) => {
      if (!isSuccessResponse(res)) {
        tableData.value = [];
        total.value = 0;
        message.error(getResponseMessage(res, "合同发起列表查询失败"));
        return;
      }
      const pageResult = getPageResult(res);
      tableData.value = pageResult.data || [];
      total.value = pageResult.totalSize || 0;
    })
    .finally(() => {
      loading.value = false;
      nextTick(() => {
        connectToolbar();
        syncTableHeight();
      });
    });
}

function handleQuery() {
  queryParam.value.pageNo = 1;
  getList();
}

function handleReset() {
  formRef.value?.resetFields?.();
  Object.assign(queryParam.value, {
    pageNo: 1,
    pageSize: 10,
    contractName: undefined,
    contractCode: undefined,
    contractType: undefined,
    status: undefined,
    dateRange: [],
  });
  getList();
}

function onShowSizeChange(current, pageSize) {
  queryParam.value.pageNo = current;
  queryParam.value.pageSize = pageSize;
  getList();
}

function handleCreate() {
  contractModalRef.value?.showModal({}, "create");
}

function handleCreateSingleAgreement() {
  contractModalRef.value?.showModal({ isSingleAgreement: "1" }, "create");
}

function handleView(row) {
  getLaunchDetail(row.id).then((res) => {
    if (!isSuccessResponse(res) || !getDataResult(res)) {
      message.error(getResponseMessage(res, "获取合同详情失败"));
      return;
    }
    contractModalRef.value?.showModal(getDataResult(res), "view");
  });
}

function handleEdit(row) {
  getLaunchDetail(row.id).then((res) => {
    if (!isSuccessResponse(res) || !getDataResult(res)) {
      message.error(getResponseMessage(res, "获取合同详情失败"));
      return;
    }
    contractModalRef.value?.showModal(getDataResult(res), "edit");
  });
}

function handleCopy(row) {
  Modal.confirm({
    title: "确认复制合同",
    content: `将复制合同【${row.contractName}】生成一份新草稿，复制后自动进入编辑状态。`,
    okText: "确认复制",
    cancelText: "取消",
    onOk: () =>
      copyLaunchDraft(row.id).then((res) => {
        if (!isSuccessResponse(res) || !getDataResult(res)) {
          message.error(getResponseMessage(res, "复制合同失败"));
          return;
        }
        const copiedRecord = getDataResult(res);
        message.success("合同已复制为新草稿，请继续完善后保存");
        getList();
        contractModalRef.value?.showModal(copiedRecord, "edit");
      }),
    icon: null,
  });
}

function handleChange(row) {
  Modal.confirm({
    title: "确认发起变更合同",
    content: h("div", [
      h("p", `将基于【${row.contractName}】发起一份变更/补充协议，`),
      h("p", "自动关联主合同编码，生成新草稿。原合同不受影响。"),
    ]),
    okText: "确认变更",
    cancelText: "取消",
    onOk: () =>
      createLaunchChangeDraft(row.id).then((res) => {
        if (!isSuccessResponse(res) || !getDataResult(res)) {
          message.error(getResponseMessage(res, "发起变更合同失败"));
          return;
        }
        const changedRecord = getDataResult(res);
        message.success("已生成变更草稿，并自动关联主合同编码");
        getList();
        contractModalRef.value?.showModal(changedRecord, "edit");
      }),
    icon: null,
  });
}

function handleSubmit(row) {
  const singleAgreement = isSingleAgreementRecord(row);
  Modal.confirm({
    title: singleAgreement ? "确认提交内部审批" : "确认提交法务审批",
    content: h("div", [
      h(
        "p",
        singleAgreement
          ? `确定将单方协议【${row.contractName}】提交内部审批吗？`
          : `确定将合同【${row.contractName}】提交法务系统审批吗？`,
      ),
      h(
        "p",
        { style: { color: "#999", fontSize: "12px" } },
        "提交后合同进入「审批中」状态，审批完成前不可编辑。",
      ),
    ]),
    okText: "确认提交",
    cancelText: "取消",
    onOk: () =>
      submitLaunchRecord(row.id).then((res) => {
        if (!isSuccessResponse(res)) {
          message.error(
            getResponseMessage(
              res,
              singleAgreement ? "提交内部审批失败" : "提交法务失败",
            ),
          );
          return;
        }
        message.success(
          singleAgreement ? "已提交内部审批，等待审批" : "已提交法务，等待审批",
        );
        getList();
      }),
    icon: null,
  });
}

function handleViewApprove(row) {
  if (!row.lawContractId) {
    message.warning("当前暂无法务合同ID，审批记录地址尚未生成");
    return;
  }

  queryApproveViewUrl({
    contractId: String(row.lawContractId),
    ivUser: row.initiator || "admin",
  }).then((res) => {
    if (!isSuccessResponse(res)) {
      message.error(getResponseMessage(res, "获取审批记录查看地址失败"));
      return;
    }
    const approveViewUrl = res?.result?.approveViewUrl;
    if (!approveViewUrl) {
      message.warning("审批记录地址为空");
      return;
    }
    window.open(approveViewUrl, "_blank");
  });
}

function buildLawCallbackModalContent(sample) {
  const approvedJson = JSON.stringify(
    { data: sample?.approvedData || {} },
    null,
    2,
  );
  const rejectedJson = JSON.stringify(
    { data: sample?.rejectedData || {} },
    null,
    2,
  );
  return h(
    "div",
    { style: { display: "flex", flexDirection: "column", gap: "12px" } },
    [
      h("div", [
        h(
          "div",
          { style: { marginBottom: "6px", fontWeight: 600 } },
          "回调地址",
        ),
        h(
          "div",
          { style: { color: "#666", wordBreak: "break-all" } },
          `${sample?.callbackMethod || "POST"} ${sample?.callbackUrl || "/contract/launch/callback/law/approve"}`,
        ),
      ]),
      h("div", [
        h(
          "div",
          { style: { marginBottom: "6px", fontWeight: 600 } },
          "审批通过 data",
        ),
        h(
          "pre",
          {
            style: {
              margin: 0,
              maxHeight: "260px",
              overflow: "auto",
              padding: "12px",
              borderRadius: "8px",
              background: "#f6f8fa",
              fontSize: "12px",
              lineHeight: "1.6",
              whiteSpace: "pre-wrap",
              wordBreak: "break-word",
            },
          },
          approvedJson,
        ),
      ]),
      h("div", [
        h(
          "div",
          { style: { marginBottom: "6px", fontWeight: 600 } },
          "审批驳回 data",
        ),
        h(
          "pre",
          {
            style: {
              margin: 0,
              maxHeight: "220px",
              overflow: "auto",
              padding: "12px",
              borderRadius: "8px",
              background: "#f6f8fa",
              fontSize: "12px",
              lineHeight: "1.6",
              whiteSpace: "pre-wrap",
              wordBreak: "break-word",
            },
          },
          rejectedJson,
        ),
      ]),
    ],
  );
}

function handleViewLawCallback(row) {
  getLawApproveCallbackSample(row.id).then((res) => {
    if (!isSuccessResponse(res) || !getDataResult(res)) {
      message.error(getResponseMessage(res, "获取法务回调样例失败"));
      return;
    }
    const sample = getDataResult(res);
    Modal.info({
      title: `法务回调 data 结构：${row.contractName}`,
      width: 900,
      okText: "知道了",
      content: buildLawCallbackModalContent(sample),
    });
  });
}

function handleMockApprove(row) {
  const singleAgreement = isSingleAgreementRecord(row);
  Modal.confirm({
    title: singleAgreement
      ? "测试操作：模拟内部审批通过"
      : "测试操作：模拟审批通过",
    content: singleAgreement
      ? `模拟单方协议【${row.contractName}】内部审批通过，状态将变为「待签署」。`
      : `模拟法务审批通过合同【${row.contractName}】，状态将变为「待签署」。`,
    okText: "确认模拟",
    cancelText: "取消",
    onOk: () =>
      mockApproveLaunch(row.id, {}).then((res) => {
        if (!isSuccessResponse(res)) {
          message.error(getResponseMessage(res, "模拟审批通过失败"));
          return;
        }
        message.success("测试审批通过完成，合同已流转到待签署");
        getList();
      }),
    icon: null,
  });
}

function handleMockReject(row) {
  const singleAgreement = isSingleAgreementRecord(row);
  Modal.confirm({
    title: singleAgreement
      ? "测试操作：模拟内部审批驳回"
      : "测试操作：模拟审批驳回",
    content: h("div", [
      h(
        "p",
        singleAgreement
          ? `模拟单方协议【${row.contractName}】内部审批驳回，状态将回到「已驳回」。`
          : `模拟法务审批驳回合同【${row.contractName}】，状态将回到「已驳回」。`,
      ),
      h(
        "p",
        { style: { color: "#999", fontSize: "12px" } },
        "驳回后可重新编辑再提交。",
      ),
    ]),
    okText: "确认驳回",
    cancelText: "取消",
    onOk: () =>
      mockRejectLaunch(row.id, {}).then((res) => {
        if (!isSuccessResponse(res)) {
          message.error(getResponseMessage(res, "模拟审批驳回失败"));
          return;
        }
        message.success("测试审批驳回完成，合同已流转到审批驳回");
        getList();
      }),
    icon: null,
  });
}

function handleMockFinishSign(row) {
  const singleAgreement = isSingleAgreementRecord(row);
  Modal.confirm({
    title: singleAgreement
      ? "测试操作：模拟盖章完成"
      : "测试操作：模拟签署完成",
    content: singleAgreement
      ? `模拟单方协议【${row.contractName}】内部业务章加盖完成，状态将变为「已完成」。`
      : `模拟合同【${row.contractName}】签署完成，状态将变为「待采集」。`,
    okText: "确认模拟",
    cancelText: "取消",
    onOk: () => {
      const signDate = sliceDateValue(row.signDate) || todayString();
      const sealDate = sliceDateValue(row.sealDate) || signDate;
      const activeDate =
        sliceDateValue(row.activeDate) ||
        sliceDateValue(row.effectiveStart) ||
        signDate;
      return finishLaunchSeal(row.id, {
        sealContractId: row.sealContractId || `TEST-SEAL-${row.id}`,
        sealContractStatus: 2000,
        signedFileName: `${row.contractName || "合同"}-测试已签署.pdf`,
        signedFilePath: row.contractTextFilePath || `mock-signed/${row.id}.pdf`,
        signedFileType: "pdf",
        signedFileSize: row.contractTextFileSize || null,
        signedOfflineReason: singleAgreement
          ? "测试按钮模拟内部业务章加盖完成"
          : "测试按钮模拟签署完成，真实签章接入后可删除此按钮",
        signDate: formatDateTimeValue(signDate),
        sealDate: formatDateTimeValue(sealDate),
        activeDate: formatDateTimeValue(activeDate),
      }).then((res) => {
        if (!isSuccessResponse(res)) {
          message.error(
            getResponseMessage(
              res,
              singleAgreement ? "测试盖章完成失败" : "测试签署完成失败",
            ),
          );
          return;
        }
        message.success(
          singleAgreement
            ? "测试盖章完成，单方协议已办结"
            : "测试签署完成，合同已流转到待采集",
        );
        getList();
      });
    },
    icon: null,
  });
}

function handleDownloadSigned(row) {
  const filePath = row.signedFilePath;
  const fileName =
    row.signedFileName || `${row.contractName || "合同"}-已签署版.pdf`;
  if (!filePath) {
    message.warning("暂无签署文件可下载");
    return;
  }
  downloadLaunchFile(filePath)
    .then((res) => {
      const arrayBuffer = res?.data ?? res;
      const blob = new Blob([arrayBuffer]);
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = fileName;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);
    })
    .catch(() => {
      message.error("签署文件下载失败");
    });
}

function handleUploadSigned(row) {
  uploadSignedModalRef.value?.showModal(row);
}

function handleOnlineSign(row) {
  getLaunchDetail(row.id).then((res) => {
    if (!isSuccessResponse(res) || !getDataResult(res)) {
      message.error(getResponseMessage(res, "获取合同详情失败"));
      return;
    }
    const detail = getDataResult(res);
    mixedSignModalRef.value?.showModal({
      ...detail,
      contractId: detail.sealContractId,
    });
  });
}

function handleSignBusinessUpdated() {
  getList();
}

function handleModalSave(payload) {
  const requestFn =
    payload.mode === "edit" ? updateLaunchDraft : createLaunchDraft;
  requestFn(payload.record).then((res) => {
    if (!isSuccessResponse(res)) {
      message.error(getResponseMessage(res, "保存合同失败"));
      return;
    }
    message.success(
      payload.successMessage ||
        (payload.mode === "edit" ? "合同修改成功" : "合同草稿保存成功"),
    );
    getList();
  });
}

function handleMockCollect(row) {
  Modal.confirm({
    title: "测试操作：模拟合同采集",
    content: `模拟将合同【${row.contractName}】信息采集同步至法务系统，状态将变为「待归档」。`,
    okText: "确认模拟",
    cancelText: "取消",
    onOk: () =>
      mockCollectLaunch(row.id).then((res) => {
        if (!isSuccessResponse(res)) {
          message.error(getResponseMessage(res, "模拟合同采集失败"));
          return;
        }
        message.success("测试合同采集完成，合同已流转到待归档");
        getList();
      }),
    icon: null,
  });
}

function handleArchive(row) {
  getLaunchDetail(row.id).then((res) => {
    if (!isSuccessResponse(res) || !getDataResult(res)) {
      message.error(getResponseMessage(res, "获取归档详情失败"));
      return;
    }
    contractArchiveModalRef.value?.showModal(getDataResult(res));
  });
}

function handleArchiveDone() {
  getList();
}

function handleTerminate(row) {
  let terminateReason = "";
  Modal.confirm({
    title: `确认终止合同【${row.contractName}】吗？`,
    content: h(
      "div",
      { style: { display: "flex", flexDirection: "column", gap: "12px" } },
      [
        h(
          "div",
          "除已完成外，任意环节都可终止。当前仅终止业务系统内流程，法务系统需分别操作。",
        ),
        h(Input.TextArea, {
          rows: 4,
          placeholder: "可选：请输入终止原因",
          onChange: (event) => {
            terminateReason = event?.target?.value || "";
          },
        }),
      ],
    ),
    okText: "确认终止",
    cancelText: "取消",
    okType: "danger",
    onOk: () =>
      terminateLaunchRecord(row.id, { terminateReason }).then((res) => {
        if (!isSuccessResponse(res)) {
          message.error(getResponseMessage(res, "终止合同失败"));
          return;
        }
        message.success("合同已终止");
        getList();
      }),
    icon: null,
  });
}

function handleDelete(row) {
  Modal.confirm({
    title: `确认删除合同【${row.contractName}】吗？`,
    content: "仅草稿或审批驳回状态支持删除。",
    okText: "删除",
    cancelText: "取消",
    okType: "danger",
    onOk: () => {
      deleteLaunchRecord(row.id).then((res) => {
        if (!isSuccessResponse(res)) {
          message.error(getResponseMessage(res, "删除失败"));
          return;
        }
        message.success("删除成功");
        getList();
      });
    },
  });
}

function handleBatchDelete() {
  const undeletable = selectedRows.value.filter((item) => !canDelete(item));
  if (undeletable.length) {
    message.warning("仅草稿或审批驳回状态支持删除，请重新选择");
    return;
  }
  Modal.confirm({
    title: `确认删除选中的 ${selectedRowKeys.value.length} 条记录吗？`,
    content: "仅草稿或审批驳回状态支持删除。",
    okText: "删除",
    cancelText: "取消",
    okType: "danger",
    onOk: async () => {
      for (const id of selectedRowKeys.value) {
        await deleteLaunchRecord(id);
      }
      message.success("批量删除成功");
      selectedRows.value = [];
      selectedRowKeys.value = [];
      getList();
    },
  });
}

function syncTableHeight() {
  nextTick(() => {
    const viewportHeight = window.innerHeight;
    const queryHeight = queryContainer.value?.offsetHeight || 0;
    const pageHeight = pageWrapperRef.value?.$el?.offsetHeight || 56;
    tableHeight.value = Math.max(
      320,
      viewportHeight - queryHeight - pageHeight - 320,
    );
  });
}

onMounted(() => {
  handleQuery();
  nextTick(() => {
    connectToolbar();
    syncTableHeight();
  });
  window.addEventListener("resize", syncTableHeight);
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", syncTableHeight);
});
</script>

<style scoped>
.section-container {
  height: calc(100vh - 116px);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.query-card {
  flex: 0 0 auto;
}

.table-card {
  flex: 1 1 auto;
  min-height: 0;
}

.section-query-container :deep(.ant-form-item) {
  display: flex;
  width: 100%;
  margin-bottom: 14px;
}

.section-query-container :deep(.ant-form-item .ant-form-item-control) {
  flex: 1;
}

.table-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.table-pagination {
  display: flex;
  justify-content: flex-end;
  padding: 12px 4px 2px;
}

@media (max-width: 960px) {
  .section-container {
    height: auto;
  }
}
</style>
