<template>
  <div class="page ctms-page-shell page--flush">
    <div v-if="study.currentStudy" class="unified-shell ctms-table-card">
      <section class="unified-action-bar milestone-action-bar">
        <div class="card-header ctms-page-header-row">
          <div class="card-title">{{ TEXT.modules.projectMilestones.listTitle }}</div>
          <div class="header-actions">
            <el-tag size="small" effect="plain">
              {{ TEXT.modules.projectMilestones.statTotal }}{{ rows.length }}
            </el-tag>
            <el-tag size="small" type="success" effect="plain">
              {{ TEXT.modules.projectMilestones.statDone }}{{ doneCount }}
            </el-tag>
            <el-button size="small" @click="loadMilestones">{{ TEXT.common.actions.refresh }}</el-button>
          </div>
        </div>
      </section>
      <section class="unified-section ctms-page-content-grid section--flush-x section--flush-top section--flush-bottom">
        <el-table :data="rows" v-loading="loading" class="ctms-table" style="width: 100%" table-layout="fixed">
          <el-table-column prop="name" :label="TEXT.modules.projectMilestones.columns.name" show-overflow-tooltip />
          <el-table-column prop="planDate" :label="TEXT.modules.projectMilestones.columns.planDate">
            <template #default="scope">
              <div class="plan-time-cell">
                <div class="plan-time-line">
                  <span class="plan-time-dot plan-time-dot-initial" />
                  <span class="plan-time-label">开始:</span>
                  <span>{{ scope.row.startDate || TEXT.common.fallback }}</span>
                </div>
                <div class="plan-time-line">
                  <span class="plan-time-dot plan-time-dot-initial" />
                  <span class="plan-time-label">结束:</span>
                  <span>{{ scope.row.endDate || TEXT.common.fallback }}</span>
                </div>
                <div class="plan-time-line">
                  <span class="plan-time-dot plan-time-dot-initial" />
                  <span class="plan-time-label">耗时:</span>
                  <span>{{ scope.row.durationText }}</span>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column :label="TEXT.modules.projectMilestones.columns.adjustedPlanDate">
            <template #default="scope">
              <div class="plan-time-cell">
                <div class="plan-time-line">
                  <span class="plan-time-dot plan-time-dot-adjusted" />
                  <span class="plan-time-label">开始:</span>
                  <span>{{ scope.row.adjustedStartDate || TEXT.common.fallback }}</span>
                </div>
                <div class="plan-time-line">
                  <span class="plan-time-dot plan-time-dot-adjusted" />
                  <span class="plan-time-label">结束:</span>
                  <span>{{ scope.row.adjustedEndDate || TEXT.common.fallback }}</span>
                </div>
                <div class="plan-time-line">
                  <span class="plan-time-dot plan-time-dot-adjusted" />
                  <span class="plan-time-label">耗时:</span>
                  <span>{{ scope.row.adjustedDurationText }}</span>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column :label="TEXT.modules.projectMilestones.columns.actualTime">
            <template #default="scope">
              <div class="plan-time-cell">
                <div class="plan-time-line">
                  <span class="plan-time-dot plan-time-dot-actual" />
                  <span class="plan-time-label">开始:</span>
                  <span>{{ scope.row.actualStartDate || TEXT.common.fallback }}</span>
                </div>
                <div class="plan-time-line">
                  <span class="plan-time-dot plan-time-dot-actual" />
                  <span class="plan-time-label">结束:</span>
                  <span>{{ scope.row.actualEndDate || TEXT.common.fallback }}</span>
                </div>
                <div class="plan-time-line">
                  <span class="plan-time-dot plan-time-dot-actual" />
                  <span class="plan-time-label">耗时:</span>
                  <span>{{ scope.row.actualDurationText }}</span>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="status" :label="TEXT.modules.projectMilestones.columns.status">
            <template #default="scope">
              <div class="status-cell" :class="`status-${getStatusView(scope.row).tone}`">
                <div class="status-main">
                  <span class="status-dot" />
                  <span>{{ getStatusView(scope.row).title }}<span v-if="getStatusView(scope.row).detail">，</span></span>
                </div>
                <div v-if="getStatusView(scope.row).detail" class="status-detail">{{ getStatusView(scope.row).detail }}</div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="remark" :label="TEXT.modules.projectMilestones.columns.remark" show-overflow-tooltip>
            <template #default="scope">{{ scope.row.remark || TEXT.common.fallback }}</template>
          </el-table-column>
          <el-table-column v-if="canUpdateMilestones" :label="TEXT.modules.projectMilestones.columns.operations" width="100">
            <template #default="scope">
              <el-button v-if="canUpdateMilestones" link type="primary" @click="openEditor(scope.row)">{{ TEXT.common.actions.edit }}</el-button>
            </template>
          </el-table-column>
          <template #empty>
            <div v-if="!loading" class="table-empty">{{ TEXT.modules.projectMilestones.emptyDescription }}</div>
          </template>
        </el-table>
      </section>
    </div>
    <StateEmpty v-else :description="TEXT.common.empty.selectProject" />

    <el-drawer
      v-if="editorVisible"
      v-model="editorVisible"
      direction="rtl"
      size="460px"
      :close-on-click-modal="true"
      :before-close="editorDirtyGuard.beforeClose"
      :show-close="false"
      class="milestone-editor-drawer"
    >
      <template #header>
        <div class="time-editor-title">编辑里程碑</div>
      </template>
      <el-form label-position="top" class="time-editor-form">
        <div class="time-editor-group">
          <div class="time-editor-group-title">
            <span class="group-dot group-dot-adjusted"></span>
            调整计划时间
          </div>
          <el-row :gutter="12">
            <el-col :span="12">
              <el-form-item label="开始日期">
                <el-date-picker v-model="editorForm.adjustedStartDate" type="date" value-format="YYYY-MM-DD" class="w-full" placeholder="选择日期" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="结束日期">
                <el-date-picker v-model="editorForm.adjustedEndDate" type="date" value-format="YYYY-MM-DD" class="w-full" placeholder="选择日期" />
              </el-form-item>
            </el-col>
          </el-row>
          <div class="duration-inline">
            <span class="duration-label">耗时</span>
            <span class="duration-value">{{ toDurationText(calcDurationDays(editorForm.adjustedStartDate, editorForm.adjustedEndDate)) }}</span>
          </div>
        </div>

        <div class="time-editor-group">
          <div class="time-editor-group-title">
            <span class="group-dot group-dot-actual"></span>
            实际时间
          </div>
          <el-row :gutter="12">
            <el-col :span="12">
              <el-form-item label="开始日期">
                <el-date-picker v-model="editorForm.actualStartDate" type="date" value-format="YYYY-MM-DD" class="w-full" placeholder="选择日期" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="结束日期">
                <el-date-picker v-model="editorForm.actualEndDate" type="date" value-format="YYYY-MM-DD" class="w-full" placeholder="选择日期" />
              </el-form-item>
            </el-col>
          </el-row>
          <div class="duration-inline">
            <span class="duration-label">耗时</span>
            <span class="duration-value">{{ toDurationText(calcDurationDays(editorForm.actualStartDate, editorForm.actualEndDate)) }}</span>
          </div>
        </div>

        <div class="time-editor-group">
          <div class="time-editor-group-title">
            <span class="group-dot group-dot-remark"></span>
            备注
          </div>
          <el-input v-model="editorForm.remark" type="textarea" :rows="3" placeholder="请输入备注" />
        </div>
      </el-form>
      <template #footer>
        <div class="time-editor-footer">
          <el-button @click="editorVisible = false">{{ TEXT.common.actions.cancel }}</el-button>
          <el-button v-if="canUpdateMilestones" type="primary" @click="saveEditor">{{ TEXT.common.actions.save }}</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from "vue";
