import { invoke } from "@tauri-apps/api/core";

export interface Project {
  /** workspace.id（也是旧 projects.id） */
  id: string;
  /** profile.id，跨空间共享的项目档案 */
  profile_id?: string;
  /** 同 id，前端可用于语义区分 */
  workspace_id?: string;
  /** 关联的 git_repos.id */
  repo_id?: string;
  name: string;
  description?: string;
  type?: string;
  // ── profile 级（项目档案，跨空间共享）────────────────────────
  status?: string;
  priority?: string;
  tech_stack?: string;
  tags?: string;
  repo_url?: string;
  upstream_url?: string;
  default_branch?: string;
  staging_url?: string;
  prod_url?: string;
  server_note?: string;
  // ── workspace 级（每空间独立）───────────────────────────────
  space_id?: string;
  wsl_path?: string;
  win_path?: string;
  platform?: "windows" | "wsl";
  recent_focus?: string;
  startup_commands?: string;
  last_push_at?: string;
  updated_at?: string;
}

export interface ProjectDetail extends Project {
  recent_activities: ActivityLog[];
}

export interface ActivityLog {
  id: number;
  project_id: string;
  summary: string;
  created_at?: string;
}

export interface ProductGroup {
  id: string;
  name: string;
  description?: string;
  space_id?: string;
  sort_order: number;
}

export interface ProjectGroupMap {
  project_id: string;
  group_id: string;
  role?: string;
}

export interface EditorCandidate {
  name: string;
  cmd: string;
  path: string | null;
  found: boolean;
}

// ── Projects ──────────────────────────────────────────────────────────────────

export const getProjects = (status?: string, spaceId?: string) =>
  invoke<Project[]>("get_projects", { status, spaceId });

export const getProject = (id: string) =>
  invoke<ProjectDetail>("get_project", { id });

export const createProject = (input: Omit<Project, "updated_at" | "workspace_id">) =>
  invoke<void>("create_project", { input });

export const updateProject = (id: string, input: Partial<Omit<Project, "id" | "updated_at">>) =>
  invoke<void>("update_project", { id, input });

export const updateProjectTags = (id: string, tags: string) =>
  invoke<void>("update_project_tags", { id, tags });

export const deleteProject = (id: string, deleteLocal?: boolean) =>
  invoke<void>("delete_project", { id, deleteLocal });

export interface SubFolder { name: string; path: string }

export const scanSubfolders = (dir: string) =>
  invoke<SubFolder[]>("scan_subfolders", { dir });

export interface BatchProjectInput {
  id: string; name: string;
  win_path?: string; wsl_path?: string;
  status: string; priority: string;
  space_id?: string; platform?: string;
}
export const batchCreateProjects = (items: BatchProjectInput[]) =>
  invoke<string[]>("batch_create_projects", { items });

// ── Activity ──────────────────────────────────────────────────────────────────

export const getActivity = (projectId: string, limit?: number) =>
  invoke<ActivityLog[]>("get_activity", { projectId, limit });

export const addActivity = (projectId: string, summary: string) =>
  invoke<void>("add_activity", { projectId, summary });

// ── Groups ────────────────────────────────────────────────────────────────────

export const getGroups = (spaceId?: string) => invoke<ProductGroup[]>("get_groups", { spaceId });

export const createGroup = (input: { id?: string; name: string; description?: string; space_id?: string }) =>
  invoke<void>("create_group", { input });

export const updateGroup = (id: string, input: { name: string; description?: string }) =>
  invoke<void>("update_group", { id, input });

export const deleteGroup = (id: string) => invoke<void>("delete_group", { id });

/** 按 ids 数组顺序批量写入 sort_order */
export const reorderGroups = (ids: string[]) => invoke<void>("reorder_groups", { ids });

export const getGroupMaps = () => invoke<ProjectGroupMap[]>("get_group_maps");

export const addGroupMember = (projectId: string, groupId: string, role?: string) =>
  invoke<string | null>("add_group_member", { projectId, groupId, role });

export const removeGroupMember = (projectId: string, groupId: string) =>
  invoke<void>("remove_group_member", { projectId, groupId });

// ── Settings ──────────────────────────────────────────────────────────────────

export const getSettings = (spaceId?: string) =>
  invoke<Record<string, string>>("get_settings", { spaceId });

export const updateSettings = (settings: Record<string, string>, spaceId?: string) =>
  invoke<void>("update_settings", { settings, spaceId });

export const detectEditors = () => invoke<EditorCandidate[]>("detect_editors");

export const searchEditorPath = (cmd: string) =>
  invoke<string | null>("search_editor_path", { cmd });

export interface McpHealthResult {
  ok: boolean;
  port: number;
  latency_ms?: number;
  error?: string;
}

export const checkMcpHealth = () => invoke<McpHealthResult>("check_mcp_health");

export interface HealthItem {
  id: string;
  name: string;
  status: "ok" | "warn" | "error" | "skip";
  detail?: string;
}

export interface DormantProject {
  id: string;
  name: string;
  days_since_push: number;
}

export interface OrphanedProject {
  id: string;
  name: string;
}

export interface QualityMetrics {
  dormant_projects: DormantProject[];
  orphaned_projects: OrphanedProject[];
  groups_with_inject_warn: string[];
  projects_without_path: number;
}

export interface HealthReport {
  checked_at: string;
  items: HealthItem[];
  quality: QualityMetrics;
}

export const runHealthCheck = () => invoke<HealthReport>("run_health_check");

// ── Project Tools ─────────────────────────────────────────────────────────────

export interface ProjectTool {
  id: string;
  project_id: string;
  name: string;
  icon: string;
  exe_path: string;
  args: string | null;
  sort_order: number;
}

export interface ProjectToolInput {
  name: string;
  icon: string;
  exe_path: string;
  args?: string;
  sort_order?: number;
}

export const getProjectTools = (projectId: string) =>
  invoke<ProjectTool[]>("get_project_tools", { projectId });

export const addProjectTool = (projectId: string, input: ProjectToolInput) =>
  invoke<string>("add_project_tool", { projectId, input });

export const updateProjectTool = (id: string, input: ProjectToolInput) =>
  invoke<void>("update_project_tool", { id, input });

export const removeProjectTool = (id: string) =>
  invoke<void>("remove_project_tool", { id });

export const launchTool = (exePath: string, args?: string) =>
  invoke<void>("launch_tool", { exePath, args });

// ── Global Quick Launch ───────────────────────────────────────────────────────

export const getGlobalTools = () =>
  invoke<ProjectTool[]>("get_global_tools");

export const addGlobalTool = (input: ProjectToolInput) =>
  invoke<string>("add_global_tool", { input });

export const updateGlobalTool = (id: string, input: ProjectToolInput) =>
  invoke<void>("update_global_tool", { id, input });

export const removeGlobalTool = (id: string) =>
  invoke<void>("remove_global_tool", { id });

// ── Dev Tools ─────────────────────────────────────────────────────────────────

export interface ScannedTool {
  id: string;
  name: string;
  category: string;
  cmd: string;
  path: string | null;
  version: string | null;
  found: boolean;
}

