namespace MyOffice.Web.Controllers;

using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

using Models.Item;
using Core.Extensions;
using Core;
using Infrastructure.Attributes;
using Services.Item;
using Services.Item.Domain;

[Authorize]
[DefaultFromBody]
public class SettingsItemController : BaseApiController
{
	private ILogger<SettingsItemController> _logger;
	private IMapper _mapper;
	private ItemService _itemService;

	public SettingsItemController(
		ILogger<SettingsItemController> logger,
		ItemService itemService,
		IMapper mapper
	)
	{
		_itemService = itemService;
		_logger = logger;
		_mapper = mapper;
	}

	public ObjectResult ItemsCategories()
	{
		var list = _itemService.GetAllCategories(UserId);

		return Ok(_mapper.Map<List<ItemCategoryViewModel>>(list)
			.OrderByDescending(x => x.SortOrder)
			.ThenBy(x => x.Name));
	}

	public ObjectResult ItemCategoriesAdd(ItemCategoryViewModel request)
	{
		var exec = _itemService.CategoryAdd(UserId, request.FromModel());

		switch (exec.Status)
		{
			case GeneralExecStatus.success:
				return Ok(_mapper.Map<ItemCategoryViewModel>(exec.Result!));

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

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

	public ObjectResult ItemCategoriesUpdate([AsGuid] string id, ItemCategoryViewModel request)
	{
		var exec = _itemService.CategoryUpdate(UserId, id.AsGuid(), request.FromModel());

		switch (exec.Status)
		{
			case GeneralExecStatus.success:
				return Ok(_mapper.Map<ItemCategoryViewModel>(exec.Result!));

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

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

	public ObjectResult ItemCategoriesDelete([AsGuid] string id)
	{
		var exec = _itemService.CategoryRemove(UserId, id.AsGuid());
		switch (exec.Status)
		{
			case ItemCategoryRemoveResult.success:
				return Ok(_mapper.Map<ItemCategoryViewModel>(exec.Result!));

			case ItemCategoryRemoveResult.failure:
				return ProblemBadResponse("Remove item category failed.");
			case ItemCategoryRemoveResult.not_found:
				return ProblemBadResponse("Account item not found.");
			case ItemCategoryRemoveResult.accounts_exists:
				return ProblemBadResponse("Account motion have accounts.");

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

	public ObjectResult Items([AsGuid] string category)
	{
		var categoryId = category.AsGuid();

		var list = categoryId != UserId
				? _itemService.GetByCategory(UserId, categoryId)
				: _itemService.GetByUncategorized(UserId);

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

	public ObjectResult ItemsUpdate([AsGuid] string id, ItemEditModel request)
	{
		var exec = _itemService.Update(UserId, id.AsGuid(), request.Category.AsGuid());

		switch (exec.Status)
		{
			case GeneralExecStatus.not_found:
				return ProblemBadResponse("Item not found.");
			case GeneralExecStatus.failure:
				return ProblemBadResponse("Item update failed.");
			case GeneralExecStatus.success:
				return Ok(_mapper.Map<ItemViewModel>(exec.Result!));

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

	public ObjectResult ItemsPost(ItemChangeCategoryModel request)
	{
		var exec = _itemService.UpdateItemsCategory(UserId, request.category.AsGuid(), request.Items.Select(x => x.AsGuid()).ToList());

		switch (exec)
		{
			case GeneralExecStatus.not_found:
				return ProblemBadResponse("Category not found.");
			case GeneralExecStatus.failure:
				return ProblemBadResponse("Update failed.");
			case GeneralExecStatus.success:
				return Ok(new {});

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