#!/usr/bin/env node
import fs from 'fs';
import os from 'os';
import path from 'path';
import { fileURLToPath } from 'url';

import { DOCCENTER_API_URL } from '../src/data/doc-paths.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, '..');
const APPLY = process.argv.includes('--apply');

const AUTH_PATH = path.join(os.homedir(), '.vl-code', 'auth.json');
const cookie = process.env.DOCCENTER_COOKIE || (() => {
  try {
    return JSON.parse(fs.readFileSync(AUTH_PATH, 'utf-8')).cookie;
  } catch {
    return '';
  }
})();

const MANIFEST = [
  {
    file: '.vl-code/workflows/parallel-codegen.json',
    path: '112',
    name: 'VL_Parallel_CodeGen_v3.16',
    description: 'Fast ProjectMeta-driven code generation with default Theme/Theme.vth and parallel VL file fanout.',
    changeNote: 'v3.16.2 — enforce Theme/Theme.vth, Database/<ProjectName>.vdb, and parallel VL file generation',
  },
  {
    file: '.vl-code/workflows/meta-direct-codegen.json',
    path: '113',
    name: 'VL_MetaDirect_CodeGen_v3.16',
    description: 'Small-project ProjectMeta-first code generation with default Theme/Theme.vth and parallel VL file fanout.',
    changeNote: 'v3.16.2 — enforce Theme/Theme.vth, Database/<ProjectName>.vdb, and parallel VL file generation',
  },
  {
    file: '.vl-code/workflows/3-file-codegen.json',
    path: '114',
    name: 'VL_3File_CodeGen_v3.16',
    description: '3-file auxiliary workflow using PRD + ServiceMap + UIMap, plus default Theme/Theme.vth.',
    changeNote: 'v3.16.2 — seed Theme/Theme.vth, remove main.vdb fallback, and parallelize final VL fanout',
  },
  {
    file: '.vl-code/workflows/6-file-codegen.json',
    path: '60',
    name: 'VL_FullStack_CodeGen_6Files_v3.16',
    description: 'Full-stack code generation using 6 auxiliary spec files and DocCenter agent prompts.',
    changeNote: 'v3.16.2 — enforce Theme/Theme.vth, Database/<ProjectName>.vdb, and parallel VL file generation',
  },
  {
    file: '.vl-code/workflows/9-file-codegen.json',
    path: '115',
    name: 'VL_9File_CodeGen_v3.16',
    description: '9-file auxiliary workflow with manifest-driven parallel VL generation and default Theme/Theme.vth.',
    changeNote: 'v3.16.2 — enforce Theme/Theme.vth, Database/<ProjectName>.vdb, and parallel VL file generation',
  },
  {
    file: '.vl-code/workflows/add-page.json',
    path: '120',
    name: 'VL_AddPage_Workflow_v1',
    description: 'Workflow to add a new page (section + components + route) to an existing VL project',
    changeNote: 'v1.2 — fix DocCenter prompt refs and write updated route to the real target app file',
  },
  {
    file: '.vl-code/workflows/add-service.json',
    path: '130',
    name: 'VL_AddService_Workflow_v1',
    description: 'Workflow to add a new backend service domain to an existing VL project',
    changeNote: 'v1.1 — fix prompt refs and write database changes to the ProjectMeta database file',
  },
  {
    file: '.vl-code/workflows/theme-customize.json',
    path: '140',
    name: 'VL_ThemeCustomize_Workflow_v1',
    description: 'Workflow to regenerate theme tokens and cascade updates to affected VL files',
    changeNote: 'v1.1 — fix theme prompt path, dynamic theme file resolution, and cascade file writes',
  },
  {
    file: '.vl-code/workflows/incremental-update.json',
    path: '141',
    name: 'VL_IncrementalUpdate_Workflow_v1',
    description: 'General existing-project adjustment workflow using meta diff plus targeted file regeneration.',
    changeNote: 'v1.0 — remove missing DocCenter prompt deps and strengthen inline regen instructions',
  },
  {
    file: '.vl-code/workflows/compile-fix.json',
    path: '142',
    name: 'VL_CompileFix_Workflow_v2',
    description: 'Compile-report-driven workflow that applies file fixes from .vl-code/last-compile.json and hands verification back to VLCompile.',
    changeNote: 'v2.0 — replace fake compile/recompile steps with report-driven repair flow',
  },
  {
    file: 'docs/workflow-audits/workflow-audit-2026-03-14.md',
    path: '161',
    name: 'VL-Code Workflow Audit Report 2026-03-14',
    description: 'Workflow/doc-center/debug-fix audit report for the 2026-03-14 correction pass.',
    changeNote: 'Initial audit report',
  },
];

