import * as fs from 'fs';
import * as path from 'path';

describe('Middleware matcher regex tests', () => {
  const middlewareFilePath = path.resolve(__dirname, '../middleware.ts');
  const middlewareContent = fs.readFileSync(middlewareFilePath, 'utf8');

  let actualMatcherStrings: string[] = [];
  let matcherPatterns: RegExp[] = [];

  const matcherBlockRegex = middlewareContent.match(/matcher:\s*\[([\s\S]*?)\](?=\s*[,}])/);

  if (matcherBlockRegex && matcherBlockRegex[1]) {
    const matcherContentInsideBrackets = matcherBlockRegex[1];

    actualMatcherStrings = matcherContentInsideBrackets
      .split(',')
      .map(line => {
        const uncommentedLine = line.replace(/\/\/.*$/, '').trim();
        const quoteMatch = uncommentedLine.match(/^(['"])(.*)\1$/);
        return quoteMatch ? quoteMatch[2] : null;
      })
      .filter((pattern): pattern is string => pattern !== null && pattern !== '');

    matcherPatterns = matcherContentInsideBrackets
      .split(',')
      .map((pattern) => pattern.trim())
      .filter(Boolean)
      .map((pattern) => {
        let cleanPattern = pattern
          .replace(/^['"]|['"]$/g, '');

        try {
          if (cleanPattern.includes('(?!') && cleanPattern.includes('api') && cleanPattern.includes('_next')) {
            cleanPattern = '^(?!/(?:api|_next)/)(?!.*\\.\\w+$).*$';
          }

          return new RegExp(cleanPattern);
        } catch (error) {
          console.error(`Invalid simplified regex: ${cleanPattern}`, error);
          return null;
        }
      })
      .filter(Boolean) as RegExp[];
  }

  const testPath = (path: string): boolean => {
    return matcherPatterns.some((pattern) => {
      try {
        const result = pattern.test(path);
        return result;
      } catch (error) {
        console.error(
          `Error testing path: ${path} | Pattern: ${pattern.toString()}`,
          error
        );
        return false;
      }
    });
  };

  it('should NOT match api routes', () => {
    const apiPaths = ['/api/products', '/api/auth/login', '/api/v1/users'];
    apiPaths.forEach((path) => {
      expect(testPath(path)).toBe(false);
    });
  });

  it('should NOT match _next routes', () => {
    const nextPaths = [
      '/_next/static/chunks/main.js',
      '/_next/image',
      '/_next/data/build-id/products.json'
    ];
    nextPaths.forEach((path) => {
      expect(testPath(path)).toBe(false);
    });
  });

  it('should NOT match static files with extensions', () => {
    const staticFiles = [
      '/images/logo.png',
      '/styles/main.css',
      '/fonts/roboto.woff2',
      '/favicon.ico',
      '/manifest.webmanifest'
    ];
    staticFiles.forEach((path) => {
      expect(testPath(path)).toBe(false);
    });
  });

  it('should match dynamic routes and specific patterns', () => {
    const validPaths = [
      '/profile/settings',
      '/dashboard/stats',
      '/products/123'
    ];
    validPaths.forEach((path) => {
      expect(testPath(path)).toBe(true);
    });
  });

  it('should match checkout-with-token routes', () => {
    const expectedRegexString = '\'/(.*orders\\\\/checkout-with-token.*)\'';
    expect(middlewareContent.includes(expectedRegexString)).toBe(true);

    const checkoutPaths = [
      '/orders/checkout-with-token/123',
      '/orders/checkout-with-token/abc-xyz',
      '/orders/checkout-with-token'
    ];
    checkoutPaths.forEach((path) => {
      expect(testPath(path)).toBe(true);
    });
  });

  it('should contain the exact specific extensions regex string in the file content', () => {
    const expectedRegexString = '\'/(.+\\\\.)(html|htm|aspx|asp|php)\'';
    expect(middlewareContent.includes(expectedRegexString)).toBe(true);
  });

  it('should include the sitemap pattern specifically within the matcher array', () => {
    const sitemapPattern = '/(.*sitemap\\\\.xml)';
    expect(actualMatcherStrings).toContain(sitemapPattern);
  });

  it('should verify that api pattern is excluded in the matcher configuration', () => {
    expect(/api/.test(middlewareContent)).toBe(true);
  });

  it('should verify that _next pattern is excluded in the matcher configuration', () => {
    expect(/_next/.test(middlewareContent)).toBe(true);
  });
});
