<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref } from "vue";
import request from "@/utils/request";
import { ElMessage } from "element-plus";
import { useRoute, useRouter } from "vue-router";
import {
  createTaskApplication,
  deleteTaskApplication,
  getTaskApplications,
  updateTaskApplication,
  type TaskApplication,
} from "@/api/tasks";
import { getUrlTitle } from "@/utils/fetchTitle";

const router = useRouter();
const route = useRoute();

const taskId = route.params.taskId ? Number(route.params.taskId) : null;
const buttonName = route.meta.buttonText as string;
const isUpdateMode = computed(() => route.meta.action === "update");

const taskNum = ref("");
const taskName = ref("");
const taskDescription = ref("");
const materialUrl = ref("");
const priority = ref({
  urgency: 0,
  importance: 0,
  contentDifficulty: 0,
  futureValue: 0,
  subjectivePriority: 0,
});

const priorityOptions = [0, 1, 2, 3, 4, 5];
const applicationStatusOptions: { label: string; value: TaskApplication["status"] }[] = [
  { label: "待应用", value: "TODO" },
  { label: "进行中", value: "DOING" },
  { label: "已完成", value: "DONE" },
];

const applications = ref<TaskApplication[]>([]);
const applicationLoading = ref(false);
const appUrlTitles = ref<Record<number, string>>({});
const applicationDialogVisible = ref(false);
const applicationSaving = ref(false);
const editingApplicationId = ref<number | null>(null);
const applicationForm = ref<{
  title: string;
  description: string;
  resourceUrl: string;
  status: TaskApplication["status"];
}>({
  title: "",
  description: "",
  resourceUrl: "",
  status: "TODO",
});

const openApplicationDialog = () => {
  resetApplicationForm();
  applicationDialogVisible.value = true;
};

const resetApplicationForm = () => {
  editingApplicationId.value = null;
  applicationForm.value = {
    title: "",
    description: "",
    resourceUrl: "",
    status: "TODO",
  };
};

const loadApplications = async (targetTaskNum: string) => {
  applicationLoading.value = true;
  try {
    const res = await getTaskApplications(targetTaskNum);
    applications.value = res?.data || [];
    // 异步抓取标题
    const map: Record<number, string> = {};
    await Promise.all(
      applications.value
        .filter((a) => a.resourceUrl)
        .map(async (a) => {
          map[a.id] = await getUrlTitle(a.resourceUrl!);
        })
    );
    appUrlTitles.value = map;
  } catch (error: any) {
    applications.value = [];
    ElMessage.error(error?.message || "应用场景加载失败");
  } finally {
    applicationLoading.value = false;
  }
};

const saveApplication = async () => {
  if (!taskNum.value) {
    ElMessage.warning("任务编号未加载，暂不能维护应用场景");
    return;
  }
  if (!applicationForm.value.title.trim()) {
    ElMessage.warning("应用项目标题不能为空");
    return;
  }
  applicationSaving.value = true;
  try {
    const payload = {
      title: applicationForm.value.title,
      description: applicationForm.value.description,
      resourceUrl: applicationForm.value.resourceUrl,
      status: applicationForm.value.status,
    };
    if (editingApplicationId.value) {
      await updateTaskApplication(editingApplicationId.value, payload);
      ElMessage.success("应用场景已更新");
    } else {
      await createTaskApplication(taskNum.value, payload);
      ElMessage.success("应用场景已添加");
    }
    applicationDialogVisible.value = false;
    resetApplicationForm();
    await loadApplications(taskNum.value);
  } finally {
    applicationSaving.value = false;
  }
};

const editApplication = (item: TaskApplication) => {
  editingApplicationId.value = item.id;
  applicationForm.value = {
    title: item.title || "",
    description: item.description || "",
    resourceUrl: item.resourceUrl || "",
    status: item.status || "TODO",
  };
  applicationDialogVisible.value = true;
};

const removeApplication = async (item: TaskApplication) => {
  await deleteTaskApplication(item.id);
  ElMessage.success("应用场景已删除");
  if (editingApplicationId.value === item.id) {
    resetApplicationForm();
  }
  if (taskNum.value) {
    await loadApplications(taskNum.value);
  }
};

