/**
 * @ai-summary Unit tests for MaintenanceService
 * @ai-context Tests business logic with mocked dependencies
 */

import * as fixtures from '../fixtures/maintenance.fixtures.json';

describe('MaintenanceService', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('createMaintenanceRecord', () => {
    it('should create maintenance record with valid data', async () => {
      const validMaintenance = fixtures.validMaintenanceOilChange;

      expect(validMaintenance).toHaveProperty('vehicleId');
      expect(validMaintenance).toHaveProperty('type');
      expect(validMaintenance).toHaveProperty('category');
      expect(validMaintenance.cost).toBeGreaterThan(0);
    });

    it('should validate category against allowed values', async () => {
      const validCategories = ['routine_maintenance', 'repair', 'performance_upgrade'];
      const validMaintenance = fixtures.validMaintenanceOilChange;

      expect(validCategories).toContain(validMaintenance.category);
    });

    it('should reject invalid category', async () => {
      const invalidMaintenance = fixtures.invalidMaintenanceInvalidCategory;

      expect(invalidMaintenance.category).not.toMatch(/routine_maintenance|repair|performance_upgrade/);
    });

    it('should allow null dueDate and dueMileage', async () => {
      const maintenanceWithoutDue = fixtures.maintenanceWithoutDueDate;

      expect(maintenanceWithoutDue.dueDate).toBeNull();
      expect(maintenanceWithoutDue.dueMileage).toBeNull();
    });
  });

  describe('updateMaintenanceRecord', () => {
    it('should update maintenance record details', async () => {
      const originalRecord = fixtures.validMaintenanceOilChange;
      const updatedData = {
        ...originalRecord,
        completedDate: '2024-01-20',
        completedMileage: 52000,
        isCompleted: true
      };

      expect(updatedData.isCompleted).toBe(true);
      expect(updatedData.completedDate).not.toBe(originalRecord.completedDate);
    });

    it('should mark maintenance as completed', async () => {
      const completedMaintenance = fixtures.validMaintenanceTireRotation;

      expect(completedMaintenance.isCompleted).toBe(true);
      expect(completedMaintenance.completedDate).not.toBeNull();
    });
  });

  describe('getMaintenanceSchedule', () => {
    it('should return upcoming maintenance for vehicle', async () => {
      const schedule = fixtures.maintenanceScheduleResponse;

      expect(schedule).toHaveProperty('id');
      expect(schedule).toHaveProperty('dueDate');
      expect(schedule).toHaveProperty('dueMileage');
      expect(schedule.isCompleted).toBe(false);
    });

    it('should identify overdue maintenance', async () => {
      const overdueMaintenance = fixtures.invalidMaintenancePastDueDate;
      const today = new Date();
      const dueDate = new Date(overdueMaintenance.dueDate);

      expect(dueDate.getTime()).toBeLessThan(today.getTime());
    });

    it('should group maintenance by category', async () => {
      const categories = {
        routine_maintenance: [fixtures.validMaintenanceOilChange],
        repair: [fixtures.validMaintenanceBrakeService],
        performance_upgrade: [fixtures.validMaintenanceUpgrade]
      };

      expect(Object.keys(categories)).toHaveLength(3);
    });
  });

  describe('getMaintenanceHistory', () => {
    it('should return completed maintenance records', async () => {
      const history = fixtures.maintenanceHistoryResponse;

      expect(Array.isArray(history)).toBe(true);
      expect(history.length).toBeGreaterThan(0);
      history.forEach(record => {
        expect(record).toHaveProperty('completedDate');
        expect(record.completedDate).not.toBeNull();
      });
    });

    it('should sort by completion date (newest first)', async () => {
      const history = fixtures.maintenanceHistoryResponse;

      for (let i = 0; i < history.length - 1; i++) {
        const current = new Date(history[i].completedDate);
        const next = new Date(history[i + 1].completedDate);
        expect(current.getTime()).toBeGreaterThanOrEqual(next.getTime());
      }
    });
  });

  describe('calculateMaintenanceCosts', () => {
    it('should sum total maintenance costs', async () => {
      const history = fixtures.maintenanceHistoryResponse;
      const totalCost = history.reduce((sum, record) => sum + record.cost, 0);

      expect(totalCost).toBeGreaterThan(0);
      expect(totalCost).toBe(385);
    });

    it('should calculate average maintenance cost', async () => {
      const history = fixtures.maintenanceHistoryResponse;
      const totalCost = history.reduce((sum, record) => sum + record.cost, 0);
      const averageCost = totalCost / history.length;

      expect(averageCost).toBeGreaterThan(0);
      expect(averageCost).toBeCloseTo(192.5, 1);
    });
  });

  describe('user ownership validation', () => {
    it('should enforce user ownership', async () => {
      const schedule = fixtures.maintenanceScheduleResponse;

      expect(schedule).toHaveProperty('userId');
      expect(schedule.userId).toBeDefined();
    });

    it('should enforce vehicle ownership', async () => {
      const maintenance = fixtures.validMaintenanceOilChange;

      expect(maintenance).toHaveProperty('vehicleId');
      expect(maintenance.vehicleId).toBeDefined();
    });
  });

  describe('maintenance type validation', () => {
    it('should validate maintenance type', async () => {
      const validTypes = [
        'oil_change',
        'tire_rotation',
        'brake_service',
        'exhaust_upgrade',
        'inspection'
      ];

      const testMaintenance = [
        fixtures.validMaintenanceOilChange,
        fixtures.validMaintenanceTireRotation,
        fixtures.validMaintenanceBrakeService,
        fixtures.validMaintenanceUpgrade,
        fixtures.maintenanceWithoutDueDate
      ];

      testMaintenance.forEach(m => {
        expect(validTypes).toContain(m.type);
      });
    });
  });
});
