using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Admin.Service.Interfaces;
using Admin.Service.Models;
using HsSqlAgent.Server.Attributes;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace HsSqlAgent.Server.Controllers;

[ApiController]
[Route("api/[controller]")]
public class AdminController(ILogger<AdminController> logger, IAdminService adminService, IAuditService auditService) : ControllerBase
{
    [HttpGet("first-run")]
    [AllowAnonymous]
    public async Task<IActionResult> CheckFirstRunAsync()
        => Ok(await adminService.IsFirstRunAsync());

    [HttpPost("sign-in")]
    [AllowAnonymous]
    public async Task<IActionResult> SignIn([FromBody] SignInRequest request)
    {
        if (!ModelState.IsValid) return ValidationProblem(ModelState);
        try
        {
            var result = await adminService.SignInAsync(request);
            await auditService.WriteLogAsync("admin.signin", request.Email, "success");
            return Ok(result);
        }
        catch (UnauthorizedAccessException ex)
        {
            logger.LogWarning(ex, "Sign-in failed for user");
            await auditService.WriteLogAsync("admin.signin", request.Email, "failed", "Invalid credentials");
            return Forbid();
        }
        catch (ArgumentException ex)
        {
            logger.LogWarning(ex, "Invalid sign-in request.");
            await auditService.WriteLogAsync("admin.signin", request.Email, "failed", ex.Message);
            return BadRequest(ex.Message);
        }
    }

    [HttpPost("sign-up")]
    [AllowAnonymous]
    public async Task<IActionResult> SignUp([FromBody] SignUpRequest request)
    {
        if (!ModelState.IsValid) return ValidationProblem(ModelState);
        try
        {
            var result = await adminService.SignUpAsync(request);
            await auditService.WriteLogAsync("admin.signup", request.Email, "success");
            return Ok(result);
        }
        catch (ArgumentException ex)
        {
            logger.LogWarning(ex, "Invalid sign-up request.");
            await auditService.WriteLogAsync("admin.signup", request.Email, "failed", ex.Message);
            return BadRequest(ex.Message);
        }
        catch (InvalidOperationException ex)
        {
            logger.LogWarning(ex, "Sign-up attempt when admin user already exists.");
            await auditService.WriteLogAsync("admin.signup", request.Email, "failed", ex.Message);
            return BadRequest(ex.Message);
        }
    }

    [RefreshAuthorize]
    [HttpPost("refresh-token")]
    public async Task<IActionResult> RefreshTokenAsync()
    {
        if (User.FindFirstValue(JwtRegisteredClaimNames.Sub) is var id && string.IsNullOrWhiteSpace(id))
            return Unauthorized("User ID is required.");
        try
        {
            var result = await adminService.RefreshTokenAsync(id);
            return Ok(result);
        }
        catch (UnauthorizedAccessException ex)
        {
            logger.LogWarning(ex, "Token refresh failed");
            return Forbid();
        }
        catch (ArgumentException ex)
        {
            logger.LogWarning(ex, "Invalid token refresh request.");
            return BadRequest(ex.Message);
        }
    }
}
