using IWS5.Core;
using IWS5.Core.Enums;
using IWS5.Core.Models.Processing;
using IWS5.DatabaseAccess.Interfaces;
using IWS5.DatabaseAccess.IwsDataModels;
using ILogger = Serilog.ILogger;

namespace IWS5.Server.EventProcessors;

public class TimerProcessor: IEventProcessor
{
    private readonly ILogger _logger;
    private readonly ITimerRepository _timerRepository;
    private readonly IWorkItemReferenceRepository _workItemReferenceRepository;
    private readonly IPendingWorkItemReferenceRepository _pendingWorkItemReferenceRepository;

    public TimerProcessor(
        ILogger logger, 
        ITimerRepository timerRepository,
        IWorkItemReferenceRepository workItemReferenceRepository,
        IPendingWorkItemReferenceRepository pendingWorkItemReferenceRepository)
    {
        _logger = logger;
        _timerRepository = timerRepository;
        _workItemReferenceRepository = workItemReferenceRepository;
        _pendingWorkItemReferenceRepository = pendingWorkItemReferenceRepository;
    }

    public async Task<bool> ProcessEventAsync(EventModel eventData, int processId)
    {
        _logger.Information("WorkItemId: {WorkItemId} - Starting timer processing for EventId: {EventId}, ProcessId: {ProcessId}",
            eventData.WorkItemId, eventData.CurrentEventId, processId);

        Attimer timer = await _timerRepository.FindAsync(atTimer => atTimer.EventId == eventData.CurrentEventId);
        var workItemRef = await _workItemReferenceRepository.FindAsync(
            atWorkItemRef => atWorkItemRef.WorkItemId == eventData.WorkItemId);
        
        if (timer == null)
        {
            _logger.Error("WorkItemId: {WorkItemId} - No Timer record found for EventId: {EventId}",
                eventData.WorkItemId, eventData.CurrentEventId);
            return false;
        }

        _logger.Information("WorkItemId: {WorkItemId} - Timer retrieved: TimerId: {TimerId}, ValueType: {ValueType}, TimeValue: {TimeValue}",
            eventData.WorkItemId, timer.Id, timer.ValueType, timer.TimeValue);

        DateTime expirationDateTime = DateTime.UtcNow;

        switch (timer.ValueType)
        {
            case "Minutes":
                expirationDateTime = DateTime.UtcNow.AddMinutes(timer.TimeValue);
                break;
            case "Hours":
                expirationDateTime = DateTime.UtcNow.AddHours(timer.TimeValue);
                break;
            case "Days":
                expirationDateTime = DateTime.UtcNow.AddDays(timer.TimeValue);
                break;
            case "Months":
                expirationDateTime = DateTime.UtcNow.AddMonths(timer.TimeValue);
                break;
            case "Years":
                expirationDateTime = DateTime.UtcNow.AddYears(timer.TimeValue);
                break;
            default:
                _logger.Warning("WorkItemId: {WorkItemId} - Unknown ValueType '{ValueType}' for EventId: {EventId}, defaulting to zero duration",
                    eventData.WorkItemId, timer.ValueType, eventData.CurrentEventId);
                break;
        }

        AtpendingWorkItemReference pendingWorkItemRef = new AtpendingWorkItemReference
        {
            PendingWorkItemReferenceId = workItemRef.WorkItemReferenceId,
            ExpirationTime = expirationDateTime,
            CreatedTime = DateTime.UtcNow
        };
        
        await _pendingWorkItemReferenceRepository.AddOrUpdateAsync(pendingWorkItemRef);
        _logger.Information("WorkItemId: {WorkItemId} - Pending work item reference created/updated: PendingWorkItemReferenceId: {PendingWorkItemReferenceId}, ExpirationTime: {ExpirationTime}",
            eventData.WorkItemId, pendingWorkItemRef.PendingWorkItemReferenceId, pendingWorkItemRef.ExpirationTime);

        ForwardWorkItemServerRequest forwardWorkItemServerRequest = new ForwardWorkItemServerRequest
        {
            WorkItemId = eventData.WorkItemId,
            EventId = eventData.NextEventId,
            PendEventId = 0,
            PendingQueueId = null,
            ServerRequest = ServerRequest.ForwardExistingWorkItem,
            ServerRequestParam = null
        };
        
        _logger.Information("WorkItemId: {WorkItemId} - Forwarding work item from EventId: {CurrentEventId} to NextEventId: {NextEventId}",
            eventData.WorkItemId, eventData.CurrentEventId, eventData.NextEventId);
        
        await _workItemReferenceRepository.ForwardWorkItemAsync(forwardWorkItemServerRequest);

        _logger.Information("WorkItemId: {WorkItemId} - Timer processing completed successfully for EventId: {EventId}",
            eventData.WorkItemId, eventData.CurrentEventId);

        return true;
    }
}