if (!cookie) {
  console.error('Missing DocCenter cookie. Set DOCCENTER_COOKIE or login so ~/.vl-code/auth.json exists.');
  process.exit(1);
}

const headers = {
  'Content-Type': 'application/json',
  Cookie: `ih5bearer=${cookie}`,
};

async function dcPost(endpoint, body) {
  const res = await fetch(`${DOCCENTER_API_URL}/${endpoint}`, {
    method: 'POST',
    headers,
    body: JSON.stringify(body),
  });
  const text = await res.text();
  try {
    return JSON.parse(text);
  } catch {
    throw new Error(`DocCenter returned non-JSON for ${endpoint}: ${text.slice(0, 300)}`);
  }
}

async function loadCatalog() {
  const res = await dcPost('SERVICE_DocCenter_GetDocList', {
    keyword: '',
    tagId: 0,
    page: 1,
    pageSize: 200,
  });
  return Array.isArray(res?.data) ? res.data : [];
}

async function getDocContent(docId) {
  const res = await dcPost('SERVICE_DocCenter_GetDocById', { docId });
  return res?.data || null;
}

async function syncOne(entry, catalog) {
  const fullPath = path.join(ROOT, entry.file);
  const currentContent = fs.readFileSync(fullPath, 'utf-8');
  const existing = catalog.find(doc => String(doc.path) === String(entry.path)) ||
    catalog.find(doc => doc.name === entry.name);

  if (!existing) {
    if (!APPLY) {
      return { action: 'create', path: entry.path, name: entry.name, docId: null };
    }
    const createRes = await dcPost('SERVICE_DocCenter_CreateDoc', {
      name: entry.name,
      description: entry.description,
      path: entry.path,
    });
    const created = createRes?.data || createRes;
    const docId = created?._id || created?.id || createRes?.docId || createRes?.data?.docId;
    if (!docId) throw new Error(`CreateDoc did not return a docId for path ${entry.path}`);
    await dcPost('SERVICE_DocCenter_SaveAsVersion', {
      path: entry.path,
      name: entry.name,
      description: entry.description,
      currentContent,
      changeNote: entry.changeNote,
    });
    catalog.push({ _id: docId, path: entry.path, name: entry.name });
    return { action: 'created', path: entry.path, name: entry.name, docId };
  }

  const docId = existing._id || existing.id;
  const remote = docId ? await getDocContent(docId) : null;
  if (remote?.currentContent === currentContent) {
    return { action: 'unchanged', path: entry.path, name: entry.name, docId };
  }

  if (!APPLY) {
    return { action: 'publish', path: entry.path, name: entry.name, docId };
  }

  await dcPost('SERVICE_DocCenter_SaveAsVersion', {
    path: entry.path,
    name: entry.name,
    description: entry.description,
    currentContent,
    changeNote: entry.changeNote,
  });
  return { action: 'published', path: entry.path, name: entry.name, docId };
}

async function main() {
  const catalog = await loadCatalog();
  const results = [];

  console.log(`\nDocCenter workflow sync ${APPLY ? '(apply)' : '(dry-run)'}`);
  for (const entry of MANIFEST) {
    const result = await syncOne(entry, catalog);
    results.push(result);
    const label = `${result.action}`.padEnd(9, ' ');
    console.log(`${label} path ${result.path}  ${result.name}${result.docId ? `  (docId ${result.docId})` : ''}`);
  }

  const counts = results.reduce((acc, item) => {
    acc[item.action] = (acc[item.action] || 0) + 1;
    return acc;
  }, {});
  console.log('\nSummary:', counts);
}

main().catch(err => {
  console.error(err.message);
  process.exit(1);
});