export type DevEnv = "windows" | "wsl";

export interface DevToolRecord {
  id: string;
  name: string;
  category: string;
  cmd: string | null;
  path: string | null;
  version: string | null;
  note: string | null;
  env: DevEnv;
  space_id?: string | null;
}

export interface SaveDevToolInput {
  id: string;
  name: string;
  category: string;
  cmd?: string;
  path?: string;
  version?: string;
  note?: string;
  env?: DevEnv;
  space_id?: string;
}

export const scanDevTools = () =>
  invoke<ScannedTool[]>("scan_dev_tools");

export const scanWslDevTools = () =>
  invoke<ScannedTool[]>("scan_wsl_dev_tools");

export const getDevTools = (env: DevEnv, spaceId?: string) =>
  invoke<DevToolRecord[]>("get_dev_tools", { env, spaceId });

export const saveDevTools = (tools: SaveDevToolInput[]) =>
  invoke<void>("save_dev_tools", { tools });

export const deleteDevTool = (id: string) =>
  invoke<void>("delete_dev_tool", { id });

export const upsertDevTool = (tool: SaveDevToolInput) =>
  invoke<void>("upsert_dev_tool", { tool });

// ── Project Env Scan ──────────────────────────────────────────────────────────

export interface EnvToolItem {
  id: string;
  project_id: string;
  layer: number;
  name: string;
  source?: string;
  version?: string;
  note?: string;
}

export interface SaveEnvToolInput {
  id: string;
  layer: number;
  name: string;
  source?: string;
  version?: string;
  note?: string;
}

export const scanProjectEnv = (projectId: string, env: 'win' | 'wsl') =>
  invoke<EnvToolItem[]>('scan_project_env', { projectId, env });

export const getProjectEnvTools = (projectId: string) =>
  invoke<EnvToolItem[]>('get_project_env_tools', { projectId });

export const saveProjectEnvTools = (projectId: string, items: SaveEnvToolInput[]) =>
  invoke<void>('save_project_env_tools', { projectId, items });

// ── Shell ─────────────────────────────────────────────────────────────────────

export const openEditor = (projectId: string, env: "wsl" | "win", editorPath: string) =>
  invoke<string>("open_editor", { projectId, env, editorPath });

export const openTerminal = (projectId: string, env: "wsl" | "win") =>
  invoke<string>("open_terminal", { projectId, env });

// ── Spaces ────────────────────────────────────────────────────────────────────

export interface Space {
  id: string;
  name: string;
  is_current: boolean;
  created_at?: string;
}

export interface DeployCommand {
  id: string;
  project_id: string;
  name: string;
  command: string;
  run_in: "windows" | "wsl";
}

export const getSpaces = () =>
  invoke<Space[]>("get_spaces");

export const createSpace = (name: string) =>
  invoke<Space>("create_space", { name });

export const updateSpace = (id: string, name: string) =>
  invoke<void>("update_space", { id, name });

export const deleteSpace = (id: string) =>
  invoke<void>("delete_space", { id });

export const setCurrentSpace = (id: string) =>
  invoke<void>("set_current_space", { id });

export const getDeployCommands = (projectId: string) =>
  invoke<DeployCommand[]>("get_deploy_commands", { projectId });

export const addDeployCommand = (
  projectId: string,
  name: string,
  command: string,
  runIn: "windows" | "wsl"
) => invoke<DeployCommand>("add_deploy_command", { projectId, name, command, runIn });

export const removeDeployCommand = (id: string) =>
  invoke<void>("remove_deploy_command", { id });

export const executeDeploy = (command: string, runIn: "windows" | "wsl", cwd?: string) =>
  invoke<string>("execute_deploy", { command, runIn, cwd });

// ── Git 操作 ──────────────────────────────────────────────────────────────────

export interface GitStatus {
  branch: string;
  ahead: number;
  behind: number;
  has_changes: boolean;
  last_commit_msg?: string;
  last_commit_time?: string;
}

export const gitClone = (repoUrl: string, localPath: string, upstreamUrl?: string) =>
  invoke<void>("git_clone", { repoUrl, localPath, upstreamUrl });

export const gitStatus = (localPath: string) =>
  invoke<GitStatus>("git_status", { localPath });

export const gitFetch = (localPath: string) =>
  invoke<void>("git_fetch", { localPath });

export const gitPull = (localPath: string) =>
  invoke<string>("git_pull", { localPath });

export const gitPush = (localPath: string) =>
  invoke<string>("git_push", { localPath });

export const gitHeadCommit = (localPath: string) =>
  invoke<string | null>("git_head_commit", { localPath });

export const gitUpstreamBehind = (localPath: string, defaultBranch: string) =>
  invoke<number>("git_upstream_behind", { localPath, defaultBranch });

export const gitCreateBranch = (localPath: string, branchName: string) =>
  invoke<void>("git_create_branch", { localPath, branchName });

export const gitListBranches = (localPath: string) =>
  invoke<string[]>("git_list_branches", { localPath });

export const gitCheckoutBranch = (localPath: string, branchName: string) =>
  invoke<void>("git_checkout_branch", { localPath, branchName });

// ── WSL 代理同步 ──────────────────────────────────────────────────────────────

export const getWslIp = () => invoke<string>("get_wsl_ip");

/** 读取 v2rayN 代理端口，写入 WSL /etc/profile.d/v2rayn-proxy.sh */
export const syncWslProxy = (dbPath?: string) =>
  invoke<string>("sync_wsl_proxy", { dbPath });

export interface WslProxyStatus {
  configured: boolean;
  port?: number;
  /** /etc/environment 中记录的 IP 与当前网关不一致（Windows 重启后常见） */
  stale?: boolean;
  configured_ip?: string;
  current_ip?: string;
  /** /etc/bash.bashrc 中的 source 行是否存在（非登录 shell 代理是否生效） */
  bashrc_ok?: boolean;
}
export const getWslProxyStatus = () => invoke<WslProxyStatus>("get_wsl_proxy_status");
export const clearWslProxy = () => invoke<void>("clear_wsl_proxy");
export const testWslProxyIp = () => invoke<string>("test_wsl_proxy_ip");
export const testWinProxyIp = () => invoke<string>("test_win_proxy_ip");

export interface ActiveV2raynNode {
  index_id: string;
  remarks: string;
  address: string;
  port: number;
  config_type: number;
  share_link: string;
}
export const getActiveV2raynNode = (dbPath?: string) =>
  invoke<ActiveV2raynNode>("get_active_v2rayn_node", { dbPath });

// ── v2rayN 节点导入 ───────────────────────────────────────────────────────────

export interface V2raynNode {
  index_id: string;
  config_type: number; // 1=VMess 3=SS 5=VLESS 6=Trojan 7=Hysteria2
  remarks: string;
  address: string;
  port: number;
  id?: string;          // UUID
  security?: string;
  network?: string;
  stream_security?: string;
  flow?: string;
  sni?: string;
  fingerprint?: string;
  public_key?: string;
  short_id?: string;
  spider_x?: string;
  request_host?: string;
  path?: string;
  alter_id?: number;
}

