import { describe, test, expect, beforeEach } from 'vitest';
import type { Cookie } from 'playwright';
import { SessionCookieStore } from './SessionCookieStore';

const logger = console as unknown;

describe('SessionCookieStore - Cookie Validation', () => {
  let cookieStore: SessionCookieStore;

  beforeEach(() => {
    cookieStore = new SessionCookieStore('test-user-data', logger);
  });

  describe('validateCookieConfiguration()', () => {
    const targetUrl = 'https://members-ng.iracing.com/jjwtauth/success';

    test('should succeed when all cookies are valid for target URL', async () => {
      const cookies: Cookie[] = [
        {
          name: 'irsso_members',
          value: 'valid_sso_token',
          domain: '.iracing.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
        {
          name: 'authtoken_members',
          value: 'valid_auth_token',
          domain: 'members-ng.iracing.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const result = cookieStore.validateCookieConfiguration(targetUrl);

      expect(result.isOk()).toBe(true);
    });

    test('should fail when cookie domain mismatches target', async () => {
      const cookies: Cookie[] = [
        {
          name: 'irsso_members',
          value: 'valid_token',
          domain: 'example.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const result = cookieStore.validateCookieConfiguration(targetUrl);

      expect(result.isErr()).toBe(true);
      expect(result.unwrapErr().message).toMatch(/domain mismatch/i);
    });

    test('should fail when cookie path is invalid for target', async () => {
      const cookies: Cookie[] = [
        {
          name: 'irsso_members',
          value: 'valid_token',
          domain: '.iracing.com',
          path: '/invalid/path',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const result = cookieStore.validateCookieConfiguration(targetUrl);

      expect(result.isErr()).toBe(true);
      expect(result.unwrapErr().message).toMatch(/path.*not valid/i);
    });

    test('should fail when required irsso_members cookie is missing', async () => {
      const cookies: Cookie[] = [
        {
          name: 'authtoken_members',
          value: 'valid_auth_token',
          domain: 'members-ng.iracing.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const result = cookieStore.validateCookieConfiguration(targetUrl);

      expect(result.isErr()).toBe(true);
      expect(result.unwrapErr().message).toMatch(/required.*irsso_members/i);
    });

    test('should fail when required authtoken_members cookie is missing', async () => {
      const cookies: Cookie[] = [
        {
          name: 'irsso_members',
          value: 'valid_sso_token',
          domain: '.iracing.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const result = cookieStore.validateCookieConfiguration(targetUrl);

      expect(result.isErr()).toBe(true);
      expect(result.unwrapErr().message).toMatch(/required.*authtoken_members/i);
    });

    test('should fail when no cookies are stored', () => {
      const result = cookieStore.validateCookieConfiguration(targetUrl);

      expect(result.isErr()).toBe(true);
      expect(result.unwrapErr().message).toMatch(/no cookies/i);
    });

    test('should validate cookies for members-ng.iracing.com domain', async () => {
      const cookies: Cookie[] = [
        {
          name: 'irsso_members',
          value: 'valid_token',
          domain: 'members-ng.iracing.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
        {
          name: 'authtoken_members',
          value: 'valid_auth_token',
          domain: 'members-ng.iracing.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const result = cookieStore.validateCookieConfiguration(targetUrl);

      expect(result.isOk()).toBe(true);
    });
  });

  describe('getValidCookiesForUrl()', () => {
    const targetUrl = 'https://members-ng.iracing.com/jjwtauth/success';

    test('should return only cookies valid for target URL', async () => {
      const cookies: Cookie[] = [
        {
          name: 'valid_cookie',
          value: 'valid_value',
          domain: '.iracing.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
        {
          name: 'invalid_cookie',
          value: 'invalid_value',
          domain: 'example.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const validCookies = cookieStore.getValidCookiesForUrl(targetUrl);

      expect(validCookies).toHaveLength(1);
      expect(validCookies[0]!.name).toBe('valid_cookie');
    });

    test('should filter out cookies with mismatched domains', async () => {
      const cookies: Cookie[] = [
        {
          name: 'cookie1',
          value: 'value1',
          domain: '.iracing.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
        {
          name: 'cookie2',
          value: 'value2',
          domain: '.example.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const validCookies = cookieStore.getValidCookiesForUrl(targetUrl);

      expect(validCookies).toHaveLength(1);
      expect(validCookies[0]!.name).toBe('cookie1');
    });

    test('should filter out cookies with invalid paths', async () => {
      const cookies: Cookie[] = [
        {
          name: 'valid_path_cookie',
          value: 'value',
          domain: '.iracing.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
        {
          name: 'invalid_path_cookie',
          value: 'value',
          domain: '.iracing.com',
          path: '/wrong/path',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const validCookies = cookieStore.getValidCookiesForUrl(targetUrl);

      expect(validCookies).toHaveLength(1);
      expect(validCookies[0]!.name).toBe('valid_path_cookie');
    });

    test('should return empty array when no cookies are valid', async () => {
      const cookies: Cookie[] = [
        {
          name: 'invalid_cookie',
          value: 'value',
          domain: 'example.com',
          path: '/',
          expires: Date.now() / 1000 + 3600,
          httpOnly: true,
          secure: true,
          sameSite: 'Lax',
        },
      ];

      await cookieStore.write({ cookies, origins: [] });
      const validCookies = cookieStore.getValidCookiesForUrl(targetUrl);

      expect(validCookies).toHaveLength(0);
    });
  });
});