using e_suite.API.Common.repository;
using e_suite.Database.Audit;
using e_suite.Database.Core.Extensions;
using e_suite.Database.Core.Helpers;
using e_suite.Database.Core.Tables.Forms;
using e_suite.UnitTestCore;
using eSuite.Core.Miscellaneous;
using MockQueryable;

namespace e_suite.Service.EFlowSync.UnitTests.FakeRepositories;

public class FakeFormsRepository : FakeRepository, IFormRepository
{
    public List<FormTemplate> FormTemplates { get; set; } = [];
    public List<FormTemplateVersion> FormTemplateVersions { get; set; } = [];
    public List<FormInstance> FormInstances { get; set; } = [];

    public List<FormFieldInstance> FormFieldValues { get; set; } = [];

    public Task CreateNewFormVersionAsync(AuditUserDetails auditUserDetails, FormTemplateVersion formTemplateVersion, CancellationToken cancellationToken)
    {
        FormTemplateVersions.Add(formTemplateVersion);
        return Task.CompletedTask;
    }

    public IQueryable<FormTemplateVersion> GetAllFormVersions(long templateId)
    {
        return FormTemplateVersions.Where(x => x.TemplateId == templateId).ToList().BuildMock();
    }

    public Task CreateTemplateAsync(AuditUserDetails auditUserDetails, FormTemplate template, CancellationToken cancellationToken)
    {
        FormTemplates.Add(template);
        return Task.CompletedTask;
    }

    public Task DeleteAllVersionsAsync(AuditUserDetails auditUserDetails, IEnumerable<FormTemplateVersion> formTemplateVersions, CancellationToken cancellationToken)
    {
        FormTemplateVersions.ForEach(x =>
        {
            if (formTemplateVersions.Any(f => f.Id == x.Id) || formTemplateVersions.Any(f => f.Guid == x.Guid))
            {
                x.Deleted = true;
            }
            ;
        });
        return Task.CompletedTask;
    }

    public Task EditFormTemplateAsync(AuditUserDetails auditUserDetails, FormTemplate formTemplate, CancellationToken cancellationToken)
    {
        var form = FormTemplates.First(x => x.Id == formTemplate.Id || x.Guid == formTemplate.Guid);
        form.Name = formTemplate.Name;
        return Task.CompletedTask;
    }

#pragma warning disable IDE0060 // Remove unused parameter
    public Task<IEnumerable<FormTemplateVersion>> GetAllFormVersionsAsync(long templateId, CancellationToken cancellationToken)
#pragma warning restore IDE0060 // Remove unused parameter
    {
        return Task.FromResult(FormTemplateVersions.Where(x => x.TemplateId == templateId));
    }

    public Task<FormTemplateVersion?> GetFormTemplateVersionAsync(IGeneralIdRef templateId, CancellationToken cancellationToken)
    {
        return Task.FromResult(FormTemplateVersions.FirstOrDefault(x => x.Id == templateId.Id || x.Guid == templateId.Guid));
    }

    public Task<FormTemplate?> GetFormTemplateWithSpecificVersionAsync(IGeneralIdRef id, long formTemplateVersionId, CancellationToken cancellationToken)
    {
        return Task.FromResult(FormTemplates.FirstOrDefault(x => x.Id == id.Id || x.Guid == id.Guid));
    }

    public Task AddFormInstance(
        AuditUserDetails auditUserDetails,
        FormInstance newFormInstance,
        CancellationToken cancellationToken
    )
    {
        FormInstances.Add(newFormInstance);
        return Task.CompletedTask;
    }

    public Task AddFormInstances(AuditUserDetails auditUserDetails, IEnumerable<FormInstance> newFormInstance,
        CancellationToken cancellationToken)
    {
        FormInstances.AddRange(newFormInstance);
        return Task.CompletedTask;
    }

    public Task AddFormInstanceValues(
        AuditUserDetails auditUserDetails,
        List<FormFieldInstance> customFieldValues,
        CancellationToken cancellationToken
    )
    {
        FormFieldValues.AddRange(customFieldValues);
        return Task.CompletedTask;
    }

    public Task<FormInstance?> GetFormInstance(GeneralIdRef createFormInstanceId, bool tracking, CancellationToken cancellationToken)
    {
        return Task.FromResult(FormInstances.FindByGeneralIdRef(createFormInstanceId));
    }

    public Task<List<FormInstance>> GetFormInstances(IEnumerable<GeneralIdRef> generalIdRefs, bool tracking, CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }

    public Task SaveCustomFieldValues(AuditUserDetails auditUserDetails, Delta<FormFieldInstance> delta, CancellationToken cancellationToken)
    {
        SaveCustomFieldValuesCalled = true;
        return Task.CompletedTask;
    }

    public Task<IEnumerable<FormInstance>> GetFormsContainingFieldValue(IGeneralIdRef customFieldGeneralIdRef, string value, CancellationToken cancellationToken)
    {
        var formInstances = new List<FormInstance>();

        foreach (var formInstance in FormInstances)
        {
            foreach (var field in formInstance.FormFields)
            {
                if (field.CustomField.Guid == customFieldGeneralIdRef.Guid || field.CustomField.Id == customFieldGeneralIdRef.Id)
                {
                    formInstances.Add(formInstance);
                    break;
                }
            }
        }

        return Task.FromResult<IEnumerable<FormInstance>>(formInstances);
    }

    public bool SaveCustomFieldValuesCalled { get; set; } = false;

    public Task<FormTemplate?> GetTemplateAsync(IGeneralIdRef id, CancellationToken cancellationToken)
    {
        var form = FormTemplates.FirstOrDefault(x => x.Id == id.Id || x.Guid == id.Guid);
        if (form is null)
            return Task.FromResult(form)!;
        form!.Versions = [.. FormTemplateVersions.Where(f => f.TemplateId == form.Id).OrderBy(f => f.Version)];
        return Task.FromResult(form)!;
    }

    public IQueryable<FormTemplate> GetTemplates()
    {
        return FormTemplates.BuildMock();
    }

#pragma warning disable IDE0060 // Remove unused parameter
    public Task<IEnumerable<FormTemplate>> GetTemplatesAsync(CancellationToken cancellationToken)
#pragma warning restore IDE0060 // Remove unused parameter
    {
        return Task.FromResult((IEnumerable<FormTemplate>)FormTemplates);
    }

    public Task<FormTemplate?> GetTemplateWithOutLoadedRefereranceAsync(IGeneralIdRef id, CancellationToken cancellationToken)
    {
        var res = FormTemplates.FirstOrDefault(x => x.Id == id.Id || x.Guid == id.Guid);
        if (res is null)
        {
            return Task.FromResult(res);
        }
        res.Versions = null!;
        return Task.FromResult(res)!;
    }
}