export const CONFIG_TYPE_LABEL: Record<number, string> = {
  1: "VMess",
  3: "Shadowsocks",
  4: "Socks",
  5: "VLESS",
  6: "Trojan",
  7: "Hysteria2",
};

export const scanV2raynNodes = (dbPath?: string) =>
  invoke<V2raynNode[]>("scan_v2rayn_nodes", { dbPath });

export const detectV2raynDbPath = () =>
  invoke<string | null>("detect_v2rayn_db_path");

// ── Git Repos Registry（仓库注册表）──────────────────────────────────────────

export interface GitRepo {
  id: string;
  repo_url: string;
  name: string;
  description?: string;
  default_branch?: string;
  upstream_url?: string;
  staging_url?: string;
  prod_url?: string;
  server_note?: string;
  status?: string;
  priority?: string;
  tech_stack?: string;
  last_synced_at?: string;
  created_at?: string;
}

export interface ImportGitRepoInput {
  id: string;
  repo_url: string;
  name: string;
  description?: string;
  default_branch?: string;
  upstream_url?: string;
  tech_stack?: string;
}

export interface UpdateGitRepoDeployInput {
  staging_url?: string;
  prod_url?: string;
  server_note?: string;
  upstream_url?: string;
  tech_stack?: string;
  status?: string;
  priority?: string;
}

export interface MountRepoInput {
  workspace_id: string;
  repo_id: string;
  space_id?: string;
  win_path?: string;
  wsl_path?: string;
  platform?: string;
}

export const getGitRepos = () =>
  invoke<GitRepo[]>("get_git_repos");

export const importGitRepos = (repos: ImportGitRepoInput[]) =>
  invoke<string[]>("import_git_repos", { repos });

export const updateGitRepoDeploy = (id: string, input: UpdateGitRepoDeployInput) =>
  invoke<void>("update_git_repo_deploy", { id, input });

export const mountRepo = (input: MountRepoInput) =>
  invoke<void>("mount_repo", { input });

export const deleteGitRepo = (id: string) =>
  invoke<void>("delete_git_repo", { id });

// ── 本地 Git 工具（扫描 / init / remote / WSL 路径）───────────────────────────

export interface ChangedFile {
  status: string; // "M" | "A" | "D" | "?" | "R"
  path: string;
}

export interface GitRemoteInfo {
  name: string;
  url: string;
}

export interface GitScanResult {
  has_git: boolean;
  has_commits: boolean;
  branch: string;
  has_changes: boolean;
  changed_files: ChangedFile[];
  remotes: GitRemoteInfo[];
  has_gitignore: boolean;
  suspicious_files: string[];
  suggested_templates: string[];
}

export const scanLocalGit = (path: string) =>
  invoke<GitScanResult>("scan_local_git", { path });

export const gitInitAndCommit = (path: string, message: string) =>
  invoke<void>("git_init_and_commit", { path, message });

export const gitRemoteSet = (path: string, url: string) =>
  invoke<void>("git_remote_set", { path, url });

/** 将 Linux WSL 路径转换为 Windows UNC 路径（\\wsl.localhost\distro\...） */
export const resolveWslPath = (path: string) =>
  invoke<string>("resolve_wsl_path", { path });

/** 列出已安装的 WSL 发行版 */
export const getWslDistros = () =>
  invoke<string[]>("get_wsl_distros");

// ── 项目模板 ──────────────────────────────────────────────────────────────────

export interface TemplateFile {
  id: string;
  template_id: string;
  path: string;
  content: string;
}

export interface TemplateVariant {
  label: string;
  description: string;
  initCommands: string;
}

export interface ProjectTemplate {
  id: string;
  name: string;
  description?: string;
  platform: string; // "win" | "wsl" | "both"
  techStack?: string;
  initCommands?: string;
  isBuiltin: boolean;
  createdAt?: string;
  files: TemplateFile[];
  /** JSON 字符串，解析后为 TemplateVariant[]，存在时显示下拉选择 */
  variants?: string;
}

export interface SaveTemplateInput {
  id?: string;
  name: string;
  description?: string;
  platform: string;
  techStack?: string;
  initCommands?: string;
  files: { path: string; content: string }[];
}

export interface CreateProjectResult {
  projectId: string;
  logs: string[];
}

export const listTemplates = () =>
  invoke<ProjectTemplate[]>("list_templates");

export const getTemplate = (id: string) =>
  invoke<ProjectTemplate>("get_template", { id });

export const saveTemplate = (input: SaveTemplateInput) =>
  invoke<string>("save_template", { input });

export const deleteTemplate = (id: string) =>
  invoke<void>("delete_template", { id });

export const createProjectFromTemplate = (
  templateId: string,
  parentPath: string,
  projectName: string,
  platform: string,
  spaceId?: string,
  variantInitCommands?: string,
) =>
  invoke<CreateProjectResult>("create_project_from_template", {
    templateId,
    parentPath,
    projectName,
    platform,
    spaceId,
    variantInitCommands,
  });

export const registerAndLinkRepo = (
  projectId: string,
  repoUrl: string,
  name: string,
  description?: string,
  defaultBranch?: string,
) => invoke<void>("register_and_link_repo", { projectId, repoUrl, name, description, defaultBranch });

// ── 项目标签 ──────────────────────────────────────────────────────────────────

export interface ProjectTag {
  id: string;
  name: string;
  color: string;
}

export interface ProfileTagMap {
  profile_id: string;
  tag_id: string;
}

export const getTags = () => invoke<ProjectTag[]>("get_tags");
export const createTag = (name: string, color: string) => invoke<string>("create_tag", { name, color });
export const updateTag = (id: string, name: string, color: string) => invoke<void>("update_tag", { id, name, color });
export const deleteTag = (id: string) => invoke<void>("delete_tag", { id });
export const getProjectTags = (workspaceId: string) => invoke<ProjectTag[]>("get_project_tags", { workspaceId });
export const setProjectTags = (workspaceId: string, tagIds: string[]) => invoke<void>("set_project_tags", { workspaceId, tagIds });
export const getAllProjectTagMaps = () => invoke<ProfileTagMap[]>("get_all_project_tag_maps");

// ── CI/CD 配置 ────────────────────────────────────────────────────────────────

export interface CicdConfig {
  id: string;
  project_id: string;
  /** 'web_ssh' | 'tauri_oss' */
  config_type: string;
  trigger_branch: string;
  build_command?: string;
  node_version?: string;
  // web_ssh 专属
  server_host?: string;
  server_user?: string;
  deploy_path?: string;
  start_command?: string;
  // tauri_oss 专属
  oss_endpoint?: string;
  created_at?: string;
}

export interface WorkflowResult {
  content: string;
  path: string;
  secrets: string[];
}

export const getCicdConfig = (projectId: string) =>
  invoke<CicdConfig | null>("get_cicd_config", { projectId });

export const saveCicdConfig = (input: CicdConfig) =>
  invoke<CicdConfig>("save_cicd_config", { input });

