using IntegryApiClient.Core.Domain.Abstraction.Contracts.Account;
using IntegryApiClient.Core.Domain.Abstraction.Contracts.Device;
using SteUp.Shared.Core.Data.Contracts;
using SteUp.Shared.Core.Dto;
using SteUp.Shared.Core.Dto.PageState;
using SteUp.Shared.Core.Entities;
using SteUp.Shared.Core.Enum;
using SteUp.Shared.Core.Helpers;
using SteUp.Shared.Core.Interface.IntegryApi;
using SteUp.Shared.Core.Interface.LocalDb;
using SteUp.Shared.Core.Interface.System;

namespace SteUp.Shared.Core.Data;

public class SteupDataService(
    IIntegrySteupService integrySteupService,
    IUserSession userSession,
    IDeviceService deviceService,
    IGenericSystemService genericSystemService,
    IIspezioniService ispezioniService,
    IFileManager fileManager,
    IDbInitializer dbInitializer) : ISteupDataService
{
    public async Task Init()
    {
        await dbInitializer.InitializeAsync();
        await LoadDataAsync();

        var ispezioni = await ispezioniService.GetAllIspezioniWithSchedeAsync(userSession.User.Username);

        if (!ispezioni.IsNullOrEmpty())
        {
            await CheckAndUpdateStatus(ispezioni);
            await CleanOldClosedInspection(ispezioni);
        }

        RegisterAppVersion();
    }

    public void RegisterAppVersion()
    {
        deviceService.RegisterAppVersion(
            genericSystemService.GetCurrentAppVersion()
        );
    }

    private async Task CleanOldClosedInspection(List<Ispezione> ispezioni)
    {
        ispezioni = ispezioni.Where(x =>
            x.Stato == StatusEnum.Completata &&
            x.Data < DateTime.Now.AddDays(-60)
        ).ToList();

        foreach (var ispezione in ispezioni)
        {
            fileManager.RemoveInspection(ispezione);
            await ispezioniService.DeleteIspezioneAsync(ispezione.CodMdep, ispezione.Data, ispezione.Rilevatore);
        }
    }

    public async Task CheckAndUpdateStatus()
    {
        var ispezioni = await ispezioniService.GetAllIspezioniWithSchedeAsync(userSession.User.Username);
        await CheckAndUpdateStatus(ispezioni);
    }

    private async Task CheckAndUpdateStatus(List<Ispezione> ispezioni)
    {
        var listActivityId = ispezioni
            .Where(x => x.ActivityId != null)
            .Select(x => x.ActivityId!)
            .ToList();

        if (!listActivityId.IsNullOrEmpty())
        {
            var stati = await integrySteupService.RetrieveStatoIspezioni(
                new RetrieveStatoIspezioniRequestDto
                {
                    ActivityIdList = listActivityId
                }
            );

            if (stati != null)
            {
                foreach (var stato in stati)
                {
                    var ispezione = ispezioni.Find(x =>
                        x.ActivityId != null &&
                        x.ActivityId.EqualsIgnoreCase(stato.ActivityId)
                    );

                    var newStatus = StatusEnumHelper.ConvertToStatusEnum(stato.ActivityResultId);

                    if (ispezione != null && ispezione.Stato != newStatus)
                    {
                        await ispezioniService.UpdateStatoIspezioneAsync(
                            ispezione.CodMdep,
                            ispezione.Data,
                            ispezione.Rilevatore,
                            newStatus
                        );
                    }
                }
            }
        }
    }

    public async Task<bool> CanOpenNewInspection()
    {
        var completedInspection = await ispezioniService.GetAllIspezioni(userSession.User.Username);

        if (completedInspection.IsNullOrEmpty()) return true;

        //Controllo se sono presenti attività più vecchie di 20 giorni non chiuse
        //Se presenti non si possono aprire nuove ispezioni
        return !completedInspection.Any(x =>
            x.Stato != StatusEnum.Completata &&
            x.Data < DateTime.Now.AddDays(-20)
        );
    }

    private async Task LoadDataAsync()
    {
        if (!await userSession.IsLoggedIn()) return;

        PuntiVenditaList = await integrySteupService.RetrievePuntiVendita();
        Reparti = await integrySteupService.RetrieveReparti();
        TipiAttività = await integrySteupService.RetrieveActivityType();
    }

    public InspectionPageState InspectionPageState { get; set; } = new();
    public List<PuntoVenditaDto> PuntiVenditaList { get; private set; } = [];
    public List<JtbFasiDto> Reparti { get; private set; } = [];
    public List<ActivityTypeDto> TipiAttività { get; private set; } = [];
}