import { ElMessage } from "element-plus";
import { useStudyStore } from "../../store/study";
import { listProjectMilestones, updateProjectMilestone } from "../../api/projectMilestones";
import { TEXT } from "../../locales";
import StateEmpty from "../../components/StateEmpty.vue";
import { usePermission } from "../../utils/permission";
import { useDrawerDirtyGuard } from "../../utils/drawerDirtyGuard";

interface MilestoneRow {
  id: string;
  name: string;
  planDate: string;
  startDate: string;
  endDate: string;
  durationDays: number | null;
  durationText: string;
  adjustedStartDate: string;
  adjustedEndDate: string;
  adjustedDurationDays: number | null;
  adjustedDurationText: string;
  actualStartDate: string;
  actualEndDate: string;
  actualDurationDays: number | null;
  actualDurationText: string;
  owner: string;
  status: string;
  remark: string;
}

type MilestoneLocalEdit = {
  adjustedStartDate?: string;
  adjustedEndDate?: string;
  actualStartDate?: string;
  actualEndDate?: string;
  remark?: string;
};

const study = useStudyStore();
const { can } = usePermission();
const rows = ref<MilestoneRow[]>([]);
const loading = ref(false);
const editorVisible = ref(false);
const editingRowId = ref("");
const editorForm = reactive<MilestoneLocalEdit>({
  adjustedStartDate: "",
  adjustedEndDate: "",
  actualStartDate: "",
  actualEndDate: "",
  remark: "",
});
const editorDirtyGuard = useDrawerDirtyGuard(() => editorForm);