/** 生成 workflow 文件写入磁盘，projectPath 必须是 Windows 可访问路径 */
export const generateWorkflow = (projectId: string, projectPath: string) =>
  invoke<WorkflowResult>("generate_workflow", { projectId, projectPath });

/** 根据节点数据构造 share link（前端完成，避免 Rust 侧 URL 编码依赖） */
export function buildShareLink(node: V2raynNode): string {
  const remarks = encodeURIComponent(node.remarks);

  if (node.config_type === 5) {
    // VLESS
    const uuid = node.id ?? "";
    const params = new URLSearchParams();
    params.set("encryption", "none");
    params.set("security", node.stream_security ?? "none");
    if (node.network) params.set("type", node.network);
    if (node.stream_security === "reality" || node.stream_security === "tls") {
      if (node.sni) params.set("sni", node.sni);
      if (node.fingerprint) params.set("fp", node.fingerprint);
    }
    if (node.stream_security === "reality") {
      if (node.public_key) params.set("pbk", node.public_key);
      if (node.short_id) params.set("sid", node.short_id);
      if (node.spider_x) params.set("spx", node.spider_x);
    }
    if (node.flow) params.set("flow", node.flow);
    if (node.request_host) params.set("host", node.request_host);
    if (node.path) params.set("path", node.path);
    return `vless://${uuid}@${node.address}:${node.port}?${params.toString()}#${remarks}`;
  }

  if (node.config_type === 6) {
    // Trojan
    const params = new URLSearchParams();
    params.set("security", node.stream_security ?? "tls");
    if (node.sni) params.set("sni", node.sni);
    if (node.fingerprint) params.set("fp", node.fingerprint);
    if (node.network) params.set("type", node.network);
    return `trojan://${node.id ?? ""}@${node.address}:${node.port}?${params.toString()}#${remarks}`;
  }

  if (node.config_type === 1) {
    // VMess — base64 JSON 格式
    const obj = {
      v: "2", ps: node.remarks, add: node.address, port: String(node.port),
      id: node.id ?? "", aid: String(node.alter_id ?? 0),
      scy: node.security ?? "auto", net: node.network ?? "tcp",
      type: "none", host: node.request_host ?? "", path: node.path ?? "",
      tls: node.stream_security ?? "", sni: node.sni ?? "", fp: node.fingerprint ?? "",
    };
    return `vmess://${btoa(JSON.stringify(obj))}`;
  }

  return "";
}

// ── Blueprint ──────────────────────────────────────────────────────────────

export interface BlueprintTask {
  title: string;
  status: string;
  complexity?: string;
  files?: string;
  depends?: string;
  acceptance?: string;
  notes?: string;
  blocked_reason?: string;
  locked?: boolean;
}

export interface BlueprintModule {
  id: string;
  name: string;
  area: string;
  status: string;
  progress: number;
  position: number[];
  description?: string;
  decisions: string[];
  tasks: BlueprintTask[];
}

export interface BlueprintEdge {
  from: string;
  to: string;
  edge_type: string;
}

export interface BlueprintArea {
  id: string;
  name: string;
  color?: string;
}

export interface BlueprintStats {
  total_modules: number;
  done: number;
  in_progress: number;
  planned: number;
  concept: number;
  blocked: number;
  total_tasks: number;
  tasks_done: number;
  tasks_blocked: number;
  tasks_locked: number;
  dispatchable: number;
}

export interface BlueprintData {
  manifest: {
    version: number;
    name: string;
    description?: string;
    updated?: string;
    /** 当前迭代号，默认 1，重构已完成模块时递增 */
    iteration?: number;
    areas: BlueprintArea[];
    modules: BlueprintModule[];
    edges: BlueprintEdge[];
  };
  stats: BlueprintStats;
}

export const getBlueprint = (projectPath: string) =>
  invoke<BlueprintData | null>("get_blueprint", { projectPath });

export const generateBlueprintPrompt = (projectPath: string, promptType: "init" | "sync") =>
  invoke<string>("generate_blueprint_prompt", { projectPath, promptType });

export interface BlueprintStatus {
  status: "none" | "rules_outdated" | "content_stale" | "synced";
  conventions_version?: string;
  claude_md_managed: boolean;
  claude_md_version?: string;
  manifest_updated?: string;
  master_version: string;
}

export interface SyncResult {
  success: boolean;
  conventions_written: boolean;
  claude_md_action: string;
  agents_md_action: string;
  message: string;
}

export const getBlueprintStatus = (projectPath: string) =>
  invoke<BlueprintStatus>("get_blueprint_status", { projectPath });

export const syncBlueprintRules = (projectPath: string) =>
  invoke<SyncResult>("sync_blueprint_rules", { projectPath });

export interface UserConventionsStatus {
  source: "builtin" | "user";
  version: string;
  content: string;
  builtin_version: string;
  outdated_from_builtin: boolean;
}

export interface SaveConventionsResult {
  version: string;
  synced_count: number;
}

export const getUserConventionsStatus = () =>
  invoke<UserConventionsStatus>("get_user_conventions_status");

export const saveUserConventions = (content: string) =>
  invoke<SaveConventionsResult>("save_user_conventions", { content });

export const resetConventionsToBuiltin = () =>
  invoke<SaveConventionsResult>("reset_conventions_to_builtin");

export interface FlywheelCohort {
  conventions_version: string;
  project_count: number;
  /** 可派发率：dispatched(可派发数) / total tasks（最新快照均值） */
  dispatchable_rate: number;
  /** 任务完成率：done / total tasks（最新快照均值，反映整体进度） */
  completion_rate: number;
  /** 飞轮持续率：30天内有快照的项目比例 */
  continuity_rate: number;
  /** 阻塞密度：blocked / total tasks（最新快照均值） */
  blocked_density: number;
}

export interface BlockedReasonCount {
  reason: string;
  count: number;
}

export interface StalledProject {
  name: string;
  /** UTC 日期字符串 "YYYY-MM-DD"，未知时为 "unknown" */
  last_active: string;
}

export interface IterationJump {
  project: string;
  from_iteration: number;
  to_iteration: number;
  /** 跳变前最后一条快照的任务完成率 */
  rate_before: number;
  /** 跳变后第一条快照的任务完成率 */
  rate_after: number;
}

export interface ProjectNoteEntry {
  project_name: string;
  content: string;
  created_at: string;
}

export interface ExecutionQuality {
  complexity_dist: Record<string, number>;
  total_rework_count: number;
  avg_rounds_m: number | null;
}

export interface FlywheelStats {
  cohorts: FlywheelCohort[];
  top_blocked_reasons: BlockedReasonCount[];
  /** 飞轮停转项目（60天无快照） */
  stalled_projects: StalledProject[];
  /** AI文档休眠项目（90天无快照） */
  ai_doc_stale_projects: StalledProject[];
  /** 迭代跳变记录（iteration 递增，说明发生了主动重构） */
  iteration_jumps: IterationJump[];
  /** 停滞模块（in_progress 但无可推进任务，格式 "project/module_id"） */
  stalled_modules: string[];
  total_projects_scanned: number;
  projects_with_data: number;
  /** 跨项目复盘笔记（最近 50 条） */
  project_notes: ProjectNoteEntry[];
  /** 跨项目执行质量指标（阶段二扩展） */
  execution_quality: ExecutionQuality;
}

