using e_suite.API.Common.repository;
using e_suite.Database.Audit;
using e_suite.Database.Audit.Models;
using e_suite.Database.Core.Extensions;
using e_suite.Database.Core.Helpers;
using e_suite.Database.Core.Tables.CustomFields;
using e_suite.Database.Core.Tables.Glossaries;
using e_suite.UnitTestCore;
using eSuite.Core.CustomFields;
using eSuite.Core.Miscellaneous;
using MockQueryable;
using System.Collections.ObjectModel;

namespace GlossariesManager.UnitTests.Repository;

public class FakeGlossariesManagerRepository : FakeRepository, IGlossariesManagerRepository
{
    public FakeGlossariesManagerRepository()
    {
        CustomFields =
        [
            new()
            {
                Id = 1,
                Name = "CustomField1",
                FieldType = FieldType.Text,
                Guid = new Guid("{AA4D6C9C-EFE5-495B-993E-97C977EDF9D7}")
            },

            new()
            {
                Id = 2,
                Name = "CustomField2",
                FieldType = FieldType.Text,
                Guid = new Guid("{67E85B6D-B25D-4AA7-8148-0B52BA694967}")
            }
        ];
    }

    public List<Glossary> Glossaries { get; set; } = [];
    public List<GlossaryCustomField> GlossaryCustomFields { get; set; } = [];
    public List<CustomField> CustomFields { get; set; }
    public List<GlossaryCustomFieldValue> GlossaryCustomFieldValues { get; set; } = [];

    public Task AddGlossaryItem(AuditUserDetails auditUserDetails, Glossary glossary, CancellationToken cancellationToken)
    {
        var items = new List<Glossary>
        {
            glossary
        };
        AddGlossaryItems(auditUserDetails, items, cancellationToken);

        return Task.CompletedTask;
    }

    public Task AddGlossaryItems(AuditUserDetails auditUserDetails, IEnumerable<Glossary> items, CancellationToken cancellationToken)
    {
        foreach( var glossary in items)
            Glossaries.Add(glossary);

        return Task.CompletedTask;
    }

    public async Task<Glossary?> GetParentGlossary(IGeneralIdRef? glossaryItemParent, CancellationToken cancellationToken)
    {
        if (glossaryItemParent == null)
            return null;

        return await FindGlossary(glossaryItemParent, cancellationToken);
    }

    public IQueryable<GlossaryCustomField> GetGlossaryCustomFields(long glossaryId)
    {
        return GlossaryCustomFields.BuildMock()
            .Where(x => x.GlossaryId == glossaryId);
    }

    public Task SaveChildCustomFieldDefinitions(AuditUserDetails auditUserDetails, IReadOnlyList<GlossaryCustomField> removalList,
        IReadOnlyList<GlossaryCustomField> additionList, CancellationToken cancellationToken)
    {
        foreach (var item in removalList)
            GlossaryCustomFields.Remove(item);

        foreach (var glossaryCustomField in additionList)
        {
            glossaryCustomField.Glossary ??= Glossaries.Single(x => x.Id == glossaryCustomField.GlossaryId);

            glossaryCustomField.CustomField ??= CustomFields.Single(x => x.Id == glossaryCustomField.CustomFieldId);

            GlossaryCustomFields.Add(glossaryCustomField);
        }

        return Task.CompletedTask;
    }

    public Task<List<GlossaryCustomFieldValue>> GetGlossaryCustomValues(IId glossary, CancellationToken cancellationToken)
    {
        return Task.FromResult(GlossaryCustomFieldValues.Where(x => x.GlossaryId == glossary.Id).ToList());
    }
        
    public Task SaveCustomFieldValues(AuditUserDetails auditUserDetails, Delta<GlossaryCustomFieldValue> delta, CancellationToken cancellationToken)
    {
        foreach (var addition in delta.Additions)
        {
            GlossaryCustomFieldValues.Add(addition);
        }

        //foreach(var deletion in delta.Deletions)
        //{
        //    GlossaryCustomFieldValues.Remove(deletion);
        //}

        return Task.CompletedTask;
    }

    public Task SaveCustomFieldValues(AuditUserDetails auditUserDetails, IEnumerable<Delta<GlossaryCustomFieldValue>> deltas, CancellationToken cancellationToken)
    {
        foreach (var delta in deltas)
        {
            SaveCustomFieldValues(auditUserDetails, delta, cancellationToken);
        }

        return Task.CompletedTask;
    }

    public Task<Glossary?> FindGlossary(IGeneralIdRef glossaryItemParent, CancellationToken cancellationToken)
    {
        var glossary = Glossaries.SingleOrDefault(x => x.Guid == glossaryItemParent.Guid | x.Id == glossaryItemParent.Id);
        if (glossary != null)
            glossary.CustomFieldDefinitions = new Collection<GlossaryCustomField>(GlossaryCustomFields.Where(x => x.GlossaryId == glossary.Id).ToList());

        return Task.FromResult(glossary);
    }


    public Task<IEnumerable<Glossary>> FindGlossaryChildren(long parentId, CancellationToken cancellationToken)
    {
        var children = Glossaries.Where(x => x.ParentId == parentId).ToList();
            
        return Task.FromResult<IEnumerable<Glossary>>(children);
    }

    public Task<List<CustomField>> GetCustomFieldDefinitions(IEnumerable<IGeneralIdRef> customFields, CancellationToken cancellationToken)
    {
        var result = new List<CustomField>();

        foreach (var customField in customFields)
        {
            var field = CustomFields.FindByGeneralIdRef(customField);

            if (field != null)
                result.Add(field);
            else
                throw new NullReferenceException();
        }

        return Task.FromResult(result);
    }

#pragma warning disable IDE0060 // Remove unused parameter
    public Task SaveCustomFieldValues(AuditUserDetails auditUserDetails, IEnumerable<GlossaryCustomFieldValue> glossaryCustomFieldValues, CancellationToken cancellationToken)
#pragma warning restore IDE0060 // Remove unused parameter
    {
        foreach (var glossaryCustomFieldValue in glossaryCustomFieldValues)
        {
            GlossaryCustomFieldValues.Add(glossaryCustomFieldValue);
        }

        return Task.CompletedTask;
    }

    public Task EditGlossaryItem(AuditUserDetails auditUserDetails, Glossary glossaryItem, CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}