const doneCount = computed(() => rows.value.filter((item) => getStatusView(item).completed).length);
const canUpdateMilestones = computed(() => can("project.milestones.update"));

const toDateOnly = (value?: string): Date | null => {
  if (!value) return null;
  const d = new Date(`${value}T00:00:00`);
  if (Number.isNaN(d.getTime())) return null;
  return d;
};

const calcDurationDays = (start?: string, end?: string): number | null => {
  if (!start || !end) return null;
  const startDate = toDateOnly(start);
  const endDate = toDateOnly(end);
  if (!startDate || !endDate || endDate < startDate) return null;
  return Math.floor((endDate.getTime() - startDate.getTime()) / 86400000) + 1;
};

const toDurationText = (days: number | null) => (days && days > 0 ? `${days}天` : TEXT.common.fallback);

const normalizeRow = (row: any): MilestoneRow => {
  const startDate = String(row?.planned_date || "").trim();
  const endDate = String(row?.planned_date || "").trim();
  const adjustedStartDate = String(row?.adjusted_start_date || "").trim();
  const adjustedEndDate = String(row?.adjusted_end_date || "").trim();
  const actualStartDate = String(row?.actual_start_date || "").trim();
  const actualEndDate = String(row?.actual_end_date || "").trim();
  const adjustedDurationDays = calcDurationDays(adjustedStartDate, adjustedEndDate);
  const actualDurationDays = calcDurationDays(actualStartDate, actualEndDate);
  return {
    id: row?.id || "",
    name: String(row?.name || "").trim(),
    planDate: startDate,
    startDate,
    endDate,
    durationDays: startDate ? 1 : null,
    durationText: startDate ? "1天" : TEXT.common.fallback,
    adjustedStartDate,
    adjustedEndDate,
    adjustedDurationDays,
    adjustedDurationText: toDurationText(adjustedDurationDays),
    actualStartDate,
    actualEndDate,
    actualDurationDays,
    actualDurationText: toDurationText(actualDurationDays),
    owner: String(row?.owner_name || "").trim(),
    status: String(row?.status || "NOT_STARTED").trim(),
    remark: String(row?.notes || "").trim(),
  };
};

const loadMilestones = async () => {
  const studyId = study.currentStudy?.id;
  if (!studyId) return;
  loading.value = true;
  try {
    const { data } = (await listProjectMilestones(studyId)) as any;
    const list = Array.isArray(data) ? data : data?.items || [];
    rows.value = list.map(normalizeRow);
  } catch (error: any) {
    rows.value = [];
    ElMessage.error(error?.response?.data?.detail || TEXT.common.messages.loadFailed);
  } finally {
    loading.value = false;
  }
};

