import { describe, it } from 'node:test';
import { strict as assert } from 'node:assert';
import { readFileSync, existsSync } from 'node:fs';
import { resolve } from 'node:path';
import { parse } from 'node:url';

const deployPath = resolve('.github/workflows/deploy.yml');
const azurePath = resolve('.github/workflows/azure-static-web-apps-salmon-sea-0f0c8771e.yml');

function readDeploy() {
  return readFileSync(deployPath, 'utf-8');
}

function readAzure() {
  return readFileSync(azurePath, 'utf-8');
}

// Snapshot the Azure file content before any tests run
const azureOriginal = readAzure();

describe('GitHub Pages deploy workflow', () => {
  it('should exist at .github/workflows/deploy.yml', () => {
    assert.ok(existsSync(deployPath), 'deploy.yml should exist');
  });

  it('should be valid YAML (parseable without error)', async () => {
    // Use a simple structural check - YAML should have proper structure
    const content = readDeploy();
    assert.ok(content.length > 0, 'file should not be empty');
    // Check it starts with a name field (standard workflow structure)
    assert.match(content, /^name:/, 'should start with name field');
  });

  describe('Triggers', () => {
    it('should trigger on push to master branch', () => {
      const content = readDeploy();
      assert.match(content, /on:/, 'should have on: trigger');
      assert.match(content, /push:/, 'should have push trigger');
      assert.match(content, /branches:[\s\S]*?-\s*master/, 'should trigger on master branch');
    });

    it('should trigger on workflow_dispatch', () => {
      const content = readDeploy();
      assert.match(content, /workflow_dispatch/, 'should have workflow_dispatch trigger');
    });
  });

  describe('Permissions', () => {
    it('should set contents: read permission', () => {
      const content = readDeploy();
      assert.match(content, /contents:\s*read/, 'should have contents read permission');
    });

    it('should set pages: write permission', () => {
      const content = readDeploy();
      assert.match(content, /pages:\s*write/, 'should have pages write permission');
    });

    it('should set id-token: write permission', () => {
      const content = readDeploy();
      assert.match(content, /id-token:\s*write/, 'should have id-token write permission');
    });
  });

  describe('Concurrency', () => {
    it('should have concurrency group pages', () => {
      const content = readDeploy();
      assert.match(content, /concurrency:/, 'should have concurrency block');
      assert.match(content, /group:\s*['"]?pages['"]?/, 'should have pages concurrency group');
    });

    it('should cancel in-progress deployments', () => {
      const content = readDeploy();
      assert.match(content, /cancel-in-progress:\s*true/, 'should cancel in-progress');
    });
  });

  describe('Build job', () => {
    it('should have a build job on ubuntu-latest', () => {
      const content = readDeploy();
      assert.match(content, /build:/, 'should have build job');
      assert.match(content, /runs-on:\s*ubuntu-latest/, 'should run on ubuntu-latest');
    });

    it('should checkout with actions/checkout@v4', () => {
      const content = readDeploy();
      assert.match(content, /actions\/checkout@v4/, 'should use checkout@v4');
    });

    it('should setup Node 22 with npm cache', () => {
      const content = readDeploy();
      assert.match(content, /actions\/setup-node@v4/, 'should use setup-node@v4');
      assert.match(content, /node-version:\s*['"]?22['"]?/, 'should use Node 22');
      assert.match(content, /cache:\s*['"]?npm['"]?/, 'should cache npm');
    });

    it('should run npm ci', () => {
      const content = readDeploy();
      assert.match(content, /npm ci/, 'should run npm ci');
    });

    it('should run npm run build', () => {
      const content = readDeploy();
      assert.match(content, /npm run build/, 'should run npm run build');
    });

    it('should upload pages artifact from dist/', () => {
      const content = readDeploy();
      assert.match(content, /actions\/upload-pages-artifact@v3/, 'should use upload-pages-artifact@v3');
      assert.match(content, /path:\s*['"]?dist\/?['"]?/, 'should upload from dist/');
    });
  });

  describe('Deploy job', () => {
    it('should have a deploy job', () => {
      const content = readDeploy();
      assert.match(content, /deploy:/, 'should have deploy job');
    });

    it('should depend on build job', () => {
      const content = readDeploy();
      assert.match(content, /needs:\s*build/, 'should need build job');
    });

    it('should run on ubuntu-latest', () => {
      const content = readDeploy();
      // The deploy job section should have its own runs-on
      // Extract deploy job section
      const deploySection = content.split(/\n\s+deploy:/)[1];
      assert.ok(deploySection, 'deploy section should exist');
      assert.match(deploySection, /runs-on:\s*ubuntu-latest/, 'deploy should run on ubuntu-latest');
    });

    it('should have github-pages environment', () => {
      const content = readDeploy();
      assert.match(content, /environment:/, 'should have environment');
      assert.match(content, /name:\s*['"]?github-pages['"]?/, 'should use github-pages environment');
    });

    it('should set URL from deployment output', () => {
      const content = readDeploy();
      assert.match(content, /url:\s*\$\{\{/, 'should set URL from deployment output');
    });

    it('should use deploy-pages@v4', () => {
      const content = readDeploy();
      assert.match(content, /actions\/deploy-pages@v4/, 'should use deploy-pages@v4');
    });
  });

  describe('Existing Azure workflow', () => {
    it('should still exist', () => {
      assert.ok(existsSync(azurePath), 'Azure workflow should still exist');
    });

    it('should be unchanged', () => {
      const current = readAzure();
      assert.equal(current, azureOriginal, 'Azure workflow content should not be modified');
    });
  });
});