namespace DatabaseUpdater;

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using Insite.Common;
using Insite.Common.Logging;
using Insite.Core.BootStrapper;
using Insite.Data;
using Insite.Public.Core.Extensions;
using log4net.Config;
using Newtonsoft.Json;

internal class DatabaseUpdater
{
    public static void Main()
    {
        XmlConfigurator.Configure(new FileInfo("log4net.config"));

#if NET6_0_OR_GREATER
        DotNetEnv.Env.NoClobber().TraversePath().Load();

        var connectionStringName = "DB_CONNECTION_STRING";
        var extensionsConnectionStringName = "EXTENSIONS_DB_CONNECTION_STRING";
#else
        var connectionStringName = "Insite.Commerce";
        var extensionsConnectionStringName = "Insite.Commerce.Extensions";
#endif

        var connectionString = Environment.GetEnvironmentVariable(connectionStringName);
        var extensionsConnectionString = Environment.GetEnvironmentVariable(
            extensionsConnectionStringName
        );

        if (connectionString.IsBlank())
        {
            throw new Exception(
                $"An environment variable named '{connectionStringName}' is required"
            );
        }

        if (extensionsConnectionString.IsBlank())
        {
            throw new Exception(
                $"An environment variable named '{extensionsConnectionStringName}' is required"
            );
        }

        LogHelper
            .For(typeof(DatabaseUpdater))
            .Info("Using a connection string of " + connectionString);

        try
        {
            // ensure we load Insite.Data
            _ = typeof(DataProviderConfiguration).Assembly;

            // ensure we load Extensions.dll
            var extensionsFile = Directory
                .GetFiles(
                    AppDomain.CurrentDomain.BaseDirectory,
                    "*.dll",
                    SearchOption.TopDirectoryOnly
                )
                .FirstOrDefault(o => Path.GetFileName(o).EqualsIgnoreCase("Extensions.dll"));

            if (extensionsFile != null)
            {
                Assembly.LoadFile(extensionsFile);
            }

            var connectionStringProvider = new DbUpdaterPrivateConnectionStringProvider(
                connectionString,
                extensionsConnectionString
            );

            AssemblyLocator.LoadAssemblies();

            Console.WriteLine("Using " + connectionString);

            if (
                Environment.GetEnvironmentVariable("MigrateAwayFromBinaryFormatter")?.ToLower()
                is "1"
                    or "true"
            )
            {
                // this was our first attempt to move away from binary data but it included type information in the json
                // which would be specific to netframework/net8
                Console.WriteLine("Only Binary!");
                UpdateClassicData.MigrateAwayFromBinaryFormatter(connectionString, true);
            }
            else
            {
                // this was our first attempt to move away from binary data but it included type information in the json
                // which would be specific to netframework/net8
                UpdateClassicData.MigrateAwayFromBinaryFormatter(connectionString);
                // this changes that typed json into non-typed json which goes along with base code changes to
                // deal with the untyped json
                UpdateClassicData.MigrateAwayFromTypedJson(connectionString);

                RunDatabaseScripts.Run(
                    connectionStringProvider,
                    connectionStringProvider,
                    AssemblyLocator.GetAssemblyProvider(),
                    new DatabaseScriptsOptions()
                );
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            LogHelper
                .For(typeof(DatabaseUpdater))
                .Error("Unhandled exception while running database scripts", ex);
            Environment.ExitCode = 1;
        }
    }
}