const daysDiff = (start: string, end: string): number => {
  const a = toDateOnly(start);
  const b = toDateOnly(end);
  if (!a || !b) return 0;
  return Math.floor((b.getTime() - a.getTime()) / 86400000);
};

const todayDateText = () => {
  const now = new Date();
  const pad = (n: number) => String(n).padStart(2, "0");
  return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
};

const getStatusView = (row: MilestoneRow): { title: string; detail: string; tone: "success" | "warning" | "danger" | "info"; completed: boolean } => {
  const planEnd = row.adjustedEndDate || row.endDate || "";
  const actualStart = row.actualStartDate || "";
  const actualEnd = row.actualEndDate || "";
  const today = todayDateText();

  if (actualEnd) {
    if (planEnd && actualEnd > planEnd) {
      const lateDays = daysDiff(planEnd, actualEnd);
      return {
        title: "延期完成",
        detail: lateDays > 0 ? `延迟 ${lateDays} 天` : "",
        tone: "danger",
        completed: true,
      };
    }
    if (planEnd && actualEnd < planEnd) {
      const earlyDays = daysDiff(actualEnd, planEnd);
      return {
        title: "提前完成",
        detail: earlyDays > 0 ? `提前 ${earlyDays} 天` : "",
        tone: "success",
        completed: true,
      };
    }
    return { title: "已完成", detail: "", tone: "success", completed: true };
  }

  if (actualStart) {
    if (planEnd && today > planEnd) {
      const lateDays = daysDiff(planEnd, today);
      return {
        title: "延期进行中",
        detail: lateDays > 0 ? `延迟 ${lateDays} 天` : "",
        tone: "danger",
        completed: false,
      };
    }
    return { title: "进行中", detail: "", tone: "warning", completed: false };
  }

  if (planEnd && today > planEnd) {
    const lateDays = daysDiff(planEnd, today);
    return {
      title: "延期未开始",
      detail: lateDays > 0 ? `延迟 ${lateDays} 天` : "",
      tone: "danger",
      completed: false,
    };
  }

  return { title: "未开始", detail: "", tone: "info", completed: false };
};

const validateDateRange = (start?: string, end?: string, label?: string) => {
  if ((start && !end) || (!start && end)) {
    ElMessage.warning(`${label}开始和结束日期需同时填写`);
    return false;
  }
  if (start && end && start > end) {
    ElMessage.warning(`${label}结束日期不能早于开始日期`);
    return false;
  }
  return true;
};

const openEditor = (row: MilestoneRow) => {
  if (!canUpdateMilestones.value) {
    ElMessage.warning("权限不足");
    return;
  }
  editingRowId.value = row.id;
  editorForm.adjustedStartDate = row.adjustedStartDate || "";
  editorForm.adjustedEndDate = row.adjustedEndDate || "";
  editorForm.actualStartDate = row.actualStartDate || "";
  editorForm.actualEndDate = row.actualEndDate || "";
  editorForm.remark = row.remark || "";
  editorDirtyGuard.syncBaseline();
  editorVisible.value = true;
};

const saveEditor = async () => {
  const studyId = study.currentStudy?.id;
  if (!studyId || !editingRowId.value) return;
  if (!canUpdateMilestones.value) {
    ElMessage.warning("权限不足");
    return;
  }
  if (!validateDateRange(editorForm.adjustedStartDate, editorForm.adjustedEndDate, "调整计划时间")) return;
  if (!validateDateRange(editorForm.actualStartDate, editorForm.actualEndDate, "实际时间")) return;
  const patch = {
    adjusted_start_date: editorForm.adjustedStartDate || null,
    adjusted_end_date: editorForm.adjustedEndDate || null,
    actual_start_date: editorForm.actualStartDate || null,
    actual_end_date: editorForm.actualEndDate || null,
    notes: (editorForm.remark || "").trim() || null,
  };
  try {
    await updateProjectMilestone(studyId, editingRowId.value, patch);
    await loadMilestones();
    editorVisible.value = false;
    ElMessage.success("里程碑时间已更新");
  } catch (error: any) {
    ElMessage.error(error?.response?.data?.detail || TEXT.common.messages.saveFailed);
  }
};