export const getFlywheelStats = (projectPaths: string[]) =>
  invoke<FlywheelStats>("get_flywheel_stats", { projectPaths });

export const generateMuhePrompt = (stats: FlywheelStats) =>
  invoke<string>("generate_muhe_prompt", { stats });

export interface ArchiveResult {
  archived_files: string[];
  archive_dir: string;
}

export const archiveProjectDocs = (projectPath: string) =>
  invoke<ArchiveResult>("archive_project_docs", { projectPath });

// ── Canvas State ───────────────────────────────────────────────────────────────
export const getCanvasState = (groupId: string) =>
  invoke<string | null>("get_canvas_state", { groupId });

export const saveCanvasState = (groupId: string, data: string) =>
  invoke<void>("save_canvas_state", { groupId, data });

// ── Mentor ────────────────────────────────────────────────────────────────────

export interface ProjectHealth {
  path_valid: boolean;
  has_git: boolean;
  last_commit?: string;
  tech_stack?: string;
}

export interface BlueprintSummary {
  module_count: number;
  done_count: number;
  in_progress: number;
  planned: number;
  total_tasks: number;
  done_tasks: number;
  dispatchable: number;
}

export interface RuntimeLogEntry {
  ts: string;
  category: string;
  level: string;
  message: string;
}

export interface ReviewCoverage {
  completed_ml_tasks: number;
  note_count: number;
}

export interface MentorContext {
  project_id: string;
  project_name: string;
  health: ProjectHealth;
  blueprint_summary?: BlueprintSummary;
  recent_errors: RuntimeLogEntry[];
  review_coverage?: ReviewCoverage;
  mentor_markdown: string;
}

export const getMentorContext = (projectId: string) =>
  invoke<MentorContext>("get_mentor_context", { projectId });

export const getGroupMentorReport = (groupId: string) =>
  invoke<string>("get_group_mentor_report", { groupId });

export interface StartupAlert {
  project_name: string;
  alert_type: string;
  detail: string;
}

export const getStartupAlerts = () =>
  invoke<StartupAlert[]>("get_startup_alerts");

export interface ProjectNote {
  id: number;
  project_id: string;
  source: string;
  content: string;
  created_at: string;
}

export const getProjectNotes = (projectId: string) =>
  invoke<ProjectNote[]>("get_project_notes", { projectId });

export const addProjectNote = (projectId: string, content: string, source: string = "manual") =>
  invoke<void>("add_project_note", { projectId, content, source });

// ── 用户项目个人备忘 ──────────────────────────────────────────────────────────

export interface UserTodo {
  id: number;
  project_id: string;
  content: string;
  done: boolean;
  sort_order: number;
  created_at: string;
}

export const getUserTodos = (projectId: string) =>
  invoke<UserTodo[]>("get_user_todos", { projectId });

export const addUserTodo = (projectId: string, content: string) =>
  invoke<UserTodo>("add_user_todo", { projectId, content });

export const toggleUserTodo = (id: number) =>
  invoke<void>("toggle_user_todo", { id });

export const deleteUserTodo = (id: number) =>
  invoke<void>("delete_user_todo", { id });

// ── Servers ──────────────────────────────────────────────────────────────────

export interface QuickLink {
  label: string;
  url: string;
}

export interface Server {
  id: string;
  name: string;
  server_host: string;
  server_port?: string;
  username?: string;
  password?: string;
  ssh_key_path?: string;
  quick_links?: string; // JSON string of QuickLink[]
  notes?: string;
  created_at?: string;
  updated_at?: string;
}

export interface SaveServerInput {
  name: string;
  server_host: string;
  server_port?: string;
  username?: string;
  password?: string;
  ssh_key_path?: string;
  quick_links?: string;
  notes?: string;
}

export interface ProjectServerLink {
  project_id: string;
  server_id: string;
  role?: string;
  deploy_type?: "bare" | "docker";
  deploy_path?: string;
  container_name?: string;
  start_command?: string;
  notes?: string;
  server_name?: string;
  server_host?: string;
  server_port?: string;
  username?: string;
  password?: string;
  ssh_key_path?: string;
  quick_links?: string;
}

export interface LinkServerInput {
  role?: string;
  deploy_type?: string;
  deploy_path?: string;
  container_name?: string;
  start_command?: string;
  notes?: string;
}

export const getServers = () =>
  invoke<Server[]>("get_servers");

export const addServer = (input: SaveServerInput) =>
  invoke<Server>("add_server", { input });

export const editServer = (id: string, input: SaveServerInput) =>
  invoke<Server>("edit_server", { id, input });

export const deleteServer = (id: string) =>
  invoke<void>("delete_server", { id });

export const linkServer = (projectId: string, serverId: string, input: LinkServerInput) =>
  invoke<void>("link_server", { projectId, serverId, input });

export const unlinkServer = (projectId: string, serverId: string) =>
  invoke<void>("unlink_server", { projectId, serverId });

export const getProjectServerLinks = (projectId: string) =>
  invoke<ProjectServerLink[]>("get_project_server_links", { projectId });

export const getServerProjectLinks = (serverId: string) =>
  invoke<ProjectServerLink[]>("get_server_project_links", { serverId });

// ── Server Service Configs（服务连接配置）─────────────────────────────────────

export interface ServiceConfigEntry {
  key: string;
  value: string;
  /** 密码/密钥等敏感值，独立隐藏和复制 */
  secretValue?: string;
}

export interface ServiceConfig {
  id: string;
  server_id: string;
  name: string;
  category?: string;
  scope?: "system" | "docker";
  config_data: string; // JSON of ServiceConfigEntry[]
  sort_order?: number;
  created_at?: string;
  updated_at?: string;
}

export interface SaveServiceConfigInput {
  name: string;
  category?: string;
  scope?: string;
  config_data: string;
  sort_order?: number;
}

export const getServiceConfigs = (serverId: string, scope?: string) =>
  invoke<ServiceConfig[]>("get_service_configs", { serverId, scope });

export const addServiceConfig = (serverId: string, input: SaveServiceConfigInput) =>
  invoke<ServiceConfig>("add_service_config", { serverId, input });

export const editServiceConfig = (id: string, input: SaveServiceConfigInput) =>
  invoke<ServiceConfig>("edit_service_config", { id, input });

export const deleteServiceConfig = (id: string) =>
  invoke<void>("delete_service_config", { id });

// ── Host Apps（宿主机部署应用）────────────────────────────────────────────────

export interface HostApp {
  id: string;
  server_id: string;
  name: string;
  deploy_type: string;
  service_name?: string;
  binary_path?: string;
  config_path?: string;
  log_path?: string;
  port?: string;
  start_cmd?: string;
  stop_cmd?: string;
  restart_cmd?: string;
  status_cmd?: string;
  notes?: string;
  sort_order?: number;
  created_at?: string;
  updated_at?: string;
}

