using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using tencentyun;

namespace DysonNetwork.Sphere.Chat;

public class RealtimeChatConfiguration
{
    public string Provider { get; set; } = null!;
    public int AppId { get; set; }
    [JsonIgnore] public string SecretKey { get; set; } = null!;
}

[ApiController]
[Route("/chat/realtime")]
public class RealtimeCallController(IConfiguration configuration, AppDatabase db, ChatService cs) : ControllerBase
{
    private readonly RealtimeChatConfiguration _config =
        configuration.GetSection("RealtimeChat").Get<RealtimeChatConfiguration>()!;

    [HttpGet]
    public ActionResult<RealtimeChatConfiguration> GetConfiguration()
    {
        return _config;
    }

    public class RealtimeChatToken
    {
        public RealtimeChatConfiguration Config { get; set; } = null!;
        public string Token { get; set; } = null!;
    }

    [HttpGet("{roomId:long}")]
    [Authorize]
    public async Task<ActionResult<RealtimeChatToken>> GetToken(long roomId)
    {
        if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();

        var member = await db.ChatMembers
            .Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId)
            .FirstOrDefaultAsync();
        if (member == null || member.Role < ChatMemberRole.Member)
            return StatusCode(403,
                "You need to be a normal member to get the token for joining the realtime chatroom."
            );

        var ongoingCall = await cs.GetCallOngoingAsync(roomId);
        if (ongoingCall is null) return BadRequest("No ongoing call.");

        var api = new TLSSigAPIv2(_config.AppId, _config.SecretKey);
        var sig = api.GenSig(currentUser.Name);
        if (sig is null) return StatusCode(500, "Failed to generate the token.");

        return Ok(new RealtimeChatToken
        {
            Config = _config,
            Token = sig
        });
    }

    [HttpPost("{roomId:long}")]
    [Authorize]
    public async Task<IActionResult> StartCall(long roomId)
    {
        if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();

        var member = await db.ChatMembers
            .Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId)
            .Include(m => m.ChatRoom)
            .FirstOrDefaultAsync();
        if (member == null || member.Role < ChatMemberRole.Member)
            return StatusCode(403, "You need to be a normal member to start a call.");

        var ongoingCall = await cs.GetCallOngoingAsync(roomId);
        if (ongoingCall is not null) return StatusCode(423, "There is already an ongoing call inside the chatroom.");
        var call = await cs.CreateCallAsync(member.ChatRoom, member);
        return Ok(call);
    }

    [HttpDelete("{roomId:long}")]
    [Authorize]
    public async Task<IActionResult> EndCall(long roomId)
    {
        if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();

        var member = await db.ChatMembers
            .Where(m => m.AccountId == currentUser.Id && m.ChatRoomId == roomId)
            .FirstOrDefaultAsync();
        if (member == null || member.Role < ChatMemberRole.Member)
            return StatusCode(403, "You need to be a normal member to end a call.");

        try
        {
            await cs.EndCallAsync(roomId);
            return NoContent();
        }
        catch (Exception exception)
        {
            return BadRequest(exception.Message);
        }
    }
}