onMounted(() => {
  loadMilestones();
});

watch(
  () => study.currentStudy?.id,
  () => {
    rows.value = [];
    loadMilestones();
  }
);
</script>

<style scoped>
.page {
  display: flex;
  flex-direction: column;
  /* 撑满父容器（desktop-route-shell 已经是 height: 100%）*/
  height: 100%;
  min-height: 0;
}

/* 让白色卡片壳撑满 .page 的剩余高度，并去掉圆角 */
.page > .unified-shell {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-radius: 0;
}

/* 让表格 section 撑满卡片壳的剩余高度 */
.page > .unified-shell > .unified-section {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* el-table 本身填满 section */
.page > .unified-shell > .unified-section :deep(.el-table),
.page > .unified-shell > .unified-section :deep(.el-table__inner-wrapper) {
  height: 100%;
}

.ctms-page-content-grid {
  gap: 0;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 0;
  flex-wrap: wrap;
}

.milestone-action-bar {
  min-height: 56px;
  box-sizing: border-box;
}

.card-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--unified-title-color);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.plan-time-cell {
  display: flex;
  flex-direction: column;
  gap: 0;
  line-height: 1.2;
}

.plan-time-line {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--ctms-text-main);
  font-size: 11px;
}

.plan-time-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 3px solid #2f84c6;
  box-sizing: border-box;
  background: var(--ctms-bg-card);
}

.plan-time-label {
  color: var(--ctms-text-secondary);
  font-size: 11px;
}

.plan-time-dot-initial {
  border-color: #2f84c6;
}

.plan-time-dot-adjusted {
  border-color: #f0ad2c;
}

.plan-time-dot-actual {
  border-color: #67c23a;
}

.time-editor-form {
  padding-top: 4px;
  padding-right: 4px;
}

.time-editor-group {
  border: 1px solid var(--ctms-border-color);
  border-radius: 10px;
  padding: 14px 16px 10px;
  background: var(--ctms-bg-muted);
}

.time-editor-group + .time-editor-group {
  margin-top: 12px;
}

.time-editor-title {
  font-size: 20px;
  font-weight: 700;
  color: var(--ctms-text-main);
}

.time-editor-group-title {
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 12px;
  color: var(--ctms-text-main);
  display: flex;
  align-items: center;
  gap: 8px;
}

.group-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.group-dot-adjusted {
  background: #f0ad2c;
}

.group-dot-actual {
  background: #67c23a;
}

.group-dot-remark {
  background: #909399;
}

.duration-inline {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0 2px;
}

.duration-label {
  font-size: 13px;
  color: var(--ctms-text-secondary);
  font-weight: 500;
}

.duration-value {
  font-size: 14px;
  font-weight: 700;
  color: var(--ctms-text-main);
}

.time-editor-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.time-editor-footer :deep(.el-button--primary) {
  border-radius: 8px;
  font-weight: 600;
}

.time-editor-form :deep(.el-form-item) {
  margin-bottom: 10px;
}

.time-editor-form :deep(.el-form-item__label) {
  font-size: 13px;
  font-weight: 600;
  color: var(--ctms-text-regular);
  padding-bottom: 4px;
}

.status-cell {
  display: flex;
  flex-direction: column;
  gap: 1px;
  line-height: 1.3;
  font-size: 11px;
}

.status-main {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #94a3b8;
}

.status-detail {
  padding-left: 14px;
  color: var(--ctms-text-secondary);
  font-size: 11px;
}

.status-success .status-dot {
  background: #22c55e;
}

.status-warning .status-dot {
  background: #f59e0b;
}

.status-danger .status-dot {
  background: #ef4444;
}

.status-info .status-dot {
  background: #94a3b8;
}

.ctms-table :deep(.el-table__inner-wrapper::before) {
  display: none;
}

.table-empty {
  min-height: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ctms-text-secondary);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.02em;
}

</style>
