using System.Text;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using DiunaBI.Infrastructure.Data;
using DiunaBI.Domain.Entities;

namespace DiunaBI.API.Controllers;

[ApiController]
[Route("[controller]")]
public class DataInboxController : Controller
{
    private readonly AppDbContext _db;
    private readonly IConfiguration _configuration;
    private readonly ILogger<DataInboxController> _logger;

    public DataInboxController(
        AppDbContext db,
        IConfiguration configuration,
        ILogger<DataInboxController> logger)
    {
        _db = db;
        _configuration = configuration;
        _logger = logger;
    }

    [HttpPut]
    [Route("Add/{apiKey}")]
    [AllowAnonymous]
    public IActionResult Add(string apiKey, [FromBody] DataInbox dataInbox)
    {
        if (apiKey != _configuration["apiKey"])
        {
            _logger.LogWarning("DataInbox: Unauthorized request - wrong apiKey for source {Source}", dataInbox.Source);
            return Unauthorized();
        }

        try
        {
            if (!Request.Headers.TryGetValue("Authorization", out var authHeader))
            {
                _logger.LogWarning("DataInbox: Unauthorized request - no authorization header for source {Source}", dataInbox.Source);
                return Unauthorized();
            }

            var credentialsArr = authHeader.ToString().Split(" ");
            if (credentialsArr.Length != 2)
            {
                _logger.LogWarning("DataInbox: Unauthorized request - wrong auth header format for source {Source}", dataInbox.Source);
                return Unauthorized();
            }

            var authValue = Encoding.UTF8.GetString(Convert.FromBase64String(credentialsArr[1]));
            var username = authValue.Split(':')[0];
            var password = authValue.Split(':')[1];
            if (username != _configuration["morska-user"] || password != _configuration["morska-pass"])
            {
                _logger.LogWarning("DataInbox: Unauthorized request - bad credentials for source {Source}", dataInbox.Source);
                return Unauthorized();
            }

            // check if datainbox.data is base64 encoded value
            if (!string.IsNullOrEmpty(dataInbox.Data) && !IsBase64String(dataInbox.Data))
            {
                _logger.LogWarning("DataInbox: Invalid data format - not base64 encoded for source {Source}", dataInbox.Source);
                return BadRequest("Invalid data format - not base64 encoded");
            }

            dataInbox.Id = Guid.NewGuid();
            dataInbox.CreatedAt = DateTime.UtcNow;
            _db.DataInbox.Add(dataInbox);
            _db.SaveChanges();

            _logger.LogInformation("DataInbox: Insert success for source {Source}, name {Name}", dataInbox.Source, dataInbox.Name);

            if (dataInbox.Name == "morska.d3.importer")
            {
                _logger.LogDebug("DataInbox: Detected morska.d3.importer - processing will be handled by AutoImport");
                // AutoImport będzie obsługiwać ten typ danych
            }

            return Ok();
        }
        catch (Exception e)
        {
            _logger.LogError(e, "DataInbox: Insert error for source {Source}, name {Name}", dataInbox.Source, dataInbox.Name);
            return BadRequest(e.ToString());
        }
    }

    [HttpGet]
    public IActionResult GetAll()
    {
        try
        {
            var dataInbox = _db.DataInbox.AsNoTracking().ToList();
            _logger.LogDebug("DataInbox: Retrieved {Count} records", dataInbox.Count);
            return Ok(dataInbox);
        }
        catch (Exception e)
        {
            _logger.LogError(e, "DataInbox: Error retrieving records");
            return BadRequest(e.ToString());
        }
    }

    // helpers
    private bool IsBase64String(string data)
    {
        if (string.IsNullOrEmpty(data))
        {
            return false;
        }
        try
        {
            var base64Bytes = Convert.FromBase64String(data);
            var utf8String = Encoding.UTF8.GetString(base64Bytes);
            var reEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(utf8String));
            return data.TrimEnd('=') == reEncoded.TrimEnd('=');
        }
        catch (FormatException)
        {
            return false;
        }
        catch (DecoderFallbackException)
        {
            return false;
        }
    }
}