/**
 * TDD Tests for MediaResolverAdapter and its components
 * 
 * Tests the complete resolution flow for all media reference types
 */

import { MediaReference } from '@core/domain/media/MediaReference';
import { describe, expect, it } from 'vitest';
import { DefaultResolvers, MediaResolverAdapter } from './MediaResolverAdapter';
import { DefaultMediaResolverAdapter } from './resolvers/DefaultMediaResolverAdapter';
import { GeneratedMediaResolverAdapter } from './resolvers/GeneratedMediaResolverAdapter';
import { UploadedMediaResolverAdapter } from './resolvers/UploadedMediaResolverAdapter';

describe('DefaultMediaResolverAdapter', () => {
  const adapter = new DefaultMediaResolverAdapter();

  describe('System Default URLs', () => {
    it('should resolve avatar default without variant', async () => {
      const ref = MediaReference.createSystemDefault('avatar');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/default/neutral-default-avatar');
    });

    it('should resolve male avatar default', async () => {
      const ref = MediaReference.createSystemDefault('avatar', 'male');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/default/male-default-avatar');
    });

    it('should resolve female avatar default', async () => {
      const ref = MediaReference.createSystemDefault('avatar', 'female');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/default/female-default-avatar');
    });

    it('should resolve neutral avatar default', async () => {
      const ref = MediaReference.createSystemDefault('avatar', 'neutral');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/default/neutral-default-avatar');
    });

    it('should resolve team logo default', async () => {
      const ref = MediaReference.createSystemDefault('logo');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/default/logo.png');
    });

    it('should resolve league logo default', async () => {
      const ref = MediaReference.createSystemDefault('logo');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/default/logo.png');
    });

    it('should return null for non-system-default references', async () => {
      const ref = MediaReference.createGenerated('team-123');
      const url = await adapter.resolve(ref);
      expect(url).toBeNull();
    });
  });
});

describe('GeneratedMediaResolverAdapter', () => {
  const adapter = new GeneratedMediaResolverAdapter();

  describe('Generated URLs', () => {
    it('should resolve team logo generated', async () => {
      const ref = MediaReference.createGenerated('team-123');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/teams/123/logo');
    });

    it('should resolve league logo generated', async () => {
      const ref = MediaReference.createGenerated('league-456');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/leagues/456/logo');
    });

    it('should resolve driver avatar generated', async () => {
      const ref = MediaReference.createGenerated('driver-789');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/avatar/789');
    });

    it('should handle complex type names with hyphens', async () => {
      const ref = MediaReference.createGenerated('team-league-123');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/teams/league-123/logo');
    });

    it('should return null for invalid format (no hyphen)', async () => {
      const ref = MediaReference.createGenerated('invalid');
      const url = await adapter.resolve(ref);
      expect(url).toBeNull();
    });

    it('should return null for non-generated references', async () => {
      const ref = MediaReference.createSystemDefault('avatar');
      const url = await adapter.resolve(ref);
      expect(url).toBeNull();
    });
  });
});

describe('UploadedMediaResolverAdapter', () => {
  const adapter = new UploadedMediaResolverAdapter();

  describe('Uploaded URLs', () => {
    it('should resolve uploaded media', async () => {
      const ref = MediaReference.createUploaded('media-123');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/uploaded/media-123');
    });

    it('should handle different media IDs', async () => {
      const ref = MediaReference.createUploaded('media-456');
      const url = await adapter.resolve(ref);
      expect(url).toBe('/media/uploaded/media-456');
    });

    it('should return null for non-uploaded references', async () => {
      const ref = MediaReference.createSystemDefault('avatar');
      const url = await adapter.resolve(ref);
      expect(url).toBeNull();
    });
  });
});

describe('MediaResolverAdapter (Composite)', () => {
  const resolver = new MediaResolverAdapter();

  describe('Composite Resolution', () => {
    it('should resolve system-default references', async () => {
      const ref = MediaReference.createSystemDefault('avatar', 'male');
      const url = await resolver.resolve(ref);
      expect(url).toBe('/media/default/male-default-avatar');
    });

    it('should resolve generated references', async () => {
      const ref = MediaReference.createGenerated('team-123');
      const url = await resolver.resolve(ref);
      expect(url).toBe('/media/teams/123/logo');
    });

    it('should resolve uploaded references', async () => {
      const ref = MediaReference.createUploaded('media-456');
      const url = await resolver.resolve(ref);
      expect(url).toBe('/media/uploaded/media-456');
    });

    it('should return null for none references', async () => {
      const ref = MediaReference.createNone();
      const url = await resolver.resolve(ref);
      expect(url).toBeNull();
    });

    it('should return null for null/undefined input', async () => {
      expect(await resolver.resolve(null as unknown as MediaReference)).toBeNull();
      expect(await resolver.resolve(undefined as unknown as MediaReference)).toBeNull();
    });
  });

  describe('Factory Functions', () => {
    it('should create local resolver', () => {
      const local = DefaultResolvers.local();
      // Local resolver should work without baseUrl (path-only)
      expect(local).toBeInstanceOf(MediaResolverAdapter);
    });

    it('should create production resolver', () => {
      const prod = DefaultResolvers.production();
      // Production resolver should work without baseUrl (path-only)
      expect(prod).toBeInstanceOf(MediaResolverAdapter);
    });
  });
});

describe('Integration: End-to-End Resolution', () => {
  const resolver = new MediaResolverAdapter();

  it('should resolve all reference types consistently', async () => {
    const testCases = [
      {
        ref: MediaReference.createSystemDefault('avatar', 'male'),
        expected: '/media/default/male-default-avatar'
      },
      {
        ref: MediaReference.createSystemDefault('avatar', 'female'),
        expected: '/media/default/female-default-avatar'
      },
      {
        ref: MediaReference.createSystemDefault('logo'),
        expected: '/media/default/logo.png'
      },
      {
        ref: MediaReference.createGenerated('team-abc123'),
        expected: '/media/teams/abc123/logo'
      },
      {
        ref: MediaReference.createGenerated('league-def456'),
        expected: '/media/leagues/def456/logo'
      },
      {
        ref: MediaReference.createUploaded('media-ghi789'),
        expected: '/media/uploaded/media-ghi789'
      },
      {
        ref: MediaReference.createNone(),
        expected: null
      }
    ];

    for (const testCase of testCases) {
      const result = await resolver.resolve(testCase.ref);
      expect(result).toBe(testCase.expected);
    }
  });

  it('should maintain URL consistency across multiple resolutions', async () => {
    const ref = MediaReference.createGenerated('team-123');
    
    const url1 = await resolver.resolve(ref);
    const url2 = await resolver.resolve(ref);
    const url3 = await resolver.resolve(ref);
    
    expect(url1).toBe(url2);
    expect(url2).toBe(url3);
    expect(url1).toBe('/media/teams/123/logo');
  });
});