<script setup>
import { Delete, Edit, FolderAdd, FolderOpened, Link, Plus, Refresh, Search, Setting } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { computed, onMounted, reactive, ref } from "vue";
import { apiDelete, apiGet, apiPost, apiPut } from "../api/http";
import FolderCreateDialog from "../components/FolderCreateDialog.vue";
import RequestParamsTabs from "../components/RequestParamsTabs.vue";
import { buildFolderTreeRows, collectFolderPaths, normalizeFolderPath } from "../utils/folderTree";
import { collectKeyValueObject, normalizeKeyValueRows } from "../utils/keyValue";

const loading = ref(false);
const saving = ref(false);
const drawerVisible = ref(false);
const drawerMode = ref("create");
const editingId = ref(null);
const searchKeyword = ref("");
const rawRows = ref([]);
const declaredFolderPaths = ref([]);
const folderDialogVisible = ref(false);
const folderDialogMode = ref("create");
const folderDialogParentPath = ref("");
const folderDialogEditPath = ref("");

const formState = reactive({
  name: "",
  folder_path: "",
  method: "GET",
  url: "",
  description: "",
  timeout_seconds: 10,
  body_text: "{}",
  query_text: "{}",
});

const headerRows = ref([{ key: "", value: "" }]);
const pathParamRows = ref([{ key: "", value: "" }]);
const requestParams = ref([]);
const responseParams = ref([]);

const paramTypeOptions = ["string", "integer", "number", "boolean", "object", "array"];

function addRequestParam() {
  requestParams.value.push({ name: "", type: "string", required: false, description: "" });
}

function removeRequestParam(index) {
  requestParams.value.splice(index, 1);
}

function addResponseParam() {
  responseParams.value.push({ name: "", type: "string", required: false, description: "" });
}

function removeResponseParam(index) {
  responseParams.value.splice(index, 1);
}

const methodOptions = ["GET", "POST", "PUT", "DELETE", "PATCH"];

const visibleRows = computed(() => {
  const keyword = searchKeyword.value.trim().toLowerCase();
  if (!keyword) return rawRows.value;
  return rawRows.value.filter((row) =>
    [row.name, row.folder_path, row.method, row.url, row.creator_name].some((value) =>
      String(value || "")
        .toLowerCase()
        .includes(keyword)
    )
  );
});

const visibleFolderPaths = computed(() => {
  const keyword = searchKeyword.value.trim().toLowerCase();
  const paths = collectFolderPaths(visibleRows.value, declaredFolderPaths.value);
  if (!keyword) return paths;
  return paths.filter((path) => path.toLowerCase().includes(keyword));
});

const treeRows = computed(() => buildFolderTreeRows(visibleRows.value, visibleFolderPaths.value));
const folderCount = computed(() => visibleFolderPaths.value.length);
const folderOptions = computed(() => collectFolderPaths(rawRows.value, declaredFolderPaths.value));

function resetForm() {
  formState.name = "";
  formState.folder_path = "";
  formState.method = "GET";
  formState.url = "";
  formState.description = "";
  formState.timeout_seconds = 10;
  formState.body_text = "{}";
  formState.query_text = "{}";
  headerRows.value = [{ key: "", value: "" }];
  pathParamRows.value = [{ key: "", value: "" }];
  requestParams.value = [];
  responseParams.value = [];
}

function openCreateDrawer() {
  drawerMode.value = "create";
  editingId.value = null;
  resetForm();
  drawerVisible.value = true;
}

function openCreateDrawerFromFolder(folderPath) {
  drawerMode.value = "create";
  editingId.value = null;
  resetForm();
  formState.folder_path = folderPath || "";
  drawerVisible.value = true;
}

function openEditDrawer(row) {
  drawerMode.value = "edit";
  editingId.value = row.id;
  formState.name = row.name || "";
  formState.folder_path = row.folder_path || "";
  formState.method = row.method || "GET";
  formState.url = row.url || "";
  formState.description = row.description || "";
  formState.timeout_seconds = row.timeout_seconds || 10;
  formState.body_text = JSON.stringify(row.body || {}, null, 2);
  formState.query_text = JSON.stringify(row.query || {}, null, 2);
  headerRows.value = normalizeKeyValueRows(row.headers || {});
  pathParamRows.value = normalizeKeyValueRows(row.path_params || {});
  requestParams.value = (row.request_params || []).map((p) => ({ ...p }));
  responseParams.value = (row.response_params || []).map((p) => ({ ...p }));
  drawerVisible.value = true;
}

