using Application.Services.Database;
using Application.Services.Database.MongoDB;
using Core.Entities;

namespace Application.Endpoints.MedicalHistories.FileManagement;

public class MedicalHistoryFileManagementHandler
{
    private readonly IMedicalHistoryRepository _medicalHistoryRepository;
    private readonly IMedicalHistoryMongoDbService _medicalHistoryMongoDbService;
    private readonly IPatientRepository _patientRepository;

    public MedicalHistoryFileManagementHandler(IMedicalHistoryRepository medicalHistoryRepository,
        IPatientRepository patientRepository, IMedicalHistoryMongoDbService medicalHistoryMongoDbService)
    {
        _medicalHistoryRepository = medicalHistoryRepository;
        _patientRepository = patientRepository;
        _medicalHistoryMongoDbService = medicalHistoryMongoDbService;
    }

    public async Task<BaseResponse> HandleGetAll()
    {
        var documents = await _medicalHistoryRepository.GetAllAsync().ConfigureAwait(false);
        if (documents.Any())
            return new BaseResponse
            {
                StatusCode = HttpStatusCodes.OK,
                Message = "Retrieved medical histories",
                Data = documents.ToList()
            };

        return new BaseResponse
        {
            StatusCode = HttpStatusCodes.NoContent,
            Message = "Medical histories not found",
            Data = null
        };
    }

    public async Task<BaseResponse> HandleGet(Guid id)
    {
        var medicalHistory = await _medicalHistoryRepository.GetByIdAsync(id).ConfigureAwait(false);
        if (medicalHistory != null)
            return new BaseResponse
            {
                StatusCode = HttpStatusCodes.OK,
                Message = "Medical history successfully retrieved",
                Data = medicalHistory
            };

        return new BaseResponse
        {
            StatusCode = HttpStatusCodes.NotFound,
            Message = "Medical history not found in system.",
            Data = null
        };
    }

    public async Task<BaseResponse> HandleCreate(MedicalHistoryCreateDto medicalHistoryCreateDto)
    {
        var validation = new MedicalHistoryCreateValidation(_patientRepository);
        var validationResult = await validation.ValidateAsync(medicalHistoryCreateDto);

        if (!validationResult.IsValid)
        {
            var firstError = validationResult.Errors.FirstOrDefault();
            var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
            var errorMessage = firstError.ErrorMessage;

            return new BaseResponse
            {
                StatusCode = errorCode,
                Message = errorMessage,
                Data = null
            };
        }

        var medicalHistory = new MedicalHistory
        {
            UserId = medicalHistoryCreateDto.UserId,
            Content = medicalHistoryCreateDto.Content
        };

        var medicalHistoryId = medicalHistory.Id;
        var newMedicalHistory = new MedicalHistoryAuthorisationModel
        {
            Id = medicalHistoryId.ToString(),
            Authorisation = new List<string>()
        };

        await _medicalHistoryMongoDbService.AddAsync(newMedicalHistory);
        await _medicalHistoryRepository.AddAsync(medicalHistory);

        return new BaseResponse
        {
            StatusCode = HttpStatusCodes.Created,
            Message = "Medical history record registered successfully",
            Data = medicalHistory
        };
    }

    public async Task<BaseResponse> HandleUpdate(MedicalHistoryUpdateDto updateDto)
    {
        var validation = new MedicalHistoryUpdateValidation(_medicalHistoryRepository, _patientRepository);
        var validationResult = await validation.ValidateAsync(updateDto);

        if (!validationResult.IsValid)
        {
            var firstError = validationResult.Errors.FirstOrDefault();
            var errorCode = int.TryParse(firstError.ErrorCode, out var code) ? code : -1;
            var errorMessage = firstError.ErrorMessage;

            return new BaseResponse
            {
                StatusCode = errorCode,
                Message = errorMessage,
                Data = null
            };
        }

        var medicalHistoryToUpdate = await _medicalHistoryRepository.GetByIdAsync(updateDto.Id);
        medicalHistoryToUpdate.Content = updateDto.Content;

        await _medicalHistoryRepository.UpdateAsync(medicalHistoryToUpdate);
        return new BaseResponse
        {
            StatusCode = HttpStatusCodes.NoContent,
            Message = "Medical record updated successfully",
            Data = null
        };
    }

    public async Task<BaseResponse> HandleDelete(Guid id)
    {
        var medicalRecord = await _medicalHistoryRepository.GetByIdAsync(id);
        if (medicalRecord == null)
            return new BaseResponse
            {
                StatusCode = HttpStatusCodes.NotFound,
                Message = "Medical record is not in system.",
                Data = null
            };

        await _medicalHistoryMongoDbService.DeleteAsync<MedicalHistoryAuthorisationModel>("_id", id.ToString());

        await _medicalHistoryRepository.DeleteAsync(medicalRecord);

        //TODO delete from MongoDB
        return new BaseResponse
        {
            StatusCode = HttpStatusCodes.NoContent,
            Message = null,
            Data = null
        };
    }
}