using MailApi.Models;
using MailApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;

namespace MailApi.Controllers;

[ApiController]
[Route("api/[controller]")]
public class MailController : ControllerBase
{
    private readonly MailStore _mail;

    public MailController(MailStore mail)
    {
        _mail = mail;
    }

    [HttpGet("characters/{characterId}")]
    [Authorize(Roles = "USER,SUPER")]
    public async Task<IActionResult> GetMailbox(string characterId)
    {
        var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
        if (string.IsNullOrWhiteSpace(userId))
            return Unauthorized();

        var access = await _mail.ResolveCharacterAsync(characterId, userId, User.IsInRole("SUPER"));
        if (!access.Exists)
            return NotFound();
        if (!access.IsAuthorized)
            return Forbid();

        var inbox = await _mail.GetInboxAsync(characterId);
        var sent = await _mail.GetSentAsync(characterId);
        return Ok(new MailboxResponse
        {
            CharacterId = characterId,
            Inbox = inbox.Select(MailMessageResponse.FromModel).ToList(),
            Sent = sent.Select(MailMessageResponse.FromModel).ToList()
        });
    }

    [HttpPost("characters/{characterId}/send")]
    [Authorize(Roles = "USER,SUPER")]
    public async Task<IActionResult> Send(string characterId, [FromBody] SendMailRequest req)
    {
        if (string.IsNullOrWhiteSpace(req.RecipientCharacterName))
            return BadRequest("recipientCharacterName required");
        if (string.IsNullOrWhiteSpace(req.Subject))
            return BadRequest("subject required");
        if (string.IsNullOrWhiteSpace(req.Body))
            return BadRequest("body required");

        var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
        if (string.IsNullOrWhiteSpace(userId))
            return Unauthorized();

        var access = await _mail.ResolveCharacterAsync(characterId, userId, User.IsInRole("SUPER"));
        if (!access.Exists)
            return NotFound();
        if (!access.IsAuthorized)
            return Forbid();

        var result = await _mail.SendAsync(characterId, req.RecipientCharacterName, req.Subject, req.Body);
        return result.Status switch
        {
            MailStore.SendMailStatus.SenderNotFound => NotFound("Sender character not found"),
            MailStore.SendMailStatus.RecipientNotFound => NotFound("Recipient character not found"),
            MailStore.SendMailStatus.RecipientAmbiguous => Conflict("Recipient character name is ambiguous"),
            MailStore.SendMailStatus.Invalid => BadRequest("Invalid recipient"),
            _ => Ok(MailMessageResponse.FromModel(result.Message!))
        };
    }

    [HttpPost("characters/{characterId}/messages/{messageId}/read")]
    [Authorize(Roles = "USER,SUPER")]
    public async Task<IActionResult> MarkRead(string characterId, string messageId)
    {
        var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
        if (string.IsNullOrWhiteSpace(userId))
            return Unauthorized();

        var access = await _mail.ResolveCharacterAsync(characterId, userId, User.IsInRole("SUPER"));
        if (!access.Exists)
            return NotFound();
        if (!access.IsAuthorized)
            return Forbid();

        var message = await _mail.MarkReadAsync(characterId, messageId);
        return message is null ? NotFound() : Ok(MailMessageResponse.FromModel(message));
    }
}
