using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using OI.Metrology.Server.Models;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System.Net;

namespace OI.Metrology.Server.ApiControllers;

[ApiController]
[Route("api/[controller]")]
public partial class InboundController : ControllerBase, IInboundController<IActionResult>
{

    private readonly ILogger _Logger;
    private readonly AppSettings _AppSettings;
    private readonly IInboundRepository _InboundRepository;
    private readonly IAttachmentsService _AttachmentsService;
    private readonly IInboundDataService _InboundDataService;
    private readonly IMetrologyRepository _MetrologyRepository;

    public InboundController(AppSettings appSettings, ILogger<InboundController> logger, IMetrologyRepository metrologyRepository, IInboundRepository inboundRepository, IInboundDataService inboundDataService, IAttachmentsService attachmentsService)
    {
        _Logger = logger;
        _AppSettings = appSettings;
        _InboundRepository = inboundRepository;
        _AttachmentsService = attachmentsService;
        _InboundDataService = inboundDataService;
        _MetrologyRepository = metrologyRepository;
    }

    private static string? GetJson(Stream stream)
    {
        string? result;
        if (!stream.CanRead)
            result = null;
        else
        {
            Task<string> task = new StreamReader(stream).ReadToEndAsync();
            result = task.Result;
        }
        return result;
    }

    private static JToken GetJToken(Stream stream)
    {
        string? json = GetJson(stream);
        JToken jsonbody = string.IsNullOrEmpty(json) ? JToken.Parse("{}") : JToken.Parse(json);
        return jsonbody;
    }

    [HttpPost]
    [Route("{tooltype}")]
    public IActionResult Post(string tooltype)
    {
        IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress;
        if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP))
        {
            _Logger.LogInformation($"Rejected remote IP: {remoteIP}");
            return Unauthorized("Remote IP is not on allowed list");
        }
        else
        {
            JToken jsonbody = GetJToken(Request.Body);
            DataResponse dataResponse = _InboundRepository.Data(_MetrologyRepository, _InboundDataService, tooltype, jsonbody);
            if (!dataResponse.Errors.Any())
                return Ok(dataResponse);
            else
                return BadRequest(dataResponse);
        }
    }

    [HttpPost]
    [Route("{tooltype}/attachment")]
    public IActionResult AttachFile(string tooltype, [FromQuery] long headerid, [FromQuery] string datauniqueid = "")
    {
        IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress;
        if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP))
        {
            _Logger.LogInformation($"Rejected remote IP: {remoteIP}");
            return Unauthorized("Remote IP is not on allowed list");
        }
        else
        {
            if (Request.Form is null)
                return BadRequest($"Invalid form");
            if (Request.Form.Files.Count != 1)
                return BadRequest($"Invalid file count");
            IFormFile formFile = Request.Form.Files[0];
            string? message = _InboundRepository.AttachFile(_MetrologyRepository, _AttachmentsService, tooltype, headerid, datauniqueid, formFile.FileName, formFile);
            if (message is null)
                return Ok();
            else
                return BadRequest(message);
        }
    }

}