import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import Fastify from 'fastify';
import cookie from '@fastify/cookie';
import Database from 'better-sqlite3';
import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';
import { orgchartRoutes } from '../orgchart-routes.js';
import { registerAuthMiddleware } from '../../auth/auth-middleware.js';
import { authRoutes } from '../../auth/auth-routes.js';
import { hashPassword } from '../../auth/password.js';
import { runMigrations } from '../../db/migrations.js';
const SECRET = 'test-secret-that-is-at-least-32-chars-long!!';
async function buildApp(db, squadsDir) {
    const app = Fastify();
    await app.register(cookie);
    registerAuthMiddleware(app, SECRET);
    await app.register(authRoutes, { db, jwtSecret: SECRET });
    await app.register(orgchartRoutes, { squadsDir });
    await app.ready();
    return app;
}
async function getAuthCookie(app) {
    const res = await app.inject({
        method: 'POST',
        url: '/api/auth/login',
        payload: { username: 'admin', password: 'admin123' },
    });
    const cookies = res.cookies;
    const accessToken = cookies.find(c => c.name === 'access_token');
    return `access_token=${accessToken.value}`;
}
describe('orgchart routes', () => {
    let db;
    let app;
    let authCookie;
    let tmpDir;
    let squadsDir;
    beforeEach(async () => {
        db = new Database(':memory:');
        runMigrations(db);
        const hash = await hashPassword('admin123');
        db.prepare("INSERT INTO users (id, username, password_hash, role, created_at) VALUES (?, ?, ?, ?, ?)").run('admin-id', 'admin', hash, 'admin', new Date().toISOString());
        // Create temp directory structure
        tmpDir = path.join(os.tmpdir(), `orgchart-test-${Date.now()}`);
        squadsDir = path.join(tmpDir, 'squads');
        fs.mkdirSync(squadsDir, { recursive: true });
        // Create agents catalog
        const agentsDir = path.join(tmpDir, 'agents');
        fs.mkdirSync(agentsDir, { recursive: true });
        fs.writeFileSync(path.join(agentsDir, '_catalog.yaml'), `catalog:
  sectors:
    - name: Development
      agents:
        - tech-lead
        - backend-dev
        - frontend-dev
    - name: Marketing
      agents:
        - content-writer
        - seo-analyst
`);
        // Create a squad
        const squadDir = path.join(squadsDir, 'alpha-team');
        fs.mkdirSync(squadDir, { recursive: true });
        fs.writeFileSync(path.join(squadDir, 'squad.yaml'), `squad:
  code: alpha-team
  name: Alpha Team
  description: Core development squad
  icon: rocket
  agents:
    - id: tech-lead
      name: Tech Lead
      icon: star
    - id: backend-dev
      name: Backend Dev
      icon: code
  pipeline:
    steps:
      - id: step-01
        agent: tech-lead
        label: Architecture review
        execution: inline
      - id: step-02
        type: checkpoint
        label: Approve architecture
        options:
          - approve
          - reject
        on_reject: step-01
      - id: step-03
        agent: backend-dev
        label: Implementation
        deliverFrom: tech-lead
        execution: inline
`);
        // Create company memory
        const memDir = path.join(tmpDir, '_expxagents', '_memory');
        fs.mkdirSync(memDir, { recursive: true });
        fs.writeFileSync(path.join(memDir, 'company.md'), '# TestCorp\nA test company');
        app = await buildApp(db, squadsDir);
        authCookie = await getAuthCookie(app);
    });
    afterEach(async () => {
        await app?.close();
        db?.close();
        fs.rmSync(tmpDir, { recursive: true, force: true });
    });
    it('GET /api/orgchart — returns tree and squads', async () => {
        const res = await app.inject({
            method: 'GET',
            url: '/api/orgchart',
            headers: { cookie: authCookie },
        });
        expect(res.statusCode).toBe(200);
        const body = JSON.parse(res.payload);
        // Tree structure
        expect(body.tree).toBeDefined();
        expect(body.tree.name).toBe('TestCorp');
        expect(body.tree.type).toBe('company');
        expect(body.tree.children).toHaveLength(2);
        // Sectors
        const dev = body.tree.children.find((s) => s.name === 'Development');
        expect(dev).toBeDefined();
        expect(dev.agentCount).toBe(3);
        expect(dev.children).toHaveLength(3);
        // Agent names are title-cased from IDs
        const techLead = dev.children.find((a) => a.id === 'tech-lead');
        expect(techLead).toBeDefined();
        expect(techLead.name).toBe('Tech Lead');
        expect(techLead.type).toBe('agent');
    });
    it('returns agent → squad mapping', async () => {
        const res = await app.inject({
            method: 'GET',
            url: '/api/orgchart',
            headers: { cookie: authCookie },
        });
        const body = JSON.parse(res.payload);
        const dev = body.tree.children.find((s) => s.name === 'Development');
        const techLead = dev.children.find((a) => a.id === 'tech-lead');
        // tech-lead is in Alpha Team
        expect(techLead.squads).toContain('Alpha Team');
        // frontend-dev is not in any squad
        const frontendDev = dev.children.find((a) => a.id === 'frontend-dev');
        expect(frontendDev.squads).toEqual([]);
    });
    it('returns squads list with pipeline', async () => {
        const res = await app.inject({
            method: 'GET',
            url: '/api/orgchart',
            headers: { cookie: authCookie },
        });
        const body = JSON.parse(res.payload);
        expect(body.squads).toHaveLength(1);
        expect(body.squads[0].name).toBe('Alpha Team');
        expect(body.squads[0].agents).toHaveLength(2);
        // Pipeline chain
        const pipeline = body.squads[0].pipeline;
        expect(pipeline).toHaveLength(3);
        expect(pipeline[0]).toEqual({ id: 'step-01', agent: 'tech-lead', label: 'Architecture review' });
        expect(pipeline[1]).toEqual({ id: 'step-02', label: 'Approve architecture', type: 'checkpoint' });
        expect(pipeline[2]).toEqual({ id: 'step-03', agent: 'backend-dev', label: 'Implementation', deliverFrom: 'tech-lead' });
    });
    it('works with no catalog file', async () => {
        // Remove the catalog
        fs.unlinkSync(path.join(tmpDir, 'agents', '_catalog.yaml'));
        const res = await app.inject({
            method: 'GET',
            url: '/api/orgchart',
            headers: { cookie: authCookie },
        });
        expect(res.statusCode).toBe(200);
        const body = JSON.parse(res.payload);
        expect(body.tree.children).toEqual([]);
    });
    it('defaults company name when no company.md', async () => {
        fs.unlinkSync(path.join(tmpDir, '_expxagents', '_memory', 'company.md'));
        const res = await app.inject({
            method: 'GET',
            url: '/api/orgchart',
            headers: { cookie: authCookie },
        });
        const body = JSON.parse(res.payload);
        expect(body.tree.name).toBe('Company');
    });
    it('rejects unauthenticated requests', async () => {
        const res = await app.inject({
            method: 'GET',
            url: '/api/orgchart',
        });
        expect(res.statusCode).toBe(401);
    });
});
//# sourceMappingURL=orgchart-routes.test.js.map