export interface SaveHostAppInput {
  name: string;
  deploy_type: string;
  service_name?: string;
  binary_path?: string;
  config_path?: string;
  log_path?: string;
  port?: string;
  start_cmd?: string;
  stop_cmd?: string;
  restart_cmd?: string;
  status_cmd?: string;
  notes?: string;
  sort_order?: number;
}

export const getHostApps = (serverId: string) =>
  invoke<HostApp[]>("get_host_apps", { serverId });

export const addHostApp = (serverId: string, input: SaveHostAppInput) =>
  invoke<HostApp>("add_host_app", { serverId, input });

export const editHostApp = (id: string, input: SaveHostAppInput) =>
  invoke<HostApp>("edit_host_app", { id, input });

export const deleteHostApp = (id: string) =>
  invoke<void>("delete_host_app", { id });

// ── API Keys ─────────────────────────────────────────────────────────────────

export interface ApiKey {
  id: string;
  name: string;
  provider: string;
  api_key: string;
  base_url?: string;
  model?: string;
  notes?: string;
  created_at?: string;
  updated_at?: string;
}

export interface SaveApiKeyInput {
  name: string;
  provider: string;
  api_key: string;
  base_url?: string;
  model?: string;
  notes?: string;
}

export const getApiKeys = () =>
  invoke<ApiKey[]>("get_api_keys");

export const addApiKey = (input: SaveApiKeyInput) =>
  invoke<ApiKey>("add_api_key", { input });

export const editApiKey = (id: string, input: SaveApiKeyInput) =>
  invoke<ApiKey>("edit_api_key", { id, input });

export const deleteApiKey = (id: string) =>
  invoke<void>("delete_api_key", { id });

// ── SSH Config & VS Code Remote ──────────────────────────────────────────────

export interface SshConfigStatus {
  config_path: string;
  file_exists: boolean;
  has_devmanager_block: boolean;
}

export interface VscodeStatus {
  installed: boolean;
  path?: string;
  remote_ssh_hint: string;
}

export const syncSshConfig = () =>
  invoke<string>("sync_ssh_config");

export const getSshConfigStatus = () =>
  invoke<SshConfigStatus>("get_ssh_config_status");

export const checkVscodeStatus = () =>
  invoke<VscodeStatus>("check_vscode_status");

export const openVscodeRemote = (serverId: string, remotePath?: string) =>
  invoke<string>("open_vscode_remote", { serverId, remotePath });

export const openServerTerminal = (serverId: string) =>
  invoke<string>("open_server_terminal", { serverId });

export interface SshConfigEntry {
  host_alias: string;
  hostname?: string;
  port?: string;
  user?: string;
  identity_file?: string;
}

export const parseSshConfigEntries = () =>
  invoke<SshConfigEntry[]>("parse_ssh_config_entries");

export const importSshConfigEntries = (entries: SshConfigEntry[]) =>
  invoke<number>("import_ssh_config_entries", { entries });

// ── Server Software & Mirrors ────────────────────────────────────────────────

export interface GithubMirror {
  id: string;
  name: string;
  url_prefix: string;
  is_builtin: boolean;
  sort_order: number;
}

export interface ServerNetworkConfig {
  server_id: string;
  github_mirror_id?: string;
  last_tested?: string;
  test_results?: string;
}

export interface MirrorTestResult {
  mirror_id: string;
  reachable: boolean;
  latency_ms?: number;
  error?: string;
}

export interface ServerSoftware {
  id: string;
  name: string;
  description?: string;
  category?: string;
  install_type: "package" | "github";
  install_cmd?: string;
  github_url?: string;
  remote_path?: string;
  post_cmd?: string;
  is_builtin: boolean;
  sort_order: number;
  created_at?: string;
}

export interface SaveSoftwareInput {
  name: string;
  description?: string;
  category?: string;
  install_type: string;
  install_cmd?: string;
  github_url?: string;
  remote_path?: string;
  post_cmd?: string;
}

export interface SaveMirrorInput {
  name: string;
  url_prefix: string;
}

export interface SoftwareCategory {
  id: string;
  name: string;
  color: string;
  sort_order: number;
}

export interface SaveCategoryInput {
  name: string;
  color?: string;
}

export const getSoftwareCategories = () =>
  invoke<SoftwareCategory[]>("get_software_categories");

export const addSoftwareCategory = (input: SaveCategoryInput) =>
  invoke<SoftwareCategory>("add_software_category", { input });

export const updateSoftwareCategory = (id: string, input: SaveCategoryInput) =>
  invoke<void>("update_software_category", { id, input });

export const deleteSoftwareCategory = (id: string) =>
  invoke<void>("delete_software_category", { id });

export const getGithubMirrors = () =>
  invoke<GithubMirror[]>("get_github_mirrors");

export const addGithubMirror = (input: SaveMirrorInput) =>
  invoke<GithubMirror>("add_github_mirror", { input });

export const deleteGithubMirror = (id: string) =>
  invoke<void>("delete_github_mirror", { id });

export const testMirrorLocal = (mirrorId: string) =>
  invoke<MirrorTestResult>("test_mirror_local", { mirrorId });

export const getServerNetworkConfig = (serverId: string) =>
  invoke<ServerNetworkConfig | null>("get_server_network_config", { serverId });

export const setServerMirror = (serverId: string, mirrorId?: string) =>
  invoke<void>("set_server_mirror", { serverId, mirrorId });

export const getServerSoftwareList = () =>
  invoke<ServerSoftware[]>("get_server_software_list");

export const addServerSoftware = (input: SaveSoftwareInput) =>
  invoke<ServerSoftware>("add_server_software", { input });

export const updateServerSoftware = (id: string, input: SaveSoftwareInput) =>
  invoke<void>("update_server_software", { id, input });

export const deleteServerSoftware = (id: string) =>
  invoke<void>("delete_server_software", { id });

export const generateInstallCommand = (softwareId: string, serverId: string) =>
  invoke<string[]>("generate_install_command", { softwareId, serverId });

// ── Blueprint Buff ────────────────────────────────────────────────────────────

export interface BuffStatus {
  project_path: string;
  project_id: string;
  applied_at: string;
  last_sync_at?: string;
  last_commit?: string;
  status: string;
}

export const applyBlueprintBuff = (projectPath: string, projectId: string) =>
  invoke<BuffStatus>("apply_blueprint_buff", { projectPath, projectId });

export const removeBlueprintBuff = (projectPath: string) =>
  invoke<void>("remove_blueprint_buff", { projectPath });

export const getBuffStatus = (projectPath: string) =>
  invoke<BuffStatus | null>("get_buff_status", { projectPath });

export const listBuffedProjects = () =>
  invoke<BuffStatus[]>("list_buffed_projects");

// ── Onboarding Pack（接入包）──────────────────────────────────────────────────

export interface TemplateResult {
  name: string;
  action: "written" | "skipped" | "failed";
  detail: string;
}

export interface OnboardingReport {
  templates: TemplateResult[];
  buff: BuffStatus;
}

