using e_suite.API.Common;
using e_suite.API.Common.extensions;
using e_suite.Database.Audit;
using e_suite.Service.SigmaImporter.Helpers;
using e_suite.Service.SigmaImporter.Repository;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using e_suite.API.Common.exceptions;
using e_suite.Service.SigmaImporter.Extensions;
using e_suite.API.Common.models;
using eSuite.Core.Clock;

namespace e_suite.Service.SigmaImporter.PrintSpecifications;

public partial class PrintSpecificationImporter : IPrintSpecificationImporter
{
    private readonly IImportGlossaryHelper _importGlossaryHelper;
    private readonly IImportCustomFieldHelper _importCustomFieldHelper;
    private readonly IFormsManager _formsManager;
    private readonly IConfiguration _configuration;
    private readonly ILogger _logger;
    private readonly ISigmaFtpuRepository _sigmaFtpuRepository;
    private readonly ISigmaFileBrowserRepository _sigmaFileBrowserURepository;
    private readonly ISpecificationManager _specificationManager;
    private readonly ISiteManager _siteManager;
    private readonly IGlossariesManager _glossariesManager;
    private readonly IOrganisationsManager _organisationsManager;
    private readonly ISigmaAirlockRepository _airlockRepository;
    private readonly ISigmaRepository _sigmaRepository;
    private readonly IDomainManager _domainManager;
    private readonly IEFlowSync _eFlowSync;
    private readonly IClock _clock;

    public PrintSpecificationImporter(IImportGlossaryHelper importGlossaryHelper,
        IImportCustomFieldHelper importCustomFieldHelper, IFormsManager formsManager, IConfiguration configuration, ILogger logger, ISigmaFtpuRepository sigmaFtpuRepository, ISpecificationManager specificationManager, ISiteManager siteManager, ISigmaFileBrowserRepository sigmaFileBrowserURepository, IGlossariesManager glossariesManager, IOrganisationsManager organisationsManager, ISigmaAirlockRepository airlockRepository, ISigmaRepository sigmaRepository, IDomainManager domainManager, IEFlowSync eFlowSync, IClock clock)
    {
        _importGlossaryHelper = importGlossaryHelper;
        _importCustomFieldHelper = importCustomFieldHelper;
        _formsManager = formsManager;
        _configuration = configuration;
        _logger = logger;
        _sigmaFtpuRepository = sigmaFtpuRepository;
        _specificationManager = specificationManager;
        _siteManager = siteManager;
        _sigmaFileBrowserURepository = sigmaFileBrowserURepository;
        _glossariesManager = glossariesManager;
        _organisationsManager = organisationsManager;
        _airlockRepository = airlockRepository;
        _sigmaRepository = sigmaRepository;
        _domainManager = domainManager;
        _eFlowSync = eFlowSync;
        _clock = clock;
    }

    public async Task DoPrintSpecificationImport(AuditUserDetails auditUserDetails)
    {
        var server = _configuration.GetConfigValue($"SigmaFTPU_SERVER", $"SigmaFTPU:Server", "");
        if (string.IsNullOrWhiteSpace(server))
        {
            _logger.LogInformation("SigmaFTPU_SERVER is not set, skipping import");
            //System is not setup to connect to the mySql database, data import cannot take place.
            return;
        }

        await MakeSureSystemGlossariesAreCreated(auditUserDetails);
        await MakeSureCustomFieldsAreCreated(auditUserDetails);
        await MakeSureSigmaOrganisationExists(auditUserDetails);
        var specificationFormTemplate = await MakeSurePrintSpecCustomFormCreated(auditUserDetails);
        await PrepareSupplyMethodsDictionary();
        await PrepareGmgProfileDictionary(auditUserDetails);
        var eSuiteDomains = await ImportDomains(auditUserDetails);
        await ImportPrintSpecifications(auditUserDetails, specificationFormTemplate, eSuiteDomains);
        await _eFlowSync.SyncEFlowPrinterCategories([]);
    }

    private readonly Dictionary<string, CustomFieldValue> _supplyMethods = [];

