using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Transactions;
using AutoMapper;
using GxPress.Common.AppOptions;
using GxPress.Common.Exceptions;
using GxPress.Common.Page;
using GxPress.Common.Tools;
using GxPress.Entity;
using GxPress.Repository.Interface;
using GxPress.Request.Finance;
using GxPress.Result.Finance;
using GxPress.Result.HumanAffairs;
using Microsoft.Extensions.Options;
using Datory;

namespace GxPress.Repository.Implement
{
    /// <summary>
    /// 财务数据
    /// </summary>
    public class FinanceRepository : IFinanceRepository
    {
        private readonly Repository<Finance> _repository;
        public FinanceRepository(IOptionsMonitor<DatabaseOptions> dbOptionsAccessor, IMapper mapper)
        {
            var databaseType = StringUtils.ToEnum<DatabaseType>(dbOptionsAccessor.CurrentValue.DatabaseType, DatabaseType.MySql);
            var database = new Database(databaseType, dbOptionsAccessor.CurrentValue.ConnectionString);
            _repository = new Repository<Finance>(database);
        }

        public IDatabase Database => _repository.Database;
        public string TableName => _repository.TableName;
        public List<TableColumn> TableColumns => _repository.TableColumns;
        /// <summary>
        /// 添加财务数据
        /// </summary>
        /// <param name="finances"></param>
        /// <returns></returns>
        public async Task<bool> InsertAsync(IEnumerable<Finance> finances)
        {
            try
            {
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    foreach (var finance in finances)
                    {
                        await _repository.InsertAsync(finance);
                    }

                    transactionScope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new BusinessException(e.Message);
            }

            return true;
        }
        /// <summary>
        /// 分页显示
        /// </summary>
        /// <returns></returns>
        public async Task<PagedList<Finance>> GetPageListAsync(PageParameter request)
        {
            var result = new PagedList<Finance>
            {
                Items = await _repository.GetAllAsync(Q.ForPage(request.Page, request.PerPage)),
                Total = await _repository.CountAsync()
            };
            return result;
        }
        /// <summary>
        /// 获取财务图像
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<FinanceResult> GetFinanceChartAsync(FinanceRequest request)
        {
            var result = new FinanceResult();
            //获取当前时间
            DateTime dt = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd"));
            DateTime dtNow = DateTime.Now;
            //当前星期几
            int weekNow = Convert.ToInt32(DateTime.Now.DayOfWeek);
            result.HumanAffairsChartDataResult = new List<HumanAffairsChartData>();
            //上月
            var a = await _repository.GetAllAsync(Q.Where(nameof(Finance.FinanceType), request.DataType)
                .WhereDate(nameof(Finance.EnteringDateTime), "<=", dt.AddDays(-dt.Day))
                .WhereDate(nameof(Finance.EnteringDateTime), ">=",
                    dt.AddDays(-dt.Day).AddMonths(1)));
            //本月
            var b = await _repository.GetAllAsync(Q.Where(nameof(Finance.FinanceType), request.DataType)
                .WhereDate(nameof(Finance.EnteringDateTime), "<=", dtNow)
                .WhereDate(nameof(Finance.EnteringDateTime), ">=",
                    dt.AddDays(-dt.Day)));
            //今天
            var c = await _repository.GetAllAsync(Q.Where(nameof(Finance.FinanceType), request.DataType)
                .WhereDate(nameof(Finance.EnteringDateTime), "<=", dtNow)
                .WhereDate(nameof(Finance.EnteringDateTime), ">=", dt));
            //同比增长
            result.ComparedMonthAmount = b.Sum(n => n.Amount) - a.Sum(n => n.Amount);
            if (request.DateType == 1)
                //今天收入
                result.ToDayIncome = c.Sum(n => n.Amount);
            else if (request.DateType == 2)
            {
                var weekDt = dt;
                //本周
                if (dtNow.DayOfWeek.GetHashCode() == 0)
                    weekDt = dt.AddDays(-7);
                else
                    weekDt = dt.AddDays(-dtNow.DayOfWeek.GetHashCode());
                c = await _repository.GetAllAsync(Q.Where(nameof(Finance.FinanceType), request.DataType)
                .WhereDate(nameof(Finance.EnteringDateTime), "<=", dtNow)
                .WhereDate(nameof(Finance.EnteringDateTime), ">=", weekDt));
                //本周收入
                result.ToDayIncome = c.Sum(n => n.Amount);
            }
            //月
            else if (request.DateType == 3)
            {
                var mouthDt = dt;
                mouthDt = dt.AddDays(-dt.Day);
                c = await _repository.GetAllAsync(Q.Where(nameof(Finance.FinanceType), request.DataType)
                .WhereDate(nameof(Finance.EnteringDateTime), "<=", dtNow)
                .WhereDate(nameof(Finance.EnteringDateTime), ">=", mouthDt));
                //本月收入
                result.ToDayIncome = c.Sum(n => n.Amount);
            }
            else if (request.DateType == 4)
            {
                var yearDt = dt;
                yearDt = dt.AddMonths(-dt.Month).AddDays(-dt.Day);
                c = await _repository.GetAllAsync(Q.Where(nameof(Finance.FinanceType), request.DataType)
                .WhereDate(nameof(Finance.EnteringDateTime), "<=", dtNow)
                .WhereDate(nameof(Finance.EnteringDateTime), ">=", yearDt));
                //本年收入
                result.ToDayIncome = c.Sum(n => n.Amount);
            }

            //计算周
            if (request.DateType == 2)
            {
                var beginDat = dt;
                for (int i = 1; i <= 7; i++)
                {
                    var week = (i - 1) * -7;
                    var endDay = beginDat.AddDays(-weekNow + week + 1);
                    var query = Q.NewQuery();
                    var humanAffairsWeekList = await _repository.GetAllAsync(query.Where(nameof(Finance.FinanceType), request.DataType)
                        .WhereDate(nameof(Finance.EnteringDateTime), "<=", beginDat)
                        .WhereDate(nameof(Finance.EnteringDateTime), ">=", endDay));
                    var humanAffairsChartData = new HumanAffairsChartData
                    {
                        NavigationNumber = i,
                        ResultParameter = humanAffairsWeekList.Sum(n => n.Amount)
                    };
                    result.HumanAffairsChartDataResult.Add(humanAffairsChartData);
                    beginDat = endDay;
                }
            }

            //天数
            if (request.DateType == 1)
            {
                var beginDat = dt;
                for (int i = 1; i <= 7; i++)
                {

                    var endDay = beginDat.AddDays(-i);
                    var query = Q.NewQuery();
                    var humanAffairsDayList = await _repository.GetAllAsync(query.Where(nameof(Finance.FinanceType), request.DataType)
                        .WhereDate(nameof(HumanAffairs.EnteringDateTime), "<=", beginDat)
                        .WhereDate(nameof(HumanAffairs.EnteringDateTime), ">=", endDay));
                    var humanAffairsChartData = new HumanAffairsChartData
                    {
                        NavigationNumber = i,
                        ResultParameter = humanAffairsDayList.Sum(n => n.Amount)
                    };
                    result.HumanAffairsChartDataResult.Add(humanAffairsChartData);
                    beginDat = endDay;
                }
            }

            //月
            if (request.DateType == 3)
            {
                var beginDat = dt;
                for (int i = 1; i <= 7; i++)
                {
                    var days = beginDat.Day;
                    var endDay = dt.AddDays(-days).AddMonths(-i);
                    var query = Q.NewQuery();
                    var humanAffairsMonthList = await _repository.GetAllAsync(query.Where(nameof(Finance.FinanceType), request.DataType)
                        .WhereDate(nameof(HumanAffairs.EnteringDateTime), "<=", beginDat)
                        .WhereDate(nameof(HumanAffairs.EnteringDateTime), ">=", endDay));
                    var humanAffairsChartData = new HumanAffairsChartData
                    {
                        NavigationNumber = i,
                        ResultParameter = humanAffairsMonthList.Sum(n => n.Amount)
                    };
                    result.HumanAffairsChartDataResult.Add(humanAffairsChartData);
                    beginDat = endDay;
                }
            }

            //年
            if (request.DateType == 4)
            {
                var beginDat = dt;
                for (int i = 1; i <= 7; i++)
                {
                    var days = beginDat.DayOfYear;
                    var endDay = dt.AddDays(-days).AddYears(-i);
                    var query = Q.NewQuery();
                    var humanAffairsYearList = await _repository.GetAllAsync(query.Where(nameof(Finance.FinanceType), request.DataType)
                        .WhereDate(nameof(HumanAffairs.EnteringDateTime), "<=", beginDat)
                        .WhereDate(nameof(HumanAffairs.EnteringDateTime), ">=", endDay));
                    var humanAffairsChartData = new HumanAffairsChartData
                    {
                        NavigationNumber = i,
                        ResultParameter = humanAffairsYearList.Sum(n => n.Amount)
                    };
                    result.HumanAffairsChartDataResult.Add(humanAffairsChartData);
                    beginDat = endDay;
                }
            }
            return result;
        }
    }
}