using Newtonsoft.Json.Linq;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System.Net;

namespace OI.Metrology.Server.Repository;

public class InboundRepository : IInboundRepository
{

    private readonly Serilog.ILogger _Log;

    public InboundRepository() => _Log = Serilog.Log.ForContext<InboundRepository>();

    bool IInboundRepository.IsIPAddressAllowed(string inboundApiAllowedIPList, IPAddress? remoteIP)
    {
        if (string.IsNullOrWhiteSpace(inboundApiAllowedIPList))
            return true;
        if (remoteIP is null)
            return false;
        byte[] remoteIPBytes = remoteIP.GetAddressBytes();
        string[] allowedIPs = inboundApiAllowedIPList.Split(';');
        foreach (string ip in allowedIPs)
        {
            IPAddress? parsedIP;
            if (IPAddress.TryParse(ip, out parsedIP))
            {
                if (parsedIP.GetAddressBytes().SequenceEqual(remoteIPBytes))
                    return true;
            }
        }
        return false;
    }

    // this is the main endpoint, it accepts a JSON message that contains both the header and data records together
    // tooltype is the ToolTypeName column from the ToolType table
    // JToken is how you can accept a JSON message without deserialization.
    // Using "string" doesn't work because ASP.NET Core will expect a json encoded string, not give you the actual string.
    DataResponse IInboundRepository.Data(IMetrologyRepository metrologyRepository, IInboundDataService inboundDataService, string tooltype, JToken jsonbody)
    {
        DataResponse result = new();
        ToolType? toolType = metrologyRepository.GetToolTypeByName(tooltype);
        if (toolType is null)
            result.Errors.Add("Invalid tool type: " + tooltype);
        else
        {
            List<ToolTypeMetadata> metaData = metrologyRepository.GetToolTypeMetadataByToolTypeID(toolType.ID).ToList();
            if (metaData is null)
                result.Errors.Add("Invalid metadata for tool type: " + tooltype);
            else if (jsonbody is null)
                result.Errors.Add("Invalid json");
            else
                inboundDataService.ValidateJSONFields(jsonbody, 0, metaData, result.Errors, result.Warnings);
            if (metaData is not null && jsonbody is not null && !result.Errors.Any())
            {
                try
                {
                    result.HeaderID = inboundDataService.DoSQLInsert(jsonbody, toolType, metaData);
                    result.Success = result.HeaderID > 0;
                }
                catch (Exception ex) { result.Errors.Add(ex.Message); }
            }
        }
        return result;
    }

    // this is the endpoint for attaching a field.  It is not JSON, it is form-data/multipart like an HTML form because that's the normal way.
    // header ID is the ID value from the Header table
    // datauniqueid is the Title value from the Data/Detail table
    string? IInboundRepository.AttachFile(IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService, string tooltype, long headerid, string datauniqueid, string fileName, object uploadedFile)
    {
        string? result = null;
        ToolType toolType = metrologyRepository.GetToolTypeByName(tooltype);
        if (toolType is null)
            result = $"Invalid tool type: {tooltype}";
        string filename = Path.GetFileName(fileName);
        if (string.IsNullOrWhiteSpace(filename))
            result = "Empty filename";
        if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
            result = "Invalid filename";
        if (result is null && toolType is not null)
            attachmentsService.SaveAttachment(toolType, headerid, datauniqueid, filename, uploadedFile);
        return result;
    }

}