using System;
using System.Text.Json;
using Expedience.Api.Encryption;
using Expedience.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Expedience.Api.Controllers
{
    [Route("api")]
    [ApiController]
    public class ExpedienceController : ControllerBase
    {
        private readonly ILogger<ExpedienceController> _logger;
        private readonly IPublishEndpoint _publisher;
        private readonly IDecryptor _decrypytor;
        private readonly IServiceScopeFactory _serviceScopeFactory;

        public ExpedienceController(ILogger<ExpedienceController> logger,
            IPublishEndpoint publisher,
            IDecryptor decrypytor,
            IServiceScopeFactory serviceScopeFactory)
        {
            _logger = logger;
            _publisher = publisher;
            _decrypytor = decrypytor;
            _serviceScopeFactory = serviceScopeFactory;
        }

        [HttpPost("DutyCompletion")]
        public async Task<ActionResult> PostDutyCompletionResult(List<string> encryptedPayloads)
        {
            var utcNow = DateTime.UtcNow;
            try
            {
                foreach (var payload in encryptedPayloads)
                {
                    var decryptedData = _decrypytor.Decrypt(payload);
                    var completionResult = JsonSerializer.Deserialize<Models.DutyCompletionResult>(decryptedData)!;
                    completionResult.UploadDateUtc = utcNow;
                    await _publisher.Publish(completionResult);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error publishing completion result: {errorMessage}", ex.Message);
            }

            return Ok();
        }

        [HttpGet("UserName/{worldId}/{userHash}")]
        public async Task<ActionResult> GetUserName(int worldId, string userHash, CancellationToken cancellationToken)
        {
            try
            {
                using var scope = _serviceScopeFactory.CreateScope();
                using var dbContext = scope.ServiceProvider.GetRequiredService<ExpedienceContext>();

                var user = await dbContext.Users.FirstOrDefaultAsync(x => x.UserHash == userHash && x.WorldId == worldId, cancellationToken);
                if (user != null)
                    return Ok(user.UserName);
                else
                    return NotFound();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error obtaining user name for World Id {worldId} and hash {userHash}: {errorMessage}", worldId, userHash, ex.Message);
            }

            return StatusCode(500);
        }

		[HttpGet("DutyCompletionRecords/{expac}")]
		public async Task<ActionResult> GetDutyCompletionRecords(string expac, CancellationToken cancellationToken)
		{
			try
			{
				using var scope = _serviceScopeFactory.CreateScope();
				var repository = scope.ServiceProvider.GetService<IExpedienceRepository>();

				var results = await repository.GetDutyCompletionRecords(expac, cancellationToken);
				return Ok(results);
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Error getting Duty Completion Records for {expac}: {errorMessage}", expac, ex.Message);
			}

			return StatusCode(500);
		}


		[HttpGet("DeepDungeonRecords")]
		public async Task<ActionResult> GetDeepDungeonRecords(CancellationToken cancellationToken)
		{
			try
			{
				using var scope = _serviceScopeFactory.CreateScope();
				var repository = scope.ServiceProvider.GetService<IExpedienceRepository>();
				
				var results = await repository.GetDeepDungeonRecords(cancellationToken);
				return Ok(results);
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Error getting Deep Dungeon Records: {errorMessage}", ex.Message);
			}

			return StatusCode(500);
		}
	}
}
