import { describe, it, expect } from 'vitest';
import { readFileSync, existsSync } from 'fs';
import { resolve } from 'path';
import { parse as parseYaml } from 'yaml';

describe('Gitea Workflow CI - Phase 9.4', () => {
  const workflowPath = resolve(process.cwd(), '.gitea/workflows/ci.yml');
  const securityPath = resolve(process.cwd(), 'SECURITY.md');
  const apiKeysPath = resolve(process.cwd(), 'docs/API_KEYS.md');

  let workflowContent: string;
  let workflowYaml: any;
  let securityContent: string;
  let apiKeysContent: string;

  // Load files once
  if (existsSync(workflowPath)) {
    workflowContent = readFileSync(workflowPath, 'utf-8');
    workflowYaml = parseYaml(workflowContent);
  }

  if (existsSync(securityPath)) {
    securityContent = readFileSync(securityPath, 'utf-8');
  }

  if (existsSync(apiKeysPath)) {
    apiKeysContent = readFileSync(apiKeysPath, 'utf-8');
  }

  // Test 1: Workflow file exists
  it('should have .gitea/workflows/ci.yml file', () => {
    expect(existsSync(workflowPath)).toBe(true);
  });

  // Test 2: Contains lint job
  it('should contain job: lint', () => {
    expect(workflowYaml?.jobs?.lint).toBeDefined();
    expect(workflowYaml.jobs.lint.steps).toBeDefined();
  });

  // Test 3: Contains test-backend job
  it('should contain job: test-backend', () => {
    expect(workflowYaml?.jobs?.['test-backend']).toBeDefined();
    expect(workflowYaml.jobs['test-backend'].steps).toBeDefined();
  });

  // Test 4: Contains test-frontend job
  it('should contain job: test-frontend', () => {
    expect(workflowYaml?.jobs?.['test-frontend']).toBeDefined();
    expect(workflowYaml.jobs['test-frontend'].steps).toBeDefined();
  });

  // Test 5: Contains test-e2e job
  it('should contain job: test-e2e', () => {
    expect(workflowYaml?.jobs?.['test-e2e']).toBeDefined();
    expect(workflowYaml.jobs['test-e2e'].steps).toBeDefined();
  });

  // Test 6: E2E job depends on backend and frontend tests
  it('test-e2e should have needs: [test-backend, test-frontend]', () => {
    const needs = workflowYaml?.jobs?.['test-e2e']?.needs;
    expect(Array.isArray(needs) || typeof needs === 'string').toBe(true);

    const needsArray = Array.isArray(needs) ? needs : [needs];
    expect(needsArray).toContain('test-backend');
    expect(needsArray).toContain('test-frontend');
  });

  // Test 7: E2E uses Gitea Secrets for API keys
  it('test-e2e should use Gitea Secrets for API keys', () => {
    const env = workflowYaml?.jobs?.['test-e2e']?.env;
    expect(env).toBeDefined();

    // Check for secret references
    const envStr = JSON.stringify(env);
    expect(envStr).toContain('secrets.IGDB_CLIENT_ID');
    expect(envStr).toContain('secrets.IGDB_CLIENT_SECRET');
    expect(envStr).toContain('secrets.RAWG_API_KEY');
    expect(envStr).toContain('secrets.THEGAMESDB_API_KEY');
  });

  // Test 8: E2E includes yarn test:install step
  it('test-e2e should include yarn test:install step', () => {
    const steps = workflowYaml?.jobs?.['test-e2e']?.steps || [];
    const testInstallStep = steps.some(
      (step: any) =>
        step.run && typeof step.run === 'string' && step.run.includes('yarn test:install')
    );
    expect(testInstallStep).toBe(true);
  });

  // Test 9: Has triggers on push and pull_request
  it('should have triggers on push and pull_request', () => {
    const on = workflowYaml?.on;
    expect(on).toBeDefined();
    expect(on?.push || on?.['push']).toBeDefined();
    expect(on?.pull_request || on?.['pull_request']).toBeDefined();
  });

  // Test 10: Installs Node.js and caches yarn (lint job)
  it('should install Node.js and cache yarn in lint job', () => {
    const steps = workflowYaml?.jobs?.lint?.steps || [];
    const hasNodeSetup = steps.some((step: any) => step.uses && step.uses.includes('setup-node'));
    const hasYarnCache = steps.some(
      (step: any) => step.uses && step.uses.includes('setup-node') && step.with?.cache === 'yarn'
    );

    expect(hasNodeSetup).toBe(true);
    expect(hasYarnCache).toBe(true);
  });

  // Test 11: SECURITY.md mentions Gitea Secrets setup
  it('SECURITY.md should mention Gitea Secrets setup', () => {
    expect(securityContent).toBeDefined();
    expect(securityContent.toLowerCase()).toContain('gitea');
    expect(securityContent.toLowerCase()).toContain('secret');
  });

  // Test 12: SECURITY.md has instructions for CI/CD secrets
  it('SECURITY.md should have CI/CD secrets instructions', () => {
    expect(securityContent).toBeDefined();
    expect(securityContent.toLowerCase()).toContain('ci/cd');
    expect(securityContent).toContain('IGDB_CLIENT_ID');
    expect(securityContent).toContain('RAWG_API_KEY');
  });
});
