using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.WmsRepository.Entities;
using Siger.Middlelayer.WmsRepository.Repositories.Interface;
using Siger.Middlelayer.WmsRepository.Response;

namespace Siger.ApiWMS.Controllers
{
    /// <summary>
    /// 库存操作历史
    /// </summary>
    public class StockHistoryController : BaseController
    {
        private readonly Isiger_wms_stock_detailRepository trace;
        private readonly Isiger_wms_stock_changeRepository changeHistory;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="trace"></param>
        /// <param name="changeHistory"></param>
        public StockHistoryController(Isiger_wms_stock_detailRepository trace, Isiger_wms_stock_changeRepository changeHistory)
        {
            this.trace = trace;
            this.changeHistory = changeHistory;
        }



        /// <summary>
        /// 库存详情
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="type"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IActionResult GetStockDetails(string filter, SearchType type, string start, string end,int page,int pageSize)
        {
            Utility.CheckPage(page, pageSize);
            DateTime.TryParse(start, out DateTime startTime);
            DateTime.TryParse(end, out DateTime endTime);

            var result = trace.GetStockDetails(ProjectId,filter, type, startTime, endTime, page, pageSize, out int totalCount);
            return new PagedObjectResult(result, totalCount,page,pageSize);
        }

        /// <summary>
        /// 导出库存详情
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="type"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public IActionResult ExportStockDetails(string filter, SearchType type, string start, string end)
        {
            DateTime.TryParse(start, out DateTime startTime);
            DateTime.TryParse(end, out DateTime endTime);

            var result = trace.GetStockDetails(ProjectId, filter, type, startTime, endTime, 0, 0, out int totalCount,false);

            //获取配置信息
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            string temporaryFileName = $"stockDetailsinfo_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<ResponseStockDetail>();
            try
            {
                helper.GenerateExcel(result, fileName,true);

                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ExportStock failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }

        /// <summary>
        /// 库存变化图表
        /// </summary>
        /// <param name="storage"></param>
        /// <param name="materialid"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetStockChangeChart(int storage,int materialid,string start, string end)
        {
            DateTime.TryParse(start, out DateTime startTime);
            DateTime.TryParse(end, out DateTime endTime);

            if(startTime>=endTime)
            {
                throw new BadRequestException(RequestEnum.StartTimeGtEndTime);
            }

            Expression<Func<siger_wms_stock_change, bool>> storageExp = f => true;
            Expression<Func<siger_wms_stock_change, bool>> materialExp = f => true;
            Expression<Func<siger_wms_stock_change, bool>> startExp = f => true;
            Expression<Func<siger_wms_stock_change, bool>> endExp = f => true;
            Expression<Func<siger_wms_stock_change, bool>> commonExp = f => f.state == (int)RowState.Valid && f.projectid == ProjectId;
            if(storage!=0)
            {
                storageExp = f => f.storageid == storage;
            }
            if (materialid != 0)
            {
                materialExp = f => f.inventoryid == materialid;
            }
            if (startTime != null&& startTime!=DateTime.MinValue)
            {
                startExp = f => f.time >= startTime;
            }
            if (endTime != null && endTime != DateTime.MinValue)
            {
                endExp = f => f.time <= endTime;
            }
            var finalExp = commonExp.And(storageExp).And(materialExp).And(startExp).And(endExp);
            var data = changeHistory.GetList(finalExp).OrderBy(f=>f.time);

            //汇总数据
            var result = new ResponseStockChangeHistory
            {
                //qty
                y = new List<int>(),
                //time
                x = new List<string>()
            };
            if(data.Any())
            {
                var day = data.Min(f => f.time).Date;
                var min = day;
                var tmpCount = 0;
                foreach (var item in data)
                {
                    if (item.time.Date != day)
                    {
                        result.y.Add(tmpCount);
                        result.x.Add(day.ToString(UnixTimeHelper.DateFormat));
                        day = item.time.Date;
                        tmpCount = item.count;
                    }
                    else
                    {
                        tmpCount += item.count;
                    }
                }
                result.y.Add(tmpCount);
                result.x.Add(day.ToString(UnixTimeHelper.DateFormat));

                var minCount = result.y.First();

                //填充小于查到数据最小时间的内容
                if (min.Date != startTime.Date)
                {
                    var tmpDay = min.Date.AddDays(-1);

                    while (tmpDay >= startTime.Date)
                    {
                        result.y.Insert(0, minCount);
                        result.x.Insert(0, tmpDay.ToString(UnixTimeHelper.DateFormat));
                        tmpDay = tmpDay.AddDays(-1);
                    }
                }
                //填充大于
                if (day.Date != endTime.Date)
                {
                    var tmpDay = day.Date;
                    while(tmpDay.Date!=endTime.Date)
                    {
                        tmpDay= tmpDay.AddDays(1);
                        result.y.Add(tmpCount);
                        result.x.Add(tmpDay.ToString(UnixTimeHelper.DateFormat));
                        tmpDay.AddDays(1);
                    }
                }
            }
            else
            {
                //判断是否有历史数据
                var tmpExp = commonExp.And(storageExp).And(materialExp);
                var tmpData = changeHistory.GetList(tmpExp).OrderByDescending(f => f.time).FirstOrDefault();
                int count = 0;
                if(tmpData!=null)
                {
                    count = tmpData.count;
                }
                for (var i = startTime; i < endTime; i=i.AddDays(1))
                {
                    result.y.Add(count);
                    result.x.Add(i.ToString(UnixTimeHelper.DateFormat));
                }
            }
            //整理数据
            var tmpResult= new ResponseStockChangeHistory
            {
                //qty
                y = new List<int>(),
                //time
                x = new List<string>()
            };
            DateTime lastDay = startTime;
            for (int i = 0; i < result.x.Count; i++)
            {
                if (result.x[i] == lastDay.ToString(UnixTimeHelper.DateFormat))
                {
                    tmpResult.x.Add(result.x[i]);
                    tmpResult.y.Add(result.y[i]);
                    lastDay = lastDay.AddDays(1);
                }
                else
                {
                    while(lastDay.ToString(UnixTimeHelper.DateFormat)!= result.x[i])
                    {
                        tmpResult.x.Add(lastDay.ToString(UnixTimeHelper.DateFormat));
                        tmpResult.y.Add(result.y[i-1]);
                        lastDay = lastDay.AddDays(1);
                    }
                    tmpResult.x.Add(result.x[i]);
                    tmpResult.y.Add(result.y[i]);
                    lastDay = lastDay.AddDays(1);
                }
            }
            return new ObjectResult(tmpResult);
        }
    }
}