export const applyOnboardingPack = (projectPath: string, projectId: string) =>
  invoke<OnboardingReport>("apply_onboarding_pack", { projectPath, projectId });

// ── Agent Infrastructure ──────────────────────────────────────────────────────

export interface DetectedContract {
  label: string;
  paths: string[];
  doc: string;
  confidence: 'high' | 'medium' | 'low';
}

export interface AgentInfraStack {
  detected_contracts: DetectedContract[];
  meta_rules_present: boolean;
  context_yaml_exists: boolean;
}

export const scanAgentInfraStack = (projectPath: string) =>
  invoke<AgentInfraStack>('scan_agent_infra_stack', { projectPath });

export interface ContractInput {
  label: string;
  paths: string[];
  doc: string;
}

export interface FileResult {
  path: string;
  action: 'written' | 'updated' | 'skipped' | 'failed';
  detail: string;
}

export interface GenerateReport {
  files: FileResult[];
}

export const generateAgentInfraFiles = (projectPath: string, contracts: ContractInput[]) =>
  invoke<GenerateReport>('generate_agent_infra_files', { projectPath, contracts });

export interface FreshnessDetail {
  contract_path: string;
  contract_ts: number | null;
  yaml_ts: number | null;
  gap_days: number | null;
  level: 'green' | 'yellow' | 'red';
}

export interface FreshnessResult {
  level: 'green' | 'yellow' | 'red';
  details: FreshnessDetail[];
  checked_at: string;
}

export interface CachedFreshness {
  score: 'green' | 'yellow' | 'red';
  details: string; // JSON string
  checked_at: string;
}

export const scanDocFreshness = (projectPath: string, projectId: string) =>
  invoke<FreshnessResult>('scan_doc_freshness', { projectPath, projectId });

export const getDocFreshnessCache = (projectId: string) =>
  invoke<CachedFreshness | null>('get_doc_freshness_cache', { projectId });

export interface AgentHealthIssue {
  level: 'error' | 'warn';
  title: string;
  fix: string;
}

export interface AgentHealthReport {
  overall: 'green' | 'yellow' | 'red';
  issues: AgentHealthIssue[];
  fix_prompt: string;
  checked_at: string;
}

export const getAgentHealth = (projectPath: string, projectId: string) =>
  invoke<AgentHealthReport>('get_agent_health', { projectPath, projectId });

export interface CommitStats {
  total: number;
  conventional: number;
  rework: number;
}

export const getCommitStats = (projectId: string) =>
  invoke<CommitStats>("get_commit_stats", { projectId });

export interface IngestResult {
  imported: number;
  skipped: number;
}

export const ingestFullGitHistory = (projectId: string, projectPath: string) =>
  invoke<IngestResult>("ingest_full_git_history", { projectId, projectPath });

export interface ScopeActivity {
  scope: string;
  commit_count: number;
  rework_count: number;
}

export interface ProjectCommitHealth {
  project_id: string;
  total_commits: number;
  conventional_commits: number;
  conventional_rate: number;
  rework_commits: number;
  rework_rate: number;
  top_scopes: ScopeActivity[];
}

export const getProjectCommitHealth = (projectIds: string[]) =>
  invoke<ProjectCommitHealth[]>("get_project_commit_health", { projectIds });

export interface CommitHealthWithName extends ProjectCommitHealth {
  project_name: string;
}

export const getAllCommitHealth = () =>
  invoke<CommitHealthWithName[]>("get_all_commit_health");

// ── Gitea Integration ────────────────────────────────────────────────────────

export interface GiteaInstance {
  id: string;
  name: string;
  url: string;
  access_token: string;
  is_default: boolean;
  created_at?: string;
}

export interface SaveGiteaInstanceInput {
  name: string;
  url: string;
  access_token: string;
  is_default?: boolean;
}

export interface GiteaUser {
  login: string;
  full_name: string;
  email: string;
}

export interface GiteaLinkedRepo {
  id: string;
  instance_id: string;
  instance_name: string;
  instance_url: string;
  project_id: string;
  gitea_owner: string;
  gitea_repo_name: string;
  clone_url?: string;
  has_webhook: boolean;
  webhook_id?: number;
  linked_at?: string;
}

export const giteaSaveInstance = (input: SaveGiteaInstanceInput) =>
  invoke<GiteaInstance>("gitea_save_instance", { input });

export const giteaListInstances = () =>
  invoke<GiteaInstance[]>("gitea_list_instances");

export const giteaDeleteInstance = (id: string) =>
  invoke<void>("gitea_delete_instance", { id });

export const giteaUpdateInstance = (
  id: string,
  fields: { name?: string; url?: string; access_token?: string; is_default?: boolean }
  // Tauri 命令参数按 camelCase 匹配 Rust snake_case，直接展开 snake_case 字段会被静默丢弃
) => invoke<GiteaInstance>("gitea_update_instance", {
  id,
  name: fields.name,
  url: fields.url,
  accessToken: fields.access_token,
  isDefault: fields.is_default,
});

export const giteaTestConnection = (instanceId: string) =>
  invoke<GiteaUser>("gitea_test_connection", { instanceId });

export const giteaListLinkedRepos = () =>
  invoke<GiteaLinkedRepo[]>("gitea_list_linked_repos");

/** 后端 GiteaRepo 结构（单项目绑定详情，与 GiteaLinkedRepo 列表视图字段不同） */
export interface GiteaRepoLink {
  id: string;
  instance_id: string;
  project_id: string;
  gitea_owner: string;
  gitea_repo_name: string;
  clone_url?: string;
  webhook_secret?: string;
  webhook_id?: number;
  linked_at?: string;
}

export const giteaGetRepoLink = (projectId: string) =>
  invoke<GiteaRepoLink | null>("gitea_get_repo_link", { projectId });

export const giteaCreateRepo = (
  instanceId: string,
  projectId: string,
  repoName: string,
  description?: string,
  privateRepo?: boolean
) => invoke<GiteaRepoLink>("gitea_create_repo", { instanceId, projectId, repoName, description, private: privateRepo });

export const giteaMigrateRepo = (
  instanceId: string,
  projectId: string,
  cloneAddr: string,
  repoName: string,
  authToken?: string,
  privateRepo?: boolean
) => invoke<GiteaRepoLink>("gitea_migrate_repo", { instanceId, projectId, cloneAddr, repoName, authToken, private: privateRepo });

export const giteaLinkRepo = (
  instanceId: string,
  projectId: string,
  owner: string,
  repoName: string
) => invoke<GiteaRepoLink>("gitea_link_repo", { instanceId, projectId, owner, repoName });

export const giteaSetupWebhook = (projectId: string, callbackBase: string) =>
  invoke<GiteaRepoLink>("gitea_setup_webhook", { projectId, callbackBase });

export const giteaUnlinkRepo = (projectId: string) =>
  invoke<void>("gitea_unlink_repo", { projectId });

/** 手动触发一次远端轮询采集（后台每 10 分钟自动跑一次） */
export const giteaPollNow = () =>
  invoke<{ polled: number; ingested: number }>("gitea_poll_now");

