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

namespace Azaion.Flights.Services;

public class WaypointService(AppDataConnection db)
{
    public async Task<Waypoint> CreateWaypoint(Guid flightId, CreateWaypointRequest request)
    {
        var flightExists = await db.Flights.AnyAsync(f => f.Id == flightId);
        if (!flightExists)
            throw new KeyNotFoundException($"Flight {flightId} not found");

        var waypoint = new Waypoint
        {
            Id = Guid.NewGuid(),
            FlightId = flightId,
            Lat = request.GeoPoint?.Lat,
            Lon = request.GeoPoint?.Lon,
            Mgrs = request.GeoPoint?.Mgrs,
            WaypointSource = request.WaypointSource,
            WaypointObjective = request.WaypointObjective,
            OrderNum = request.OrderNum,
            Height = request.Height
        };
        await db.InsertAsync(waypoint);
        return waypoint;
    }

    public async Task<Waypoint> UpdateWaypoint(Guid flightId, Guid waypointId, UpdateWaypointRequest request)
    {
        var waypoint = await db.Waypoints.FirstOrDefaultAsync(w => w.FlightId == flightId && w.Id == waypointId)
            ?? throw new KeyNotFoundException($"Waypoint {waypointId} not found");

        waypoint.Lat = request.GeoPoint?.Lat;
        waypoint.Lon = request.GeoPoint?.Lon;
        waypoint.Mgrs = request.GeoPoint?.Mgrs;
        waypoint.WaypointSource = request.WaypointSource;
        waypoint.WaypointObjective = request.WaypointObjective;
        waypoint.OrderNum = request.OrderNum;
        waypoint.Height = request.Height;

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

    public async Task<List<Waypoint>> GetWaypoints(Guid flightId)
    {
        return await db.Waypoints
            .Where(w => w.FlightId == flightId)
            .OrderBy(w => w.OrderNum)
            .ToListAsync();
    }

    public async Task DeleteWaypoint(Guid flightId, Guid waypointId)
    {
        var waypoint = await db.Waypoints.FirstOrDefaultAsync(w => w.FlightId == flightId && w.Id == waypointId)
            ?? throw new KeyNotFoundException($"Waypoint {waypointId} not found");

        var mediaIds = await db.Media.Where(m => m.WaypointId == waypointId).Select(m => m.Id).ToListAsync();
        if (mediaIds.Count > 0)
        {
            var annotationIds = await db.Annotations.Where(a => mediaIds.Contains(a.MediaId))
                .Select(a => a.Id).ToListAsync();
            if (annotationIds.Count > 0)
                await db.Detections.DeleteAsync(d => annotationIds.Contains(d.AnnotationId));
            await db.Annotations.DeleteAsync(a => mediaIds.Contains(a.MediaId));
        }
        await db.Media.DeleteAsync(m => m.WaypointId == waypointId);
        await db.GpsCorrections.DeleteAsync(g => g.WaypointId == waypointId);
        await db.Waypoints.DeleteAsync(w => w.Id == waypointId);
    }
}
