using System.Runtime.CompilerServices;
using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using ms_lesService.Database;
using ms_lesService.Database.Models;
using ms_lesService.Mapping;

namespace ms_lesService.Objects;

/// <summary>
/// A class for saving LogSource data to the database.
/// </summary>
public class DatabaseSave
{
    /// <summary>
    /// Represents the logger instance for this class.
    /// </summary>
    private static ILogger Logger = Logging.LoggerFactory.CreateLogger<DatabaseSave>();

    /// <summary>
    /// Configuration to get the database connection string.
    /// </summary>
    private static IConfigurationRoot Configuration = new ConfigurationBuilder()
        .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
        .AddJsonFile("appsettings.json", true, true)
        .Build();

    /// <summary>
    /// Setting the database connection.
    /// </summary>
    private static DbContextOptionsBuilder<RulesContext> OptionsBuilder =
        new DbContextOptionsBuilder<RulesContext>().UseNpgsql(Configuration.GetConnectionString("Database"));

    /// <summary>
    /// DbContext class instance for the database communication
    /// </summary>
    private static RulesContext Context = new(OptionsBuilder.Options);


    /// <summary>
    /// Saves a LogSource object to the database.
    /// </summary>
    /// <param name="logSource">The LogSource object to be saved.</param>
    public static void SaveLogSource(LogSource logSource)
    {
        //Prevent saving duplicates (LESes are often repeated)
        LesType existingLesType = Context.LesTypes.FirstOrDefault(lt => lt.Type == logSource.Name);

        //Creating a log source objects to store in the database, if nothing is found
        if (existingLesType == null)
        {
            //Name = Type, different terminology is used in the program and in the database!
            LesType lesType = new LesType()
            {
                Type = logSource.Name //e.g. Linux, Windows, etc.
            };
            LesTypesCategory lesTypesCategory = new LesTypesCategory()
            {
                LesType = lesType,
                Category = logSource.Type, //OS/SA/OA/ND
                ShortCategory = GetShortCategory(logSource.Type) //abbreviated name, e.g. lin, win...
            };
            Les les = new Les()
            {
                LesType = lesType
            };

            //Saving into database
            Context.LesTypes.Add(lesType);
            Context.LesTypesCategories.Add(lesTypesCategory);
            Context.Leses.Add(les);
            
            Logger.LogInformation("Data saved: " + JsonSerializer.Serialize(logSource)); //Log
            Context.SaveChanges(); 
        }
        else
        {
            //Log Information
            Logger.LogInformation("Database already contains the data: " + JsonSerializer.Serialize(logSource));
        }
    }
    
    /// <summary>
    /// Returns the short category of log source type.
    /// </summary>
    /// <param name="type">The type string to get the short category code for.</param>
    /// <returns>A string representing the short category code for the given type string.</returns>
    private static string GetShortCategory(string type)
    {
        string shortCategory = string.Empty;
        switch (type)
        {
            case "Operating System":
                shortCategory = "os";
                break;
            case "Security Application":
                shortCategory = "sa";
                break;
            case "Other Application":
                shortCategory = "oa";
                break;
            case "Network Device":
                shortCategory = "nd";
                break;
            default:
                shortCategory = "oth";
                break;
        }

        return shortCategory;
    }
}