using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json.Serialization;
using Yuna.Website.Server.Services.DeviceSkillService;
using Yuna.Website.Server.Services.DeviceService;
using Yuna.Website.Server.Model;
using System.Security.Claims;
using Yuna.Website.Server.Infrastructure;

namespace Yuna.Website.Server.API
{
    public class DeviceEndpoints
    {
        public void Define(WebApplication app)
        {
            app.MapPost("/api/device", CreateDevice)
                .WithTags("device");

            app.MapGet("/api/device/{deviceId:long}", GetById)
                .WithTags("device");

            app.MapGet("/api/device", GetAll)
                .WithTags("device");

            app.MapGet("/api/device/{deviceId:long}/fetch", FetchData)
                .WithTags("device")
                .Produces<string>(404)
                .Produces(200);

            app.MapPut("/api/device/{deviceId:long}", AddSkillsToDevice)
                .WithTags("device");

            app.MapPut("/api/device", Update)
                .WithTags("device");

            app.MapDelete("/api/device/{deviceId:long}", Delete)
                .WithTags("device");
        }


        public class CreateDeviceResult
        {
            [JsonPropertyName("name")]
            public string Name { get; set; } = null!;

            [JsonPropertyName("description")]
            public string Description { get; set; } = "";

            [JsonPropertyName("deviceUrl")]
            public string DeviceUrl { get; set; } = null!;

        }

        [Authorize]
        public async Task<IResult> CreateDevice([FromBody] CreateDeviceResult request, IDeviceService deviceService, HttpContext context)
        {

            var userId = context.GetUserIdFromCookie();
            if (userId is null) return Results.Unauthorized();

            var device = new Device()
            {
                Description = request.Description,
                DeviceUrl = request.DeviceUrl,
                Name = request.Name,
                UserId = (long)userId
            };

            var result = await deviceService.Create(device);
            if (result is null) return Results.BadRequest();


            return Results.Ok(result);
        }

        [Authorize]
        public async Task<IResult> GetById(long deviceId,IDeviceService deviceService)
        {
            var result = await deviceService.GetById(deviceId);

            if (result is null) return Results.NotFound(deviceId);

            return Results.Ok(result);
        }

        [Authorize]
        public async Task<IResult> GetAll(IDeviceService deviceService, HttpContext context)
        {

            var isAdmin = context.GetRoleFromCookie();
            if(isAdmin)
            {
                var adminResult = await deviceService.GetList();
                return Results.Ok(adminResult);
            }

            var userId = context.GetUserIdFromCookie();
            if (userId is null) return Results.Unauthorized();

            var result = await deviceService.GetList((long)userId);
            return Results.Ok(result);
        }

        [Authorize]
        public async Task<IResult> Delete(IDeviceService deviceService, HttpContext context, long deviceId)
        {
            var isAdmin = context.GetRoleFromCookie();
            var userId = context.GetUserIdFromCookie();

            var deviceToDelete = await deviceService.GetById(deviceId);
            if(deviceToDelete is null) return Results.NotFound();

            if (userId != deviceToDelete.UserId && !isAdmin) return Results.Forbid();

            var result = await deviceService.Delete(deviceId);
            if (result is null) return Results.Problem(statusCode: 500);
            return Results.Ok(result);
        }

        [Authorize]
        public async Task<IResult> AddSkillsToDevice([FromBody] long[] skillsIds, long deviceId, IDeviceService deviceService, IPropService skillService)
        {
            var skills = await skillService.GetByIds(skillsIds);
            if (skills is null) return Results.NotFound("not all skills exist");

            var result = await deviceService.AddProps(skills, deviceId);
            if (result is null) return Results.NotFound("device");
            return Results.Ok(result);
        }

        [Authorize]
        public async Task<IResult> FetchData(long deviceId, IDeviceService deviceService)
        {
            var device = await deviceService.GetById(deviceId);
            if (device is null) return Results.NotFound("device");


            var result = await deviceService.FetchPropsData(device);
            if (result is null) return Results.NotFound("props");

            return Results.Ok(result);
        }


        public class UpdateDeviceRequest
        {
            [JsonPropertyName("id")]
            public long Id { get; set; }

            [JsonPropertyName("name")]
            public string Name { get; set; } = null!;

            [JsonPropertyName("description")]
            public string Description { get; set; } = "";

            [JsonPropertyName("deviceUrl")]
            public string DeviceUrl { get; set; } = null!;
        }

        [Authorize]
        public async Task<IResult> Update([FromBody] UpdateDeviceRequest request, HttpContext context, IDeviceService deviceService)
        {
            var userId = context.GetUserIdFromCookie();
            var isAdmin = context.GetRoleFromCookie();

            var device = await deviceService.GetById(request.Id);
            
            if (device is null) return Results.NotFound();
            if (device.UserId != userId && !isAdmin) return Results.Forbid();

            device.DeviceUrl = request.DeviceUrl;
            device.Name = request.Name;
            device.Description = request.Description;

            var result = await deviceService.Update(device);
            return Results.Ok(result);
        }
    }
}
