using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.Masters;
using adas_core.Domain.Models.MongoModels;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;

namespace adas_core.Application.Services;

public class PatientCarePlanService : IPatientCarePlanService
{
    private readonly IArchivePatientCarePlanService _archivePatientCarePlanService;
    private readonly ILocalAuditService _auditService;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly ILogger<PatientCarePlanService> _logger;
    private readonly IPatientCarePlanRepository _patientCarePlanRepository;
    private readonly IUserRepository _userRepository;

    public PatientCarePlanService(
        ILogger<PatientCarePlanService> logger,
        IPatientCarePlanRepository patientCarePlanRepository,
        IUserRepository userRepository,
        IArchivePatientCarePlanService archivePatientCarePlanService,
        IHttpContextAccessor httpContextAccessor,
        ILocalAuditService auditService)
    {
        _logger = logger;
        _patientCarePlanRepository = patientCarePlanRepository;
        _userRepository = userRepository;
        _archivePatientCarePlanService = archivePatientCarePlanService;
        _httpContextAccessor = httpContextAccessor;
        _auditService = auditService;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<List<PatientCarePlan>> FindByPatientId(ObjectId patientId)
    {
        try
        {
            return await _patientCarePlanRepository.FindByPatientId(patientId);
        }
        catch (Exception e)
        {
            _logger.LogError("Error finding Patient care plan by patientId: {PatientId} message: {Message}", patientId,
                e.Message);
            return [];
        }
    }

    public async Task<List<PatientCarePlan>> FindByUserId(ObjectId userId)
    {
        try
        {
            return await _patientCarePlanRepository.FindByUserId(userId);
        }
        catch (Exception e)
        {
            _logger.LogError("Error finding Patient care plan by userId: {UserId} message: {Message}", userId,
                e.Message);
            return [];
        }
    }

    public async Task<List<PatientCarePlan>> FindAll()
    {
        try
        {
            return await _patientCarePlanRepository.FindAll();
        }
        catch (Exception e)
        {
            _logger.LogError("Error finding all Patient care plan message: {Message}", e.Message);
            return [];
        }
    }

    public async Task InsertOneAsync(PatientCarePlan patientCarePlan)
    {
        try
        {
            patientCarePlan.Time = DateTime.UtcNow;
            await _patientCarePlanRepository.InsertOneAsync(patientCarePlan);
            await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, null, patientCarePlan);
        }
        catch (Exception e)
        {
            _logger.LogError("Error InsertOneAsync Patient care plan message: {Message} trace: {Trace}", e.Message,
                e.StackTrace);
        }
    }

    public async Task ArchiveCarePlanFromJob(Patient patientWithFinishedProcedure, List<OptionList> itemsToArchive)
    {
        var systemUser = await _userRepository.GetOrCreateSystemUser();
        foreach (var item in itemsToArchive)
        {
            var itemToArchive = new PatientCarePlan
            {
                PatientId = patientWithFinishedProcedure.Id,
                PatientNumber = patientWithFinishedProcedure.PatientNumber,
                PointOfCareId = patientWithFinishedProcedure.PointOfCareId,
                UserId = systemUser.Id,
                CarePlan = item,
                Description = "Archive item expired from job",
                Action = ActionsEnum.CrudAction.Archive,
                Time = DateTime.UtcNow
            };
            await _patientCarePlanRepository.InsertOneAsync(itemToArchive);
        }
    }

    public async Task ArchiveByPatientId(ObjectId patientid)
    {
        var carePlansToArchive = await FindByPatientId(patientid);
        await _archivePatientCarePlanService.InsertManyAsync(carePlansToArchive);
        foreach (var item in carePlansToArchive)
        {
            await _patientCarePlanRepository.DeleteAsync(item.Id);
            await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, item, null);
        }
    }

    public async Task UpdateManyObjectId(string patientid, ObjectId patientId, ObjectId oldId)
    {
        await _patientCarePlanRepository.UpdateManyObjectId(patientid, patientId, oldId);
    }
}