const convertMaterialUrls = async () => {
  const raw = materialUrl.value || "";
  if (!raw.trim()) return;
  const bareUrls = new Set<string>();
  raw.replace(/https?:\/\/[^\s)\u3001\uFF09\u300D\u300B<>]+/g, (url) => {
    const clean = url.replace(/[.。,，;；!！?？）】」』\]]+$/, "");
    // 跳过 [text](url) 内的
    if (!raw.includes(`](${clean})`)) bareUrls.add(clean);
    return url;
  });
  if (bareUrls.size === 0) return;
  const titles: Record<string, string> = {};
  const results = await Promise.all([...bareUrls].map(async (u) => ({ u, t: await getUrlTitle(u) })));
  results.forEach(({ u, t }) => { titles[u] = t; });
  let result = raw;
  for (const u of bareUrls) {
    if (titles[u] && titles[u] !== u) {
      result = result.replace(u, `[${titles[u].replace(/]/g, "\\]")}](${u})`);
    }
  }
  materialUrl.value = result;
};

const createTask = () => {
  convertMaterialUrls().then(() => {
    request
    .post("/tasks", {
      taskName: taskName.value,
      taskDescription: taskDescription.value,
      materialUrl: materialUrl.value,
      ...priority.value,
    })
    .then((result) => {
      if (result.code === 200) {
        ElMessage.success("创建任务成功");
        router.push({ name: "study" });
      } else {
        ElMessage.error("任务创建失败：" + result.message);
      }
    });
  });
};

const loadTask = () => {
  if (taskId !== null) {
    request.get(`/tasks/${taskId}`, {}).then((result) => {
      if (result.code === 200) {
        const data = result.data;
        taskNum.value = data.taskNum || "";
        taskName.value = data.taskName;
        taskDescription.value = data.taskDescription;
        materialUrl.value = data.materialUrl || "";
        priority.value = {
          urgency: data.urgency,
          importance: data.importance,
          contentDifficulty: data.contentDifficulty,
          futureValue: data.futureValue,
          subjectivePriority: data.subjectivePriority,
        };
        if (taskNum.value) {
          loadApplications(taskNum.value);
        }
      } else {
        ElMessage.error(`任务加载失败：${result.message}`);
      }
    });
  }
};

const updateTask = () => {
  convertMaterialUrls().then(() => {
    request
    .put("/tasks/" + taskId, {
      id: taskId,
      taskName: taskName.value,
      taskDescription: taskDescription.value,
      materialUrl: materialUrl.value,
      ...priority.value,
    })
    .then((result) => {
      if (result.code === 200) {
        ElMessage.success("更新任务成功");
        router.push({ name: "study" });
      } else {
        ElMessage.error("任务更新失败：" + result.message);
      }
    });
  });
};

const cancelTask = () => {
  ElMessage.info("已取消操作");
  router.push({ name: "study" });
};

const submitTask = () => {
  switch (route.name) {
    case "add-task":
      createTask();
      break;
    case "update-task":
      updateTask();
      break;
    default:
      ElMessage.error("未知操作类型");
  }
};

const screenWidth = ref(window.innerWidth);

const updateWidth = () => {
  screenWidth.value = window.innerWidth;
};

onMounted(() => {
  window.addEventListener("resize", updateWidth);
  if (route.meta.action === "update" && taskId !== null) {
    loadTask();
  }
});

onUnmounted(() => window.removeEventListener("resize", updateWidth));

const isMobile = computed(() => screenWidth.value <= 900);

// 学习材料 Markdown 预览
const showPreview = ref(false);
const materialPreview = ref("");
const previewLoading = ref(false);

const escapeHtml = (s: string) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
const escapeAttr = (s: string) => s.replace(/"/g, "&quot;").replace(/&/g, "&amp;");

function renderMarkdown(raw: string, urlTitles: Record<string, string> = {}): string {
  if (!raw.trim()) return "";
  let html = raw;
  // 1) [text](url) → &lt;a&gt; 占位，防止后续裸 URL 匹配进属性里
  const links: string[] = [];
  html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m: string, text: string, url: string) => {
    const tag = `<a href="${escapeAttr(url)}" target="_blank" rel="noopener">${escapeHtml(text)}</a>`;
    links.push(tag);
    return `__LINK_${links.length - 1}__`;
  });
  // 2) 裸 URL → &lt;a&gt; 占位
  html = html.replace(/https?:\/\/[^\s)\u3001\uFF09\u300D\u300B<>]+/g, (url) => {
    const clean = url.replace(/[.。,，;；!！?？）】」』\]]+$/, "");
    const label = urlTitles[clean] || url;
    const tag = `<a href="${escapeAttr(clean)}" target="_blank" rel="noopener">${escapeHtml(label)}</a>`;
    links.push(tag);
    return `__LINK_${links.length - 1}__`;
  });
  // 3) 换行
  html = html.replace(/\n/g, "<br>");
  // 4) 还原占位
  for (let i = 0; i < links.length; i++) {
    html = html.replace(`__LINK_${i}__`, links[i]);
  }
  return html;
}

