using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OpenWarehouse.warehouse.api.Common.Producer;
using OpenWarehouse.warehouse.api.Model.Producer;

namespace OpenWarehouse.warehouse.api.Controller;

[ApiController]
[Route("[controller]/[action]")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class Producer(ILogger<Producer> logger, IProducerManager producerManager) : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> CreateProducer([FromBody] Model.Producer.Producer? producer)
    {
        if (producer == null)
        {
            logger.LogWarning("Received null producer in CreateProducer");
            return BadRequest();
        }

        var newProducer = new Data.Producers()
        {
            FiestLineAdress = producer.FirstLineAddress,
            SecondLineAdress = producer.SecondLineAddress,
            Name = producer.Name,
            Email = producer.Email,
            Phone = producer.PhoneNumber
        };

        var res = await producerManager.CreateAsync(newProducer);

        if (!res.IsSuccess)
        {
            logger.LogError("Failed to create producer: {Errors}", res.Errors);
            return BadRequest(res.Errors);
        }

        logger.LogInformation("Producer created successfully: {ProducerName}", producer.Name);
        return Ok();
    }

    [HttpGet("{name}")]
    public async Task<ActionResult<Model.Producer.Producer>> GetProducer([FromRoute] string name)
    {
        logger.LogInformation("Fetching producer with name: {Name}", name);

        var res = await producerManager.FindProducerByName(name);

        if (res == null)
        {
            logger.LogWarning("Producer not found with name: {Name}", name);
            return NotFound();
        }

        var processedRes = new Model.Producer.Producer
        {
            Name = res.Name,
            Email = res.Email,
            PhoneNumber = res.Phone,
            FirstLineAddress = res.FiestLineAdress,
            SecondLineAddress = res.SecondLineAdress,
            Claims = res.Claims?.Select(q => q as ClaimBase).ToList(),
        };

        logger.LogInformation("Producer fetched successfully: {Name}", name);
        return Ok(processedRes);
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<Model.Producer.Producer>>> GetProducers()
    {
        logger.LogInformation("Fetching list of producers");

        var res = await producerManager.GetProducerList();

        var processedRes = res.Select(producer => new Model.Producer.Producer
        {
            Name = producer.Name,
            Email = producer.Email,
            PhoneNumber = producer.Phone,
            FirstLineAddress = producer.FiestLineAdress,
            SecondLineAddress = producer.SecondLineAdress,
            Claims = producer.Claims?.Select(q => q as ClaimBase).ToList(),
        }).ToList();

        logger.LogInformation("Fetched {Count} producers", processedRes.Count);
        return Ok(processedRes);
    }

    [HttpDelete]
    public async Task<IActionResult> DeleteProducerByName([FromBody] string name)
    {
        logger.LogInformation("Deleting producer with name: {Name}", name);

        var res = await producerManager.DeleteProducerByName(name);

        if (!res)
        {
            logger.LogWarning("Failed to delete producer: {Name}", name);
            return NotFound();
        }

        logger.LogInformation("Deleted producer successfully: {Name}", name);
        return Ok();
    }

    [HttpPost]
    public async Task<ActionResult<int>> UpdateProducerClaim([FromBody] UpdateClaimRequest request)
    {
        logger.LogInformation("Updating claims for producer");

        int result = 0;
        Producers? producers;

        if (request.Id != null)
        {
            producers = await producerManager.FindProducerById(request.Id);
        }
        else if (request.Name != null)
        {
            producers = await producerManager.FindProducerByName(request.Name);
        }
        else
        {
            logger.LogWarning("Invalid request: both Id and Name are null");
            return BadRequest();
        }

        if (producers == null)
        {
            logger.LogWarning("Producer not found during claim update");
            return NotFound();
        }

        foreach (var claim in request.ListOfUpdateClaim)
        {
            if (claim.ClaimType == null) continue;

            if (claim.ClaimValue == null)
            {
                var resultOperation = await producerManager.DeleteClaim(producers, claim.ClaimType);

                if (resultOperation.IsSuccess)
                {
                    result++;
                }
                else
                {
                    logger.LogWarning("Failed to delete claim: {ClaimType}", claim.ClaimType);
                }
            }
            else
            {
                var resultOperation = await producerManager.UpdateClaim(producers,
                    new Claim(claim.ClaimType, claim.ClaimValue, claim.ClaimIssuer));

                if (resultOperation.IsSuccess)
                {
                    result++;
                }
                else
                {
                    logger.LogWarning("Failed to update claim: {ClaimType}", claim.ClaimType);
                }
            }
        }

        logger.LogInformation("Claims updated successfully. Total updated: {Count}", result);
        return result > 0 ? Ok(result) : BadRequest();
    }
}
