using BankYouBankruptBusinessLogic.BusinessLogics;
using BankYouBankruptContracts.BindingModels;
using BankYouBankruptContracts.BusinessLogicsContracts;
using BankYouBankruptContracts.SearchModels;
using BankYouBankruptContracts.ViewModels;
using BankYouBankruptContracts.ViewModels.Client.Default;
using BankYouBankruptContracts.ViewModels.Client.Diagram;
using BankYouBankruptDatabaseImplement.Models;
using BankYouBankruptDataModels.Enums;
using Microsoft.AspNetCore.Mvc;

namespace BankYouBankruptRestApi.Controllers
{
	//указание у контроллера, что Route будет строиться не только по наванию контроллера, но и по названию метода (так как у нас два Post-метода)
	[Route("api/[controller]/[action]")]
    [ApiController]
    public class AccountController : Controller
    {
        private readonly ILogger _logger;

        private readonly IAccountLogic _accountLogic;

		private readonly IDebitingLogic _debitingLogic;

		private readonly ICreditingLogic _creditingLogic;

		private readonly ICashWithdrawalLogic _cashLogic;

		private readonly IMoneyTransferLogic _moneyTransferLogic;

		public AccountController(IAccountLogic accountLogic, IDebitingLogic debitingLogic, ICashWithdrawalLogic cashLogic, 
			ICreditingLogic creditingLogic, IMoneyTransferLogic moneyTransferLogic, ILogger<AccountController> logger)
        {
            _logger = logger;
            _accountLogic = accountLogic;
            _debitingLogic = debitingLogic;
			_cashLogic = cashLogic;
			_creditingLogic = creditingLogic;
			_moneyTransferLogic = moneyTransferLogic;
        }

        [HttpGet]
        public AccountViewModel? Login(string accountNumber, string passwordAccount)
        {
            try
            {
                //попытка найти запись по переданным номеру и паролю счёта
                return _accountLogic.ReadElement(new AccountSearchModel
                {
                    AccountNumber = accountNumber,
                    PasswordAccount = passwordAccount
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка входа в систему");
                throw;
            }
        }

		//получаем все имеющиеся счета
		[HttpGet]
		public List<AccountViewModel>? GetAllAccounts()
		{
			try
			{
				return _accountLogic.ReadList(null);
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

		//получаем все имеющиеся счета
		[HttpGet]
		public AccountViewModel? GetAccount(int accountId)
		{
			try
			{
				return _accountLogic.ReadElement(new AccountSearchModel
				{
					Id = accountId
				});
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

		[HttpPost]
        public void Register(AccountBindingModel model)
        {
            try
            {
                //создание счёта
                _accountLogic.Create(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка регистрации");
                throw;
            }
        }

        [HttpPost]
        public void UpdateData(AccountBindingModel model)
        {
            try
            {
                //изменение счёта
                _accountLogic.Update(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка обновления данных");
                throw;
            }
        }

        //найти все счета, которые создал конкретный кассир
		[HttpGet]
		public List<AccountViewModel>? SearchAccounts(int cashierId)
		{
			try
			{
				return _accountLogic.ReadList(new AccountSearchModel
				{
					CashierId = cashierId
				});
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

        //найти все счета клиента
		[HttpGet]
		public List<AccountViewModel>? SearchAccountsOfCLient(int clientId)
		{
			try
			{
				//попытка найти запись по переданным номеру и паролю счёта
				return _accountLogic.ReadList(new AccountSearchModel
				{
					ClientId = clientId
				});
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

        [HttpGet]
        public List<CashWithdrawalViewModel>? FindAllCashWithdrawal()
        {
            try
            {
                return _cashLogic.ReadList(null);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка входа в систему");
                throw;
            }
        }

        [HttpGet]
        public List<MoneyTransferViewModel>? FindAllMoneyTransfer()
        {
            try
            {
                return _moneyTransferLogic.ReadList(null);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка входа в систему");
                throw;
            }
        }

        //найти все открытые заявки на снятие средств
        [HttpGet]
		public List<DebitingViewModel>? FindOpenDebiting()
		{
			try
			{
				return _debitingLogic.ReadList(new DebitingSearchModel
				{
					Status = StatusEnum.Открыта
				});
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

		//найти все открытые заявки на снятие средств
		[HttpGet]
		public List<CreditingViewModel>? FindOpenCrediting()
		{
			try
			{
				return _creditingLogic.ReadList(new CreditingSearchModel
				{
					Status = StatusEnum.Открыта
				});
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

		//подтверждение заявки на снятие средств со счёта
		[HttpPost]
		public void CloseDebiting(CashWithdrawalBindingModel CashWithdrawal)
		{
			try
			{
				bool flag =_accountLogic.ChangeBalance(new AccountSearchModel
				{
					Id = CashWithdrawal.AccountId
				}, CashWithdrawal.Sum * -1);

				_cashLogic.Create(CashWithdrawal, flag);
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

		//подтверждение заявки на перевод либо пополнение балланса
		[HttpPost]
		public void CloseCrediting(MoneyTransferBindingModel moneyTransfer)
		{
			try
			{
				_moneyTransferLogic.Create(moneyTransfer);

				bool flag = true;

				//если есть отправитель, т. е. операция на перевод денег со счёта на счёт
				if (moneyTransfer.AccountSenderId.HasValue)
				{
					flag = _accountLogic.ChangeBalance(new AccountSearchModel
					{
						Id = moneyTransfer.AccountSenderId
					}, moneyTransfer.Sum * -1);
				}

				if (flag)
				{
					_accountLogic.ChangeBalance(new AccountSearchModel
					{
						Id = moneyTransfer.AccountPayeeId
					}, moneyTransfer.Sum);
				}
				else
				{
					throw new Exception("Недостаточно средств");
				}

			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

		//поиск заявки на зачисление по id
		[HttpGet]
		public CreditingViewModel FindCrediting(int id)
		{
			try
			{
				return _creditingLogic.ReadElement(new CreditingSearchModel
				{
					Id = id
				});
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

		//поиск заявки на снятие по id
		[HttpGet]
		public DebitingViewModel FindDebiting(int id)
		{
			try
			{
				return _debitingLogic.ReadElement(new DebitingSearchModel
				{
					Id = id
				});
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка входа в систему");
				throw;
			}
		}

        [HttpGet]
        public List<CashierDiagramElementsViewModel> getAccountMonthResult(int cardId)
        {
            try
            {
                return _accountLogic.GetMonthInfo(cardId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения пользователей");
                throw;
            }
        }
    }
}