async function previewMaterial() {
  showPreview.value = true;
  const raw = materialUrl.value || "";
  if (!raw.trim()) { materialPreview.value = ""; return; }
  previewLoading.value = true;
  try {
    const titles: Record<string, string> = {};
    const bareUrls = new Set<string>();
    raw.replace(/https?:\/\/[^\s)\u3001\uFF09\u300D\u300B<>]+/g, (url) => {
      bareUrls.add(url.replace(/[.。,，;；!！?？）】」』\]]+$/, ""));
      return url;
    });
    const results = await Promise.all([...bareUrls].map(async (u) => ({ u, t: await getUrlTitle(u) })));
    results.forEach(({ u, t }) => { titles[u] = t; });
    materialPreview.value = renderMarkdown(raw, titles);
  } finally {
    previewLoading.value = false;
  }
}
</script>

<template>
  <section class="task-form-page">
    <el-form label-position="top" class="surface-card form-shell">
      <div class="group">
        <h3>基础信息</h3>
        <el-form-item label="任务名称">
          <el-input v-model="taskName" placeholder="例如：Vue3 组件通信实践" />
        </el-form-item>
        <el-form-item label="任务描述">
          <el-input v-model="taskDescription" type="textarea" :rows="5" placeholder="请输入任务描述" />
        </el-form-item>
        <el-form-item>
          <template #label>
            <div class="material-label">
              <span>学习材料地址</span>
              <el-button
                v-if="!showPreview"
                text
                size="small"
                type="primary"
                @click="previewMaterial()"
              >预览</el-button>
              <el-button
                v-else
                text
                size="small"
                @click="showPreview = false"
              >编辑</el-button>
              <span class="material-hint" v-if="!showPreview">[链接文字](url) 或直接粘贴链接</span>
              <span class="material-hint" v-else>链接会自动获取标题展示</span>
            </div>
          </template>
          <el-input
            v-if="!showPreview"
            v-model="materialUrl"
            type="textarea"
            :rows="6"
            placeholder="支持 Markdown 格式&#10;例如：&#10;参考 [Vue.js 文档](https://vuejs.org/guide)&#10;源码在 https://github.com/vuejs/core"
          />
          <div v-else class="material-preview" v-html="materialPreview" />
        </el-form-item>
      </div>

      <div class="group">
        <h3>优先级维度</h3>
        <div class="priority-grid" :class="{ mobile: isMobile }">
          <el-form-item label="急迫性">
            <el-select v-model="priority.urgency">
              <el-option v-for="item in priorityOptions" :key="'u' + item" :label="item" :value="item" />
            </el-select>
          </el-form-item>

          <el-form-item label="重要性">
            <el-select v-model="priority.importance">
              <el-option v-for="item in priorityOptions" :key="'i' + item" :label="item" :value="item" />
            </el-select>
          </el-form-item>

          <el-form-item label="内容难度">
            <el-select v-model="priority.contentDifficulty">
              <el-option v-for="item in priorityOptions" :key="'d' + item" :label="item" :value="item" />
            </el-select>
          </el-form-item>

          <el-form-item label="未来价值">
            <el-select v-model="priority.futureValue">
              <el-option v-for="item in priorityOptions" :key="'f' + item" :label="item" :value="item" />
            </el-select>
          </el-form-item>

          <el-form-item label="主观优先级">
            <el-select v-model="priority.subjectivePriority">
              <el-option v-for="item in priorityOptions" :key="'s' + item" :label="item" :value="item" />
            </el-select>
          </el-form-item>
        </div>
      </div>

      <div class="group" v-if="isUpdateMode" v-loading="applicationLoading">
        <div class="application-header">
          <h3>应用场景</h3>
          <el-button type="primary" @click="openApplicationDialog()">添加应用场景</el-button>
        </div>
        <div class="application-list" v-if="applications.length > 0">
          <div class="application-item" v-for="item in applications" :key="item.id">
            <div class="application-main">
              <strong>{{ item.title }}</strong>
              <el-tag size="small" effect="plain">
                {{ applicationStatusOptions.find(option => option.value === item.status)?.label || item.status }}
              </el-tag>
            </div>
            <p v-if="item.description">{{ item.description }}</p>
            <el-link v-if="item.resourceUrl" :href="item.resourceUrl" target="_blank" type="primary">
              {{ appUrlTitles[item.id] || item.resourceUrl }}
            </el-link>
            <div class="application-actions">
              <el-button text type="primary" size="small" @click="editApplication(item)">编辑</el-button>
              <el-button text type="danger" size="small" @click="removeApplication(item)">删除</el-button>
            </div>
          </div>
        </div>
        <p v-else class="empty-text">暂未设置应用场景</p>
      </div>

      <el-dialog v-model="applicationDialogVisible" :title="editingApplicationId ? '编辑应用场景' : '添加应用场景'" width="500px">
        <el-form label-position="top">
          <el-form-item label="应用项目" required>
            <el-input v-model="applicationForm.title" placeholder="例如：用Vue3重构个人博客" />
          </el-form-item>
          <el-form-item label="应用描述">
            <el-input v-model="applicationForm.description" type="textarea" :rows="4" placeholder="描述如何应用所学内容" />
          </el-form-item>
          <el-form-item label="相关链接">
            <el-input v-model="applicationForm.resourceUrl" placeholder="https://..." />
          </el-form-item>
          <el-form-item label="状态">
            <el-select v-model="applicationForm.status" placeholder="状态">
              <el-option v-for="option in applicationStatusOptions" :key="option.value" :label="option.label" :value="option.value" />
            </el-select>
          </el-form-item>
        </el-form>
        <template #footer>
          <el-button @click="applicationDialogVisible = false">取消</el-button>
          <el-button type="success" :loading="applicationSaving" @click="saveApplication">
            {{ editingApplicationId ? '更新' : '添加' }}
          </el-button>
        </template>
      </el-dialog>

      <div class="action-row">
        <el-button type="success" size="large" @click="submitTask">{{ buttonName }}</el-button>
        <el-button size="large" @click="cancelTask">取消</el-button>
      </div>
    </el-form>
  </section>
