namespace MyOffice.Web.Controllers;

using AutoMapper;
using Microsoft.AspNetCore.Authorization;

using Core;
using Core.Extensions;
using Models.Account;
using Services.Account;
using Services.Account.Domain;
using Infrastructure.Attributes;
using Services.Identity;
using Microsoft.AspNetCore.Mvc;

[Authorize]
[ApiController]
[Route("api/settings/account-categories")]
[DefaultFromBody]
public class SettingsAccountCategoryController : BaseApiController
{
	private readonly ILogger<SettingsAccountController> _logger;
	private readonly IMapper _mapper;
	private readonly AccountService _accountService;
	private readonly IContextProvider _contextProvider;

	public SettingsAccountCategoryController(
		ILogger<SettingsAccountController> logger,
		IMapper mapper,
		AccountService accountService,
		IContextProvider contextProvider
	)
	{
		_logger = logger;
		_mapper = mapper;
		_accountService = accountService;
		_contextProvider = contextProvider;
	}

	[HttpGet]
	public async Task<ObjectResult> AccountCategories(CancellationToken cancellationToken)
	{
		var list = await _accountService.GetAllCategoriesAsync(UserId, cancellationToken);

		return OkResponse(_mapper.Map<List<AccountCategoryViewModel>>(list).OrderBy(x => x.Name));
	}

	[HttpGet("{id}")]
	public async Task<ObjectResult> AccountCategory([AsGuid] string id, CancellationToken cancellationToken)
	{
		var exec = await _accountService.GetCategoryAsync(UserId, id.AsGuid(), cancellationToken);

		switch (exec.Status)
		{
			case GeneralExecStatus.not_found:
			case GeneralExecStatus.failure:
				return ProblemNotFoundResponse("Account category not found.");

			case GeneralExecStatus.success:
				return OkResponse(_mapper.Map<AccountCategoryViewModel>(exec.Result!));

			default:
				throw new NotSupportedException(exec.Status.ToString());
		}
	}

	[HttpPost]
	public async Task<ObjectResult> AccountCategoriesAdd(AccountCategoryViewModel request, CancellationToken cancellationToken)
	{
		var exec = await _accountService.CategoryAddAsync(UserId, new AccountCategoryDto { Name = request.Name! }, cancellationToken);
		switch (exec.Status)
		{
			case GeneralExecStatus.success:
				return OkResponse(_mapper.Map<AccountCategoryViewModel>(exec.Result!));

			case GeneralExecStatus.failure:
			case GeneralExecStatus.not_found:
				return ProblemBadResponse("Adding account category failed.");

			default:
				throw new NotSupportedException(exec.Status.ToString());
		}
	}

	[HttpPut("{id}")]
	public async Task<ObjectResult> AccountCategoriesUpdate([AsGuid] string id, AccountCategoryViewModel request, CancellationToken cancellationToken)
	{
		var exec = await _accountService.CategoryUpdateAsync(UserId, id.AsGuid(), new AccountCategoryDto { Name = request.Name! }, cancellationToken);
		switch (exec.Status)
		{
			case GeneralExecStatus.success:
				return OkResponse(_mapper.Map<AccountCategoryViewModel>(exec.Result!));

			case GeneralExecStatus.failure:
			case GeneralExecStatus.not_found:
				return ProblemBadResponse("Update account category failed.");

			default:
				throw new NotSupportedException(exec.Status.ToString());
		}
	}

	[HttpDelete("{id}")]
	public async Task<ObjectResult> AccountCategoriesDelete([AsGuid] string id, CancellationToken cancellationToken)
	{
		var exec = await _accountService.CategoryRemoveAsync(UserId, id.AsGuid(), cancellationToken);
		switch (exec.Status)
		{
			case AccountCategoryRemoveResult.success:
				return OkResponse(_mapper.Map<AccountCategoryViewModel>(exec.Result!));

			case AccountCategoryRemoveResult.failure:
				return ProblemBadResponse("Remove account category failed.");
			case AccountCategoryRemoveResult.not_found:
				return ProblemNotFoundResponse("Account category not found.");
			case AccountCategoryRemoveResult.accounts_exists:
				return ProblemBadResponse("Account category have accounts.");

			default:
				throw new NotSupportedException(exec.Status.ToString());
		}
	}
}