    private Task PrepareSupplyMethodsDictionary()
    {
        if (_supplyMethods.Count == 0)
        {
            _supplyMethods.Add("pdf", new CustomFieldValue { Value = PdfGuid.ToGeneralIdRef().ToJson(), DisplayValue = "PDF" });
            _supplyMethods.Add("illustrator", new CustomFieldValue{ Value = IllustratorGuid.ToGeneralIdRef().ToJson(), DisplayValue = "Illustrator" });
            _supplyMethods.Add("esko", new CustomFieldValue { Value = EskoGuid.ToGeneralIdRef().ToJson(), DisplayValue = "Esko" });
            _supplyMethods.Add("artpro", new CustomFieldValue { Value = ArtProGuid.ToGeneralIdRef().ToJson(), DisplayValue = "ArtPro" });
        }

        return Task.CompletedTask;
    }


    private readonly Dictionary<string, CustomFieldValue> _printProcessDictionary = [];

    private async Task PrepareProcessDictionary(AuditUserDetails auditUserDetails, List<SigmaPrintSpecification> printSpecifications)
    {
        var printProcessGlossaryGeneralIdRef = _printProcessGlossaryGuid.ToGeneralIdRef();
        var printProcessGlossary = await _glossariesManager.GetGlossaryItem(auditUserDetails, printProcessGlossaryGeneralIdRef, CancellationToken.None);
        AddItemsToPrintProcessDictionary(printProcessGlossary!);

        var newProcesses = new List<NewGlossaryItem>();
        foreach (var printSpecification in printSpecifications)
        {
            if (!string.IsNullOrWhiteSpace(printSpecification.Process) && !_printProcessDictionary.ContainsKey(printSpecification.Process.ToLowerInvariant().Trim()))
            {
                var newProcess = new NewGlossaryItem
                {
                    Name = printSpecification.Process.Trim(),
                    Guid = Guid.NewGuid(),
                    Parent = printProcessGlossaryGeneralIdRef
                };
                newProcesses.Add(newProcess);
                _printProcessDictionary.Add(newProcess.Name.ToLowerInvariant().Trim(), new CustomFieldValue
                {
                    DisplayValue = newProcess.Name,
                    Value = newProcess.Guid!.Value.ToGeneralIdRef().ToJson()
                });
            }
        }

        await _glossariesManager.AddGlossaryItems(auditUserDetails, newProcesses, CancellationToken.None);
    }

    private void AddItemsToPrintProcessDictionary(GlossaryItem items)
    {
        foreach (var printProcessItem in items.Children!)
        {
            if (!_printProcessDictionary.ContainsKey(printProcessItem.Name.ToLowerInvariant().Trim()))
            {
                _printProcessDictionary.Add(printProcessItem.Name.ToLowerInvariant().Trim(), new CustomFieldValue
                {
                    DisplayValue = printProcessItem.Name,
                    Value = printProcessItem.Guid.ToGeneralIdRef().ToJson()
                });
            }
        }
    }
    
    public readonly Guid GmgProfileGuid = new("BBA078CF-8326-40B8-92EC-ECD9A2017702");
    private readonly Dictionary<long, CustomFieldValue>  _gmgProfileDictionary = [];

    private async Task PrepareGmgProfileDictionary(AuditUserDetails auditUserDetails)
    {
        var glossaryGeneralIdRef = GmgProfileGuid.ToGeneralIdRef();
        var gmgProfileGlossaryItem =
            await _glossariesManager.GetGlossaryItem(auditUserDetails, glossaryGeneralIdRef, CancellationToken.None) ?? throw new NotFoundException("Unable to find GMG Profile glossary");

        var gmgProfiles = (await _sigmaFileBrowserURepository.GetActiveGmgProfiles()).ToList();

        foreach (var gmgProfile in gmgProfiles)
        {
            var existingGmgProfileItem = gmgProfileGlossaryItem.Children?.Single(x => x.Name == gmgProfile.CompiledName) ?? throw new NotFoundException();

            if (!_gmgProfileDictionary.ContainsKey(gmgProfile.Id))
            {
                _gmgProfileDictionary.Add(gmgProfile.Id, new CustomFieldValue
                {
                    DisplayValue = existingGmgProfileItem!.Name,
                    Value = existingGmgProfileItem!.Guid.ToGeneralIdRef().ToJson()
                });
            }
        }
    }
}