using AutoMapper;
using AutoMapper.QueryableExtensions;
using IRaCIS.Application.ExpressionExtend;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Infra.Data.ExpressionExtend;
using System;
using System.Linq;
using System.Linq.Expressions;
using IRaCIS.Core.Domain.Interfaces;
using IRaCIS.Core.Domain.Models;

namespace IRaCIS.Application.Services
{
    public class ExchangeRateService : IExchangeRateService
    {
        private readonly IExchangeRateRepository _exchangeRateRepository;
        private readonly IMapper _mapper;
        private readonly IPaymentRepository _paymentRepository;

        public ExchangeRateService(IExchangeRateRepository exchangeRateRepository, IMapper mapper,IPaymentRepository paymentRepository)
        {
            _exchangeRateRepository = exchangeRateRepository;
            _mapper = mapper;
            _paymentRepository = paymentRepository;
        }
        public IResponseOutput AddOrUpdateExchangeRate(ExchangeRateCommand model)
        {
            if (model.Id == Guid.Empty||model.Id==null)
            {
                var existItem = _exchangeRateRepository.FindSingleOrDefault(u => u.YearMonth == model.YearMonth);
                if (existItem != null)
                {
                    return ResponseOutput.NotOk("Same month's exchange rate is already exist.");
                }
                var rate = _mapper.Map<ExchangeRate>(model);
                rate = _exchangeRateRepository.Add(rate);
                if (_exchangeRateRepository.SaveChanges())
                {
                    return ResponseOutput.Ok(rate.Id.ToString());
                }
                else
                {
                    return ResponseOutput.NotOk();
                }

            }
            else
            {
                var success = _exchangeRateRepository.Update(t => t.Id == model.Id, u => new ExchangeRate()
                {
                    //YearMonth = model.YearMonth,
                    Rate = model.Rate,
                    UpdateTime = DateTime.Now
                });
                return ResponseOutput.Result(success, success ? string.Empty : StaticData.UpdateFailed);
            }
        }

        public IResponseOutput DeleteExchangeRate(Guid id)
        {
            var monthInfo = _exchangeRateRepository.GetAll().FirstOrDefault(t => t.Id == id);

            if (_paymentRepository.GetAll().Any(t => t.YearMonth == monthInfo.YearMonth))
            {
                return ResponseOutput.NotOk("The exchange rate has been used in monthly payment");
            }


            var success = _exchangeRateRepository.Delete(t => t.Id == id);

            return ResponseOutput.Result(success, success ? string.Empty : StaticData.DeleteFailed); ;
        }

        public decimal GetExchangeRateByMonth(string month)
        {
            //var rate = _exchangeRateRepository.FindSingleOrDefault(u => u.YearMonth.Equals(month));
            //if (rate == null)
            //{
            //    return 0;
            //}
            //return rate.Rate;

            var rate = _exchangeRateRepository.GetAll().FirstOrDefault(t => t.YearMonth == month);
            if (rate == null)
            {
                return 0;
            }
            return rate.Rate;
        }

        public PageOutput<ExchangeRateCommand> GetExchangeRateList(ExchangeRateQueryDTO queryParam)
        {

            Expression<Func<ExchangeRate, bool>> exchangeRateLambda = x => true;
            if (queryParam.SearchMonth != null)
            {
                var yearMonth = queryParam.SearchMonth?.ToString("yyyy-MM");
                exchangeRateLambda = exchangeRateLambda.And(o => o.YearMonth == yearMonth);
            }
            var exchangeRateQueryable = _exchangeRateRepository.GetAll().Where(exchangeRateLambda).ProjectTo<ExchangeRateCommand>(_mapper.ConfigurationProvider);

            exchangeRateQueryable = exchangeRateQueryable.OrderByDescending("YearMonth");
            int count = exchangeRateQueryable.Count();
            exchangeRateQueryable = exchangeRateQueryable.Skip((queryParam.PageIndex - 1) * queryParam.PageSize)
                .Take(queryParam.PageSize);
            var list = exchangeRateQueryable.ToList();

            return new PageOutput<ExchangeRateCommand>(queryParam.PageIndex, queryParam.PageSize, count, list);

        }
    }
}