function openCreateFolderDialog(parentPath = "") {
  folderDialogMode.value = "create";
  folderDialogEditPath.value = "";
  folderDialogParentPath.value = normalizeFolderPath(parentPath);
  folderDialogVisible.value = true;
}

function openEditFolderDialog(folderPath) {
  folderDialogMode.value = "edit";
  folderDialogEditPath.value = normalizeFolderPath(folderPath);
  folderDialogParentPath.value = "";
  folderDialogVisible.value = true;
}

async function handleFolderCreated() {
  await loadApis();
}

function parseJsonObject(text, label) {
  try {
    const parsed = JSON.parse(text || "{}");
    if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
      throw new Error(`${label} 必须是 JSON 对象`);
    }
    return parsed;
  } catch (error) {
    throw new Error(error instanceof Error ? error.message : `${label} 解析失败`);
  }
}

function buildPayload() {
  return {
    name: formState.name.trim(),
    folder_path: formState.folder_path.trim(),
    method: formState.method,
    url: formState.url.trim(),
    description: formState.description.trim(),
    timeout_seconds: Number(formState.timeout_seconds || 10),
    headers: collectKeyValueObject(headerRows.value, "Headers"),
    body: parseJsonObject(formState.body_text, "Body"),
    query: parseJsonObject(formState.query_text, "Query"),
    path_params: collectKeyValueObject(pathParamRows.value, "Path Params"),
    request_params: requestParams.value.filter((p) => p.name.trim()),
    response_params: responseParams.value.filter((p) => p.name.trim()),
  };
}

async function loadApis() {
  loading.value = true;
  try {
    const [apis, folders] = await Promise.all([
      apiGet("/api/apis"),
      apiGet("/api/folders?target=apis"),
    ]);
    rawRows.value = apis;
    declaredFolderPaths.value = folders.folders || [];
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "接口列表加载失败");
  } finally {
    loading.value = false;
  }
}

async function syncFromWorkflows() {
  try {
    await ElMessageBox.confirm(
      "将从当前可见工作流的 HTTP 节点提取 method+URL，补全到接口库（已存在的不会重复创建）。是否继续？",
      "从工作流同步接口",
      {
        type: "info",
        confirmButtonText: "同步",
        cancelButtonText: "取消",
      }
    );
  } catch {
    return;
  }

  loading.value = true;
  try {
    const result = await apiPost("/api/apis/sync-from-workflows", {});
    ElMessage.success(`同步完成：新增 ${result.created || 0} 个，跳过 ${result.skipped || 0} 个，当前共 ${result.total || 0} 个`);
    await loadApis();
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "同步失败");
  } finally {
    loading.value = false;
  }
}

async function submitForm() {
  let payload;
  try {
    payload = buildPayload();
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "表单校验失败");
    return;
  }

  if (!payload.name || !payload.url) {
    ElMessage.warning("名称和 URL 不能为空");
    return;
  }

  saving.value = true;
  try {
    if (drawerMode.value === "edit" && editingId.value) {
      await apiPut(`/api/apis/${editingId.value}`, payload);
      ElMessage.success("接口已更新");
    } else {
      await apiPost("/api/apis", payload);
      ElMessage.success("接口已创建");
    }
    drawerVisible.value = false;
    await loadApis();
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : "保存失败");
  } finally {
    saving.value = false;
  }
}

async function handleDelete(row) {
  try {
    await ElMessageBox.confirm(`确认删除接口「${row.name}」吗？`, "删除确认", {
      type: "warning",
      confirmButtonText: "删除",
      cancelButtonText: "取消",
    });
    await apiDelete(`/api/apis/${row.id}`);
    ElMessage.success("接口已删除");
    await loadApis();
  } catch (error) {
    if (error !== "cancel") {
      ElMessage.error(error instanceof Error ? error.message : "删除失败");
    }
  }
}

onMounted(() => {
  loadApis();
});
</script>

<template>
  <div class="page-stack">
    <el-card class="panel-card" shadow="never">
      <template #header>
        <div class="panel-card__header">
          <div>
            <strong>接口管理</strong>
          </div>
          <div class="toolbar-actions">
            <el-button :icon="Refresh" @click="loadApis">刷新</el-button>
            <el-button :icon="FolderAdd" @click="openCreateFolderDialog()">新建目录</el-button>
            <el-button @click="syncFromWorkflows">从工作流同步</el-button>
            <el-button type="primary" :icon="Plus" @click="openCreateDrawer">新建接口</el-button>
          </div>
        </div>
      </template>

      <div class="api-toolbar">
        <el-input
          v-model="searchKeyword"
          placeholder="搜索名称、目录、方法、URL、创建人"
          clearable
          class="api-toolbar__search"
        >
          <template #prefix>
            <el-icon><Search /></el-icon>
          </template>
        </el-input>
        <div class="toolbar-actions">
          <el-tag type="info" effect="plain">目录 {{ folderCount }}</el-tag>
          <el-tag type="success" effect="plain">接口 {{ visibleRows.length }}</el-tag>
        </div>
      </div>

      <el-table
        :data="treeRows"
        row-key="rowKey"
        default-expand-all
        v-loading="loading"
        class="api-table"
        :tree-props="{ children: 'children' }"
        :row-class-name="({ row }) => (row.nodeType === 'folder' ? 'table-row-folder' : 'table-row-api')"
      >
        <el-table-column label="目录 / 接口" min-width="360">
          <template #default="{ row }">
            <div v-if="row.nodeType === 'folder'" class="tree-title tree-title--folder">
              <el-icon><FolderOpened /></el-icon>
              <strong>{{ row.name || "/" }}</strong>
              <el-tag v-if="row.isEmptyFolder" size="small" type="info" effect="plain">空目录</el-tag>
            </div>
            <div v-else class="tree-title">
              <span class="tree-title__api-icon">
                <el-icon><Link /></el-icon>
              </span>
              <strong>{{ row.name }}</strong>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="Method" width="110">
          <template #default="{ row }">
            <template v-if="row.nodeType === 'api'">
              <el-tag :type="row.method === 'GET' ? 'success' : 'primary'" effect="light">{{ row.method }}</el-tag>
            </template>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="URL" min-width="300">
          <template #default="{ row }">
            <span class="table-url">{{ row.nodeType === "api" ? row.url : row.folder_path || "/" }}</span>
          </template>
        </el-table-column>
        <el-table-column label="超时(s)" width="110">
          <template #default="{ row }">
            <span>{{ row.nodeType === "api" ? row.timeout_seconds : "-" }}</span>
          </template>
        </el-table-column>
        <el-table-column label="创建人" min-width="140">
          <template #default="{ row }">
            <span>{{ row.nodeType === "folder" ? "-" : row.creator_name }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="360" fixed="right">
          <template #default="{ row }">
            <div v-if="row.nodeType === 'folder'" class="row-actions">
              <el-button text :icon="Setting" @click="openEditFolderDialog(row.folder_path)">编辑</el-button>
              <el-button text :icon="FolderAdd" @click="openCreateFolderDialog(row.folder_path)">子目录</el-button>
              <el-button text :icon="Plus" @click="openCreateDrawerFromFolder(row.folder_path)">新建接口</el-button>
            </div>
            <div v-else class="row-actions">
              <el-button text :icon="Edit" @click="openEditDrawer(row)">编辑</el-button>
              <el-button text type="danger" :icon="Delete" @click="handleDelete(row)">删除</el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <el-drawer
      v-model="drawerVisible"
      :title="drawerMode === 'edit' ? '编辑接口' : '新建接口'"
      size="760px"
      destroy-on-close
    >
      <div class="api-form">
        <el-form label-position="top">
          <el-row :gutter="16">
            <el-col :span="12">
              <el-form-item label="接口名称">
                <el-input v-model="formState.name" placeholder="登录接口" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="目录">
                <el-input v-model="formState.folder_path" placeholder="auth/login" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="16">
            <el-col :span="8">
              <el-form-item label="Method">
                <el-select v-model="formState.method" class="full-width">
                  <el-option v-for="item in methodOptions" :key="item" :label="item" :value="item" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="16">
              <el-form-item label="URL">
                <el-input v-model="formState.url" placeholder="/api/example" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-form-item label="接口说明">
            <el-input
              v-model="formState.description"
              type="textarea"
              :rows="3"
              placeholder="描述接口用途、注意事项等…"
            />
          </el-form-item>

          <el-form-item label="超时（秒）">
            <el-input-number v-model="formState.timeout_seconds" :min="1" :step="1" class="full-width" />
          </el-form-item>

          <el-divider content-position="left">请求参数</el-divider>

          <RequestParamsTabs
            v-model:header-rows="headerRows"
            v-model:body-text="formState.body_text"
            v-model:query-text="formState.query_text"
            v-model:path-param-rows="pathParamRows"
          />

          <el-divider content-position="left">入参结构</el-divider>

          <div class="param-struct-section">
            <el-table :data="requestParams" border size="small" class="param-struct-table">
              <el-table-column label="字段名" min-width="120">
                <template #default="{ row }">
                  <el-input v-model="row.name" placeholder="字段名" size="small" />
                </template>
              </el-table-column>
              <el-table-column label="类型" width="120">
                <template #default="{ row }">
                  <el-select v-model="row.type" size="small">
                    <el-option v-for="t in paramTypeOptions" :key="t" :label="t" :value="t" />
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column label="必填" width="70" align="center">
                <template #default="{ row }">
                  <el-checkbox v-model="row.required" />
                </template>
              </el-table-column>
              <el-table-column label="字段说明" min-width="160">
                <template #default="{ row }">
                  <el-input v-model="row.description" placeholder="字段说明" size="small" />
                </template>
              </el-table-column>
              <el-table-column label="" width="60" align="center">
                <template #default="{ $index }">
                  <el-button text type="danger" size="small" @click="removeRequestParam($index)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>
            <el-button size="small" @click="addRequestParam" style="margin-top: 8px">+ 添加入参字段</el-button>
          </div>

          <el-divider content-position="left">出参结构</el-divider>

          <div class="param-struct-section">
            <el-table :data="responseParams" border size="small" class="param-struct-table">
              <el-table-column label="字段名" min-width="120">
                <template #default="{ row }">
                  <el-input v-model="row.name" placeholder="字段名" size="small" />
                </template>
              </el-table-column>
              <el-table-column label="类型" width="120">
                <template #default="{ row }">
                  <el-select v-model="row.type" size="small">
                    <el-option v-for="t in paramTypeOptions" :key="t" :label="t" :value="t" />
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column label="必填" width="70" align="center">
                <template #default="{ row }">
                  <el-checkbox v-model="row.required" />
                </template>
              </el-table-column>
              <el-table-column label="字段说明" min-width="160">
                <template #default="{ row }">
                  <el-input v-model="row.description" placeholder="字段说明" size="small" />
                </template>
              </el-table-column>
              <el-table-column label="" width="60" align="center">
                <template #default="{ $index }">
                  <el-button text type="danger" size="small" @click="removeResponseParam($index)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>
            <el-button size="small" @click="addResponseParam" style="margin-top: 8px">+ 添加出参字段</el-button>
          </div>
        </el-form>
      </div>

      <template #footer>
        <div class="drawer-footer">
          <el-button @click="drawerVisible = false">取消</el-button>
          <el-button type="primary" :loading="saving" @click="submitForm">保存</el-button>
        </div>
      </template>
    </el-drawer>

    <FolderCreateDialog
      v-model="folderDialogVisible"
      target="apis"
      :mode="folderDialogMode"
      :edit-path="folderDialogEditPath"
      :parent-path="folderDialogParentPath"
      :folder-options="folderOptions"
      @success="handleFolderCreated"
    />
  </div>
</template>