</template>

<style scoped>
.task-form-page {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.form-shell {
  padding: 22px;
}

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

.group h3 {
  margin: 0 0 12px;
  color: var(--green-900);
}

.material-label {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 8px;
}

.material-label .material-hint {
  font-size: 12px;
  color: var(--text-secondary);
  font-weight: 400;
}

.material-preview {
  min-height: 120px;
  padding: 14px 16px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: #fafdfb;
  font-size: 14px;
  line-height: 1.8;
  word-break: break-word;
  color: var(--text-primary);
}

.material-preview :deep(a) {
  color: var(--green-600);
  text-decoration: none;
  border-bottom: 1px dashed var(--green-400);
  transition: color 0.15s, border-color 0.15s;
}

.material-preview :deep(a:hover) {
  color: var(--green-800);
  border-bottom-style: solid;
}

.material-preview :deep(a)::after {
  content: " ↗";
  font-size: 11px;
  opacity: 0.5;
}

.priority-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 14px;
}

.priority-grid.mobile {
  grid-template-columns: 1fr;
}

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

.application-header h3 {
  margin: 0;
}

.application-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 14px;
}

.application-item {
  padding: 12px;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: #fbfefc;
}

.application-main {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.application-main strong {
  min-width: 0;
  color: var(--text-primary);
  word-break: break-word;
}

.application-item p {
  margin: 8px 0 0;
  color: var(--text-secondary);
  font-size: 13px;
  word-break: break-word;
}

.application-actions {
  display: flex;
  justify-content: flex-end;
  gap: 4px;
  margin-top: 8px;
}

.empty-text {
  margin: 0 0 12px;
  color: var(--text-secondary);
  font-size: 13px;
}

.action-row {
  margin-top: 8px;
  display: flex;
  gap: 10px;
}

@media (max-width: 768px) {
  .form-shell {
    padding: 16px;
  }

  .action-row {
    flex-direction: column;
  }

  .action-row .el-button {
    width: 100%;
    margin: 0;
  }

  .application-main {
    align-items: flex-start;
    flex-direction: column;
  }

}
</style>
