import { describe, it, expect } from 'vitest';
import { parseCwPreviewConfig } from './config-reader.js';

describe('parseCwPreviewConfig', () => {
  it('parses minimal single-service config', () => {
    const raw = `
version: 1
services:
  app:
    build: "."
    port: 3000
`;
    const config = parseCwPreviewConfig(raw);
    expect(config.version).toBe(1);
    expect(Object.keys(config.services)).toEqual(['app']);
    expect(config.services.app.port).toBe(3000);
    expect(config.services.app.build).toBe('.');
  });

  it('parses multi-service config with routes and healthchecks', () => {
    const raw = `
version: 1
services:
  frontend:
    build:
      context: "."
      dockerfile: apps/web/Dockerfile
    port: 3000
    route: /
    healthcheck:
      path: /
      interval: 5s
      retries: 10
    env:
      VITE_API_URL: /api
  backend:
    build:
      context: "."
      dockerfile: packages/api/Dockerfile
    port: 8080
    route: /api
    healthcheck:
      path: /health
    env:
      DATABASE_URL: "postgres://db:5432/app"
  db:
    image: postgres:16-alpine
    port: 5432
    internal: true
    env:
      POSTGRES_PASSWORD: preview
`;
    const config = parseCwPreviewConfig(raw);

    expect(Object.keys(config.services)).toHaveLength(3);

    // Frontend
    expect(config.services.frontend.port).toBe(3000);
    expect(config.services.frontend.route).toBe('/');
    expect(config.services.frontend.healthcheck?.path).toBe('/');
    expect(config.services.frontend.healthcheck?.retries).toBe(10);
    expect(config.services.frontend.env?.VITE_API_URL).toBe('/api');
    expect(config.services.frontend.build).toEqual({
      context: '.',
      dockerfile: 'apps/web/Dockerfile',
    });

    // Backend
    expect(config.services.backend.port).toBe(8080);
    expect(config.services.backend.route).toBe('/api');

    // DB (internal)
    expect(config.services.db.internal).toBe(true);
    expect(config.services.db.image).toBe('postgres:16-alpine');
  });

  it('rejects config without services', () => {
    expect(() => parseCwPreviewConfig('version: 1\n')).toThrow('missing "services"');
  });

  it('rejects service without port (unless internal)', () => {
    const raw = `
version: 1
services:
  app:
    build: "."
`;
    expect(() => parseCwPreviewConfig(raw)).toThrow('must specify a "port"');
  });

  it('allows internal service without port', () => {
    const raw = `
version: 1
services:
  redis:
    image: redis:7
    internal: true
`;
    const config = parseCwPreviewConfig(raw);
    expect(config.services.redis.internal).toBe(true);
    expect(config.services.redis.port).toBe(0);
  });

  it('normalizes string build to string', () => {
    const raw = `
version: 1
services:
  app:
    build: "./app"
    port: 3000
`;
    const config = parseCwPreviewConfig(raw);
    expect(config.services.app.build).toBe('./app');
  });

  it('parses dev section with image, command, and workdir', () => {
    const raw = `
version: 1
services:
  frontend:
    build: "."
    port: 3000
    route: /
    dev:
      image: node:20-alpine
      command: npm run dev -- --host 0.0.0.0
      workdir: /app
`;
    const config = parseCwPreviewConfig(raw);
    expect(config.services.frontend.dev).toBeDefined();
    expect(config.services.frontend.dev!.image).toBe('node:20-alpine');
    expect(config.services.frontend.dev!.command).toBe('npm run dev -- --host 0.0.0.0');
    expect(config.services.frontend.dev!.workdir).toBe('/app');
  });

  it('parses seed array on a service', () => {
    const raw = `
version: 1
services:
  app:
    build: "."
    port: 3000
    seed:
      - npm run db:migrate
      - npm run db:seed
`;
    const config = parseCwPreviewConfig(raw);
    expect(config.services.app.seed).toEqual(['npm run db:migrate', 'npm run db:seed']);
  });

  it('omits seed when not specified', () => {
    const raw = `
version: 1
services:
  app:
    build: "."
    port: 3000
`;
    const config = parseCwPreviewConfig(raw);
    expect(config.services.app.seed).toBeUndefined();
  });

  it('parses dev section with only image', () => {
    const raw = `
version: 1
services:
  app:
    build: "."
    port: 3000
    dev:
      image: node:20-alpine
`;
    const config = parseCwPreviewConfig(raw);
    expect(config.services.app.dev).toBeDefined();
    expect(config.services.app.dev!.image).toBe('node:20-alpine');
    expect(config.services.app.dev!.command).toBeUndefined();
    expect(config.services.app.dev!.workdir).toBeUndefined();
  });
});
