using MemberCenter.Api.Contracts;
using MemberCenter.Api.Extensions;
using MemberCenter.Application.Abstractions;
using MemberCenter.Application.Models.Profile;
using MemberCenter.Infrastructure.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;

namespace MemberCenter.Api.Controllers;

[ApiController]
[Route("user")]
public class UserController : ControllerBase
{
    private readonly IProfileService _profileService;
    private readonly INewsletterService _newsletterService;
    private readonly UserManager<ApplicationUser> _userManager;

    public UserController(
        IProfileService profileService,
        INewsletterService newsletterService,
        UserManager<ApplicationUser> userManager)
    {
        _profileService = profileService;
        _newsletterService = newsletterService;
        _userManager = userManager;
    }

    [Authorize(Policy = "ProfileBasicRead")]
    [HttpGet("profile")]
    public async Task<IActionResult> Profile()
    {
        var user = await _userManager.GetUserAsync(User);
        if (user is null)
        {
            return Unauthorized();
        }

        var profile = await _profileService.GetProfileAsync(user.Id);
        return Ok(new
        {
            id = user.Id,
            email = user.Email,
            email_verified = user.EmailConfirmed,
            created_at = user.CreatedAt,
            profile
        });
    }

    [Authorize(Policy = "ProfileBasicWrite")]
    [HttpPost("profile")]
    public async Task<IActionResult> SaveProfile([FromBody] SaveProfileRequest request)
    {
        var user = await _userManager.GetUserAsync(User);
        if (user is null)
        {
            return Unauthorized();
        }

        try
        {
            var profile = await _profileService.SaveProfileAsync(user.Id, new SaveUserProfileRequest(
                request.LastName,
                request.FirstName,
                request.NickName,
                request.MobilePhone,
                request.LandlinePhone,
                request.DateOfBirth,
                request.Gender,
                request.CompanyName,
                request.Department,
                request.JobTitle,
                request.CompanyPhone,
                request.TaxId,
                request.InvoiceTitle,
                request.Remark));
            return Ok(profile);
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(ex.Message);
        }
    }

    [Authorize(Policy = "ProfileAddressesRead")]
    [HttpGet("addresses")]
    public async Task<IActionResult> Addresses()
    {
        var user = await _userManager.GetUserAsync(User);
        if (user is null)
        {
            return Unauthorized();
        }

        return Ok(await _profileService.ListAddressesAsync(user.Id));
    }

    [Authorize(Policy = "ProfileAddressesWrite")]
    [HttpPost("addresses")]
    public async Task<IActionResult> SaveAddress([FromBody] SaveAddressRequest request)
    {
        var user = await _userManager.GetUserAsync(User);
        if (user is null)
        {
            return Unauthorized();
        }

        try
        {
            var address = await _profileService.SaveAddressAsync(user.Id, new SaveUserAddressRequest(
                request.Id,
                request.Label,
                request.RecipientName,
                request.RecipientPhone,
                request.CountryCode,
                request.PostalCode,
                request.StateRegion,
                request.City,
                request.District,
                request.AddressLine1,
                request.AddressLine2,
                request.CompanyName,
                request.IsDefault,
                request.AddressMetaJson));
            return Ok(address);
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(ex.Message);
        }
    }

    [Authorize(Policy = "ProfileAddressesWrite")]
    [HttpDelete("addresses/{id:guid}")]
    public async Task<IActionResult> DeleteAddress(Guid id)
    {
        var user = await _userManager.GetUserAsync(User);
        if (user is null)
        {
            return Unauthorized();
        }

        try
        {
            await _profileService.DeleteAddressAsync(user.Id, id);
            return NoContent();
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(ex.Message);
        }
    }

    [Authorize(Policy = "ProfileSubscriptionsRead")]
    [HttpGet("subscriptions")]
    public async Task<IActionResult> Subscriptions()
    {
        var user = await _userManager.GetUserAsync(User);
        if (user is null)
        {
            return Unauthorized();
        }

        return Ok(await _newsletterService.ListSubscriptionsForUserAsync(user.Id));
    }

    [Authorize(Policy = "ProfileSubscriptionsWrite")]
    [HttpPost("subscriptions/{id:guid}/unsubscribe")]
    public async Task<IActionResult> Unsubscribe(Guid id)
    {
        var user = await _userManager.GetUserAsync(User);
        if (user is null)
        {
            return Unauthorized();
        }

        var subscription = await _newsletterService.UnsubscribeForUserAsync(user.Id, id);
        return subscription is null ? NotFound() : Ok(subscription);
    }
}