// ── Beast Global Status (read-only) ───────────────────────────────────────────

export interface BeastGlobalStatus {
  /** Beast 是否已安装 */
  installed: boolean;
  /** 当前是否处于狂暴模式 */
  active: boolean;
  /** ~/.claude/CLAUDE.md 是否含 Beast 注入的 bash 规则 */
  has_bash_rules: boolean;
}

export const getBeastGlobalStatus = () =>
  invoke<BeastGlobalStatus>("get_beast_global_status");

// ── Source Library (源码库) ──────────────────────────────────────────────────

export interface SourceCategory {
  id: string;
  name: string;
  icon: string;
  color: string;
  sort_order: number;
}

export interface SourceProject {
  id: string;
  name: string;
  description?: string;
  category_id?: string;
  language?: string;
  tags?: string;
  repo_url?: string;
  introduction?: string;
  readme?: string;
  notes?: string;
  created_at?: string;
  updated_at?: string;
  category_name?: string;
  version_count?: number;
}

export interface SourceVersion {
  id: string;
  project_id: string;
  version: string;
  file_path: string;
  archive_path?: string;
  file_size: number;
  is_primary: boolean;
  dir_tree?: string;
  notes?: string;
  imported_at?: string;
}

export interface DirEntry {
  name: string;
  type: "dir" | "file";
  children_count?: number;
}

// categories
export const getSourceCategories = () =>
  invoke<SourceCategory[]>("get_source_categories");

export const createSourceCategory = (name: string, icon?: string, color?: string) =>
  invoke<SourceCategory>("create_source_category", { name, icon, color });

export const updateSourceCategory = (id: string, name: string, icon: string, color: string) =>
  invoke<void>("update_source_category", { id, name, icon, color });

export const deleteSourceCategory = (id: string) =>
  invoke<void>("delete_source_category", { id });

// projects
export const getSourceProjects = (categoryId?: string, search?: string) =>
  invoke<SourceProject[]>("get_source_projects", { categoryId, search });

export const createSourceProject = (
  name: string,
  description?: string,
  categoryId?: string,
  language?: string,
  repoUrl?: string,
  introduction?: string,
) => invoke<SourceProject>("create_source_project", { name, description, categoryId, language, repoUrl, introduction });

export const updateSourceProject = (
  id: string,
  name: string,
  description?: string,
  categoryId?: string,
  language?: string,
  repoUrl?: string,
  introduction?: string,
  notes?: string,
) => invoke<void>("update_source_project", { id, name, description, categoryId, language, repoUrl, introduction, notes });

export const deleteSourceProject = (id: string) =>
  invoke<void>("delete_source_project", { id });

// versions
export const getSourceVersions = (projectId: string) =>
  invoke<SourceVersion[]>("get_source_versions", { projectId });

export const addSourceVersion = (projectId: string, projectName: string, version: string, filePath: string) =>
  invoke<SourceVersion>("add_source_version", { projectId, projectName, version, filePath });

export const setPrimaryVersion = (versionId: string, projectId: string) =>
  invoke<void>("set_primary_version", { versionId, projectId });

export const deleteSourceVersion = (versionId: string) =>
  invoke<void>("delete_source_version", { versionId });

export const updateVersionNotes = (versionId: string, notes: string) =>
  invoke<void>("update_version_notes", { versionId, notes });

export const scanSourceDirTree = (path: string) =>
  invoke<DirEntry[]>("scan_source_dir_tree", { path });

export const revealSourceInExplorer = (path: string) =>
  invoke<void>("reveal_source_in_explorer", { path });

export const copySourceTo = (source: string, destDir: string) =>
  invoke<string>("copy_source_to", { source, destDir });

// ── Cloud Products ────────────────────────────────────────────────────────────

export interface CloudProduct {
  id: string;
  vendor: string;        // aliyun | tencent | custom
  product_type: string;  // ecs/cvm/rds/tdsql/oss/cos/cdn/domain/redis/clb/custom
  name: string;
  region?: string;
  instance_id?: string;
  endpoint?: string;
  expire_at?: string;
  status: string;        // active | expired | stopped
  config_data: string;   // JSON string
  notes?: string;
  sort_order: number;
  created_at?: string;
  updated_at?: string;
}

export interface SaveCloudProductInput {
  vendor: string;
  product_type: string;
  name: string;
  region?: string;
  instance_id?: string;
  endpoint?: string;
  expire_at?: string;
  status: string;
  config_data?: string;
  notes?: string;
  sort_order?: number;
}

export const getCloudProducts = () =>
  invoke<CloudProduct[]>("get_cloud_products");

export const addCloudProduct = (input: SaveCloudProductInput) =>
  invoke<CloudProduct>("add_cloud_product", { input });

export const editCloudProduct = (id: string, input: SaveCloudProductInput) =>
  invoke<CloudProduct>("edit_cloud_product", { id, input });

export const deleteCloudProduct = (id: string) =>
  invoke<void>("delete_cloud_product", { id });

// ── Cloud DB Databases ────────────────────────────────────────────────────────

export interface CloudDatabase {
  id: string;
  product_id: string;
  name: string;
  db_driver: string;  // postgresql | mysql | redis | mongodb | custom
  username?: string;
  password?: string;
  charset?: string;
  notes?: string;
  sort_order: number;
  created_at?: string;
  updated_at?: string;
}

export interface SaveCloudDatabaseInput {
  product_id: string;
  name: string;
  db_driver: string;
  username?: string;
  password?: string;
  charset?: string;
  notes?: string;
  sort_order?: number;
}

export const getCloudDatabases = (productId: string) =>
  invoke<CloudDatabase[]>("get_cloud_databases", { productId });

export const addCloudDatabase = (input: SaveCloudDatabaseInput) =>
  invoke<CloudDatabase>("add_cloud_database", { input });

export const editCloudDatabase = (id: string, input: SaveCloudDatabaseInput) =>
  invoke<CloudDatabase>("edit_cloud_database", { id, input });

export const deleteCloudDatabase = (id: string) =>
  invoke<void>("delete_cloud_database", { id });

// ── Docker Apps ──────────────────────────────────────────────────────────────

export interface DockerApp {
  id: string;
  product_id: string;
  name: string;
  access_url?: string;
  username?: string;
  password?: string;
  notes?: string;
  sort_order: number;
  created_at?: string;
  updated_at?: string;
}

export interface SaveDockerAppInput {
  product_id: string;
  name: string;
  access_url?: string;
  username?: string;
  password?: string;
  notes?: string;
  sort_order?: number;
}

export const getDockerApps = (productId: string) =>
  invoke<DockerApp[]>("get_docker_apps", { productId });

export const addDockerApp = (input: SaveDockerAppInput) =>
  invoke<DockerApp>("add_docker_app", { input });

export const editDockerApp = (id: string, input: SaveDockerAppInput) =>
  invoke<DockerApp>("edit_docker_app", { id, input });

export const deleteDockerApp = (id: string) =>
  invoke<void>("delete_docker_app", { id });

