using Azaion.Flights.Database;
using Azaion.Flights.Database.Entities;
using Azaion.Flights.DTOs;

namespace Azaion.Flights.Services;

public class AircraftService(AppDataConnection db)
{
    public async Task<Aircraft> CreateAircraft(CreateAircraftRequest request)
    {
        if (request.IsDefault)
            await db.Aircrafts.Where(a => a.IsDefault).Set(a => a.IsDefault, false).UpdateAsync();

        var aircraft = new Aircraft
        {
            Id = Guid.NewGuid(),
            Type = request.Type,
            Model = request.Model,
            Name = request.Name,
            FuelType = request.FuelType,
            BatteryCapacity = request.BatteryCapacity,
            EngineConsumption = request.EngineConsumption,
            EngineConsumptionIdle = request.EngineConsumptionIdle,
            IsDefault = request.IsDefault
        };
        await db.InsertAsync(aircraft);
        return aircraft;
    }

    public async Task<Aircraft> UpdateAircraft(Guid id, UpdateAircraftRequest request)
    {
        var aircraft = await db.Aircrafts.FirstOrDefaultAsync(a => a.Id == id)
            ?? throw new KeyNotFoundException($"Aircraft {id} not found");

        if (request.Type.HasValue)
            aircraft.Type = request.Type.Value;
        if (request.Model != null)
            aircraft.Model = request.Model;
        if (request.Name != null)
            aircraft.Name = request.Name;
        if (request.FuelType.HasValue)
            aircraft.FuelType = request.FuelType.Value;
        if (request.BatteryCapacity.HasValue)
            aircraft.BatteryCapacity = request.BatteryCapacity.Value;
        if (request.EngineConsumption.HasValue)
            aircraft.EngineConsumption = request.EngineConsumption.Value;
        if (request.EngineConsumptionIdle.HasValue)
            aircraft.EngineConsumptionIdle = request.EngineConsumptionIdle.Value;
        if (request.IsDefault.HasValue)
        {
            if (request.IsDefault.Value)
                await db.Aircrafts.Where(a => a.IsDefault).Set(a => a.IsDefault, false).UpdateAsync();
            aircraft.IsDefault = request.IsDefault.Value;
        }

        await db.UpdateAsync(aircraft);
        return aircraft;
    }

    public async Task<Aircraft> GetAircraft(Guid id)
    {
        var aircraft = await db.Aircrafts.FirstOrDefaultAsync(a => a.Id == id)
            ?? throw new KeyNotFoundException($"Aircraft {id} not found");
        return aircraft;
    }

    public async Task<List<Aircraft>> GetAircrafts(GetAircraftsQuery query)
    {
        var q = db.Aircrafts.AsQueryable();

        if (!string.IsNullOrEmpty(query.Name))
            q = q.Where(a => a.Name.ToLower().Contains(query.Name.ToLower()));
        if (query.IsDefault.HasValue)
            q = q.Where(a => a.IsDefault == query.IsDefault.Value);

        return await q.OrderBy(a => a.Name).ToListAsync();
    }

    public async Task DeleteAircraft(Guid id)
    {
        var hasFlights = await db.Flights.AnyAsync(f => f.AircraftId == id);
        if (hasFlights)
            throw new InvalidOperationException($"Aircraft {id} is referenced by flights");

        var aircraft = await db.Aircrafts.FirstOrDefaultAsync(a => a.Id == id)
            ?? throw new KeyNotFoundException($"Aircraft {id} not found");

        await db.Aircrafts.DeleteAsync(a => a.Id == id);
    }

    public async Task SetDefault(Guid id, SetDefaultRequest request)
    {
        var aircraft = await db.Aircrafts.FirstOrDefaultAsync(a => a.Id == id)
            ?? throw new KeyNotFoundException($"Aircraft {id} not found");

        if (request.IsDefault)
            await db.Aircrafts.Where(a => a.IsDefault).Set(a => a.IsDefault, false).UpdateAsync();

        aircraft.IsDefault = request.IsDefault;
        await db.UpdateAsync(aircraft);
    }
}
