using Managing.Api.Models.Requests;
using Managing.Application.Abstractions.Services;
using Managing.Domain.Accounts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Managing.Api.Controllers
{
    /// <summary>
    /// Provides endpoints for account management operations such as creating, retrieving, and deleting accounts.
    /// Requires authorization for access.
    /// </summary>
    [Authorize]
    public class AccountController : BaseController
    {
        private readonly IAccountService _AccountService;

        /// <summary>
        /// Initializes a new instance of the <see cref="AccountController"/> class.
        /// </summary>
        /// <param name="AccountService">Service for account-related operations.</param>
        /// <param name="userService">Service for user-related operations.</param>
        public AccountController(
            IAccountService AccountService,
            IUserService userService)
            : base(userService)
        {
            _AccountService = AccountService;
        }

        /// <summary>
        /// Creates a new account for the authenticated user.
        /// </summary>
        /// <param name="Account">The account details to create.</param>
        /// <returns>The created account details.</returns>
        [HttpPost]
        public async Task<ActionResult<Account>> PostAccount(Account Account)
        {
            var user = await GetUser();
            return Ok(await _AccountService.CreateAccount(user, Account));
        }

        /// <summary>
        /// Retrieves all accounts associated with the authenticated user.
        /// </summary>
        /// <returns>A list of accounts.</returns>
        [HttpGet]
        [Route("accounts")]
        public async Task<ActionResult<IEnumerable<Account>>> GetAccounts()
        {
            var user = await GetUser();
            return Ok(_AccountService.GetAccountsByUser(user, true));
        }

        /// <summary>
        /// Retrieves the balances of all accounts associated with the authenticated user.
        /// </summary>
        /// <returns>A list of accounts with their balances.</returns>
        [HttpGet]
        [Route("balances")]
        public async Task<ActionResult<IEnumerable<Account>>> GetAccountsBalances()
        {
            var user = await GetUser();
            return Ok(_AccountService.GetAccountsBalancesByUser(user));
        }

        /// <summary>
        /// Retrieves a specific account by name for the authenticated user.
        /// </summary>
        /// <param name="name">The name of the account to retrieve.</param>
        /// <returns>The account details if found.</returns>
        [HttpGet]
        public async Task<ActionResult<Account>> GetAccount(string name)
        {
            var user = await GetUser();
            return Ok(await _AccountService.GetAccountByUser(user, name, true, true));
        }

        /// <summary>
        /// Retrieves the GMX claimable fees summary for a specific account.
        /// </summary>
        /// <param name="name">The name of the account to get claimable fees for.</param>
        /// <returns>The GMX claimable fees summary including funding fees, UI fees, and rebate stats.</returns>
        [HttpGet]
        [Route("{name}/gmx-claimable-summary")]
        public async Task<ActionResult<GmxClaimableSummary>> GetGmxClaimableSummary(string name)
        {
            var user = await GetUser();
            var result = await _AccountService.GetGmxClaimableSummaryAsync(user, name);
            return Ok(result);
        }

        /// <summary>
        /// Swaps tokens on GMX for a specific account.
        /// </summary>
        /// <param name="name">The name of the account to perform the swap for.</param>
        /// <param name="request">The swap request containing ticker symbols, amount, and order parameters.</param>
        /// <returns>The swap response with transaction details.</returns>
        [HttpPost]
        [Route("{name}/gmx-swap")]
        public async Task<ActionResult<SwapInfos>> SwapGmxTokens(string name, [FromBody] SwapTokensRequest request)
        {
            var user = await GetUser();
            var result = await _AccountService.SwapGmxTokensAsync(
                user,
                name,
                request.FromTicker,
                request.ToTicker,
                request.Amount,
                request.OrderType,
                request.TriggerRatio,
                request.AllowedSlippage
            );
            return Ok(result);
        }

        /// <summary>
        /// Sends tokens from a specific account to a recipient address.
        /// </summary>
        /// <param name="name">The name of the account to send tokens from.</param>
        /// <param name="request">The token sending request containing recipient address, ticker, and amount.</param>
        /// <returns>The transaction response with details.</returns>
        [HttpPost]
        [Route("{name}/send-token")]
        public async Task<ActionResult<SwapInfos>> SendToken(string name, [FromBody] SendTokenRequest request)
        {
            var user = await GetUser();
            var result = await _AccountService.SendTokenAsync(
                user,
                name,
                request.RecipientAddress,
                request.Ticker,
                request.Amount,
                request.ChainId
            );
            return Ok(result);
        }

        /// <summary>
        /// Deletes a specific account by name for the authenticated user.
        /// </summary>
        /// <param name="name">The name of the account to delete.</param>
        /// <returns>An ActionResult indicating the outcome of the operation.</returns>
        [HttpDelete]
        public async Task<ActionResult> DeleteAccount(string name)
        {
            var user = await GetUser();
            return Ok(_AccountService.DeleteAccount(user, name));
        }
    }
}