import { describe, expect, it } from 'vitest';
import { RacingDomainInvariantError, RacingDomainValidationError } from '../errors/RacingDomainError';
import { DecalOverride } from '../value-objects/DecalOverride';
import { LiveryDecal } from '../value-objects/LiveryDecal';
import { DriverLivery } from './DriverLivery';

describe('DriverLivery', () => {
  const validProps = {
    id: 'livery-1',
    driverId: 'driver-1',
    gameId: 'game-1',
    carId: 'car-1',
    uploadedImageUrl: 'https://example.com/image.png',
  };

  describe('create', () => {
    it('should create a valid DriverLivery', () => {
      const livery = DriverLivery.create(validProps);

      expect(livery.id).toBe('livery-1');
      expect(livery.driverId.toString()).toBe('driver-1');
      expect(livery.gameId.toString()).toBe('game-1');
      expect(livery.carId.toString()).toBe('car-1');
      expect(livery.uploadedImageUrl.toString()).toBe('https://example.com/image.png');
      expect(livery.userDecals).toEqual([]);
      expect(livery.leagueOverrides).toEqual([]);
      expect(livery.isValidated()).toBe(false);
    });

    it('should throw error for invalid id', () => {
      expect(() => DriverLivery.create({ ...validProps, id: '' })).toThrow(RacingDomainValidationError);
    });

    it('should throw error for invalid driverId', () => {
      expect(() => DriverLivery.create({ ...validProps, driverId: '' })).toThrow(RacingDomainValidationError);
    });

    it('should throw error for invalid gameId', () => {
      expect(() => DriverLivery.create({ ...validProps, gameId: '' })).toThrow(RacingDomainValidationError);
    });

    it('should throw error for invalid carId', () => {
      expect(() => DriverLivery.create({ ...validProps, carId: '' })).toThrow(RacingDomainValidationError);
    });

    it('should throw error for invalid uploadedImageUrl', () => {
      expect(() => DriverLivery.create({ ...validProps, uploadedImageUrl: '' })).toThrow(RacingDomainValidationError);
    });
  });

  describe('addDecal', () => {
    it('should add a user decal', () => {
      const livery = DriverLivery.create(validProps);
      const decal = LiveryDecal.create({
        id: 'decal-1',
        imageUrl: 'https://example.com/decal.png',
        x: 0.5,
        y: 0.5,
        width: 0.1,
        height: 0.1,
        zIndex: 1,
        type: 'user',
      });

      const updatedLivery = livery.addDecal(decal);

      expect(updatedLivery.userDecals).toHaveLength(1);
      expect(updatedLivery.userDecals[0]).toBe(decal);
      expect(updatedLivery.updatedAt).toBeInstanceOf(Date);
    });

    it('should throw error for non-user decal', () => {
      const livery = DriverLivery.create(validProps);
      const decal = LiveryDecal.create({
        id: 'decal-1',
        imageUrl: 'https://example.com/decal.png',
        x: 0.5,
        y: 0.5,
        width: 0.1,
        height: 0.1,
        zIndex: 1,
        type: 'sponsor',
      });

      expect(() => livery.addDecal(decal)).toThrow(RacingDomainInvariantError);
    });
  });

  describe('removeDecal', () => {
    it('should remove a decal', () => {
      const decal = LiveryDecal.create({
        id: 'decal-1',
        imageUrl: 'https://example.com/decal.png',
        x: 0.5,
        y: 0.5,
        width: 0.1,
        height: 0.1,
        zIndex: 1,
        type: 'user',
      });
      const livery = DriverLivery.create({ ...validProps, userDecals: [decal] });

      const updatedLivery = livery.removeDecal('decal-1');

      expect(updatedLivery.userDecals).toHaveLength(0);
    });

    it('should throw error if decal not found', () => {
      const livery = DriverLivery.create(validProps);

      expect(() => livery.removeDecal('nonexistent')).toThrow(RacingDomainValidationError);
    });
  });

  describe('updateDecal', () => {
    it('should update a decal', () => {
      const decal = LiveryDecal.create({
        id: 'decal-1',
        imageUrl: 'https://example.com/decal.png',
        x: 0.5,
        y: 0.5,
        width: 0.1,
        height: 0.1,
        zIndex: 1,
        type: 'user',
      });
      const livery = DriverLivery.create({ ...validProps, userDecals: [decal] });
      const updatedDecal = decal.moveTo(0.6, 0.6);

      const updatedLivery = livery.updateDecal('decal-1', updatedDecal);

      expect(updatedLivery.userDecals[0]).toBe(updatedDecal);
    });

    it('should throw error if decal not found', () => {
      const livery = DriverLivery.create(validProps);
      const decal = LiveryDecal.create({
        id: 'decal-1',
        imageUrl: 'https://example.com/decal.png',
        x: 0.5,
        y: 0.5,
        width: 0.1,
        height: 0.1,
        zIndex: 1,
        type: 'user',
      });

      expect(() => livery.updateDecal('nonexistent', decal)).toThrow(RacingDomainValidationError);
    });
  });

  describe('setLeagueOverride', () => {
    it('should add a league override', () => {
      const livery = DriverLivery.create(validProps);

      const updatedLivery = livery.setLeagueOverride('league-1', 'season-1', 'decal-1', 0.5, 0.5);

      expect(updatedLivery.leagueOverrides).toHaveLength(1);
      expect(updatedLivery.leagueOverrides[0]!.leagueId).toBe('league-1');
    });

    it('should update existing override', () => {
      const override = DecalOverride.create({
        leagueId: 'league-1',
        seasonId: 'season-1',
        decalId: 'decal-1',
        newX: 0.5,
        newY: 0.5,
      });
      const livery = DriverLivery.create({ ...validProps, leagueOverrides: [override] });

      const updatedLivery = livery.setLeagueOverride('league-1', 'season-1', 'decal-1', 0.6, 0.6);

      expect(updatedLivery.leagueOverrides).toHaveLength(1);
      expect(updatedLivery.leagueOverrides[0]!.newX).toBe(0.6);
    });
  });

  describe('removeLeagueOverride', () => {
    it('should remove a league override', () => {
      const override = DecalOverride.create({
        leagueId: 'league-1',
        seasonId: 'season-1',
        decalId: 'decal-1',
        newX: 0.5,
        newY: 0.5,
      });
      const livery = DriverLivery.create({ ...validProps, leagueOverrides: [override] });

      const updatedLivery = livery.removeLeagueOverride('league-1', 'season-1', 'decal-1');

      expect(updatedLivery.leagueOverrides).toHaveLength(0);
    });
  });

  describe('getOverridesFor', () => {
    it('should return overrides for league and season', () => {
      const override1 = DecalOverride.create({
        leagueId: 'league-1',
        seasonId: 'season-1',
        decalId: 'decal-1',
        newX: 0.5,
        newY: 0.5,
      });
      const override2 = DecalOverride.create({
        leagueId: 'league-1',
        seasonId: 'season-2',
        decalId: 'decal-2',
        newX: 0.6,
        newY: 0.6,
      });
      const livery = DriverLivery.create({ ...validProps, leagueOverrides: [override1, override2] });

      const overrides = livery.getOverridesFor('league-1', 'season-1');

      expect(overrides).toHaveLength(1);
      expect(overrides[0]).toBe(override1);
    });
  });

  describe('markAsValidated', () => {
    it('should mark livery as validated', () => {
      const livery = DriverLivery.create(validProps);

      const validatedLivery = livery.markAsValidated();

      expect(validatedLivery.isValidated()).toBe(true);
      expect(validatedLivery.validatedAt).toBeInstanceOf(Date);
    });
  });

  describe('isValidated', () => {
    it('should return false when not validated', () => {
      const livery = DriverLivery.create(validProps);

      expect(livery.isValidated()).toBe(false);
    });

    it('should return true when validated', () => {
      const livery = DriverLivery.create(validProps).markAsValidated();

      expect(livery.isValidated()).toBe(true);
    });
  });
});