using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Dapper;
using Siger.Middlelayer.DashboardRepository.Entities;
using Siger.Middlelayer.DashboardRepository.Repositories.Interface;
using Siger.Middlelayer.DashboardRepository.Request;
using Siger.Middlelayer.DashboardRepository.Response;
using Siger.Middlelayer.KpiRespository.Repositories.Interface;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Utility.Helpers;

namespace Siger.ApiDashboard.Controllers
{
    public class DashboardCnConfigController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IDashboardCnSetRepository _cnSetRepository;
        private readonly ISigerProjectFactoryRepository _factoryRepository;
        private readonly ISigerKpiTasklist _kpiTasklist;
        private readonly IDashboardLevelRepository _dashboardLevel;
        private readonly ISigerProjectLevelSectionRepository _sigerProjectLevelSection;
        private readonly IDashboardFactoryChanel _dashboardFactoryChanel;
        private readonly IDashboardTotalSetRepository _totalSetRepository;

        /// <inheritdoc />
        public DashboardCnConfigController(IUnitOfWork unitOfWork, IDashboardCnSetRepository cnSetRepository, ISigerProjectFactoryRepository factoryRepository,
            ISigerKpiTasklist kpiTasklist, IDashboardLevelRepository dashboardLevel, ISigerProjectLevelSectionRepository sigerProjectLevelSection, 
            IDashboardFactoryChanel dashboardFactory, IDashboardTotalSetRepository totalSetRepository)
        {
            _unitOfWork = unitOfWork;
            _cnSetRepository = cnSetRepository;
            _factoryRepository = factoryRepository;
            _kpiTasklist = kpiTasklist;
            _dashboardLevel = dashboardLevel;
            _sigerProjectLevelSection = sigerProjectLevelSection;
            _dashboardFactoryChanel = dashboardFactory;
            _totalSetRepository = totalSetRepository;
        }

        [HttpPost]
        public IActionResult SetCnConfig([FromBody]RequestSetCnConfig request)
        {
            var dt = DateTime.MinValue;
            if (!string.IsNullOrWhiteSpace(request.date))
            {
                var date = request.date.ToDateTime().Date;
                if (date != DateTime.Now.Date)
                {
                    dt = date;
                }
            }
            var config = _cnSetRepository.Get(q => q.status == (int)RowState.Valid && q.project_id == ProjectId);
            if (config == null)
            {
                var entity = new siger_dashboard_cn_set
                {
                    date = dt,
                    level1 = request.level1,
                    level2 = request.level2,
                    level3 = request.level3,
                    level4 = request.level4,
                    level5 = request.level5,
                    level6 = request.level6,
                    oee1 = request.oee1.ToDouble(),
                    oee2 = request.oee2.ToDouble(),
                    oee3 = request.oee3.ToDouble(),
                    project_id = ProjectId
                };
                _cnSetRepository.Insert(entity);
            }
            else
            {
                config.date = dt;
                config.level1 = request.level1;
                config.level2 = request.level2;
                config.level3 = request.level3;
                config.level4 = request.level4;
                config.level5 = request.level5;
                config.level6 = request.level6;
                config.oee1 = request.oee1.ToDouble();
                config.oee2 = request.oee2.ToDouble();
                config.oee3 = request.oee3.ToDouble();
                _cnSetRepository.Update(config);
            }

            if (_unitOfWork.Commit() > 0)
            {
                //重新请求接口
                try
                {
                    return new ObjectResult(GetSummary(dt));
                }
                catch
                {
                    return new ObjectResult(GetDefaultSummary());
                }
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        private List<ResponseGetCnSummary> GetDefaultSummary()
        {
            var responses = new List<ResponseGetCnSummary>();
            var factories = _factoryRepository.GetList(q => q.status == (int)RowState.Valid).OrderBy(q => q.sorting).ToList();
            var days = 60;
            foreach (var factory in factories)
            {
                AddDefaultFactory(responses, factory.name, days);
                days += 20;
            }

            return responses;
        }

        [HttpGet]
        public IActionResult GetCnConfig()
        {
            var config = _cnSetRepository.Get(q => q.project_id == ProjectId && q.status == (int)RowState.Valid);
            if (config == null)
            {
                return new ObjectResult(new siger_dashboard_cn_set { date = DateTime.Now });
            }

            config.date = config.date == DateTime.MinValue ? DateTime.Now : config.date;
            return new ObjectResult(config);
        }

        [HttpGet]
        public IActionResult GetCurrentSummary(string datetime = "")
        {
            var ret = new List<ResponseGetCnSummary>();
            if (datetime == "")
            {
                ret = GetSummary(DateTime.MinValue);
            }
            else
            {
                ret = GetSummary(datetime.ToDateTime());
            }
            ret.ForEach(item => { item.rate = item.rate > 100 ? 100 : item.rate; });
            return new ObjectResult(ret);
        }

        [HttpGet]
        public List<ResponseGetCnSummary> GetSummary(DateTime dt)
        {
            var monthStart = DateTime.Parse(dt.ToString(ParameterConstant.MouthFirstDay));
            var monthEnd = DateTime.Parse(monthStart.AddMonths(1).ToString(ParameterConstant.MouthFirstDay));

            var responses = new List<ResponseGetCnSummary>();
            var factories = _factoryRepository.GetList(q => q.status == (int)RowState.Valid).OrderBy(q => q.sorting).ToList();
            var days = 60;
            foreach (var factory in factories.Where(q => q.sorting > 0))
            {
                AddDefaultFactory(responses, factory.name, days);
                days += 20;
            }

            var totalset = _totalSetRepository.Get(q => q.project_id == ProjectId);

            var safeDayCount = _kpiTasklist.GetKpiSafeDay(totalset?.safe_day.ToInt() ?? 0, ProjectId).ToStr().ToInt();
            var response = new ResponseGetCnSummary
            {
                actual = 0,
                theory = 0,
                delivery = _kpiTasklist.GetKpiValue(totalset?.delivery_rate.ToInt() ?? 0, ProjectId, monthStart, monthEnd).ToStr().ToInt(),
                delivery_target = _kpiTasklist.GetKpiTarget(totalset?.delivery_rate.ToInt() ?? 0, ProjectId).ToStr().ToInt(),
                name = factories.First(q => q.sorting == 0).name,
                quanlity = _kpiTasklist.GetKpiComplaint(totalset?.complaint_count.ToInt() ?? 0, ProjectId, monthStart, monthEnd).ToStr().ToInt(),
                safeday = safeDayCount,
                minsafeday = safeDayCount,
                projectId = ProjectId
            };

            var datas = _kpiTasklist.GetKpiComplaints(totalset?.complaint_count.ToInt() ?? 0, ProjectId).Where(q => q.Busidate >= monthStart
                                                                                                                    && q.Busidate < monthEnd);
            foreach (var data in datas)
            {
                var complaint = new ResponseComplaint
                {
                    datetime = data.Busidate.ToString(ParameterConstant.DateFormat),
                    remark = data.Remark.ToStr()
                };
                response.complaints.Add(complaint);
            }

            var dateRange = DateTimeHelper.GetDateTimeRange(dt.ToString());
            var outputs = GetTheoryLine(dateRange.StarTime, dateRange.EndTime);
            if (outputs.Count > 1)
            {
                response.actual = outputs[0];
                response.theory = Math.Round(outputs[1], 0);
                response.rate = Math.Round(outputs[1] <= 0 ? 0 : outputs[0] * 100 / outputs[1], 2);
            }

            responses.Insert(0, response);
            return responses;
        }

        //[HttpGet]
        //public IActionResult GetComplaints(int projectId)
        //{
        //    var totalset = _totalSetRepository.Get(q => q.project_id == ProjectId);
        //    var datas = _kpiTasklist.GetKpiComplaints(totalset?.complaint_count.ToInt() ?? 0, ProjectId);
        //    var responses = new List<ResponseComplaint>();
        //    foreach (var data in datas)
        //    {
        //        var response = new ResponseComplaint
        //        {
        //            datetime = data.Busidate.ToString(ParameterConstant.DateFormat),
        //            remark = data.Remark
        //        };
        //        responses.Add(response);
        //    }
        //    return new ObjectResult(responses);
        //}

        private List<double> GetTheoryLine(DateTime dtStart, DateTime dtEnd)
        {
            var list = new List<double> { };
            var yieldRepository = new LocationYieldRepository(CompanyId, ProjectId);
            var levelline = _dashboardFactoryChanel.GetDashboardChanel(ProjectId);

            var yiedTotal = 0;
            var targetTotal = 0d;
            foreach (var line in levelline)
            {
                var stations = _sigerProjectLevelSection.GetAccStationByline(ProjectId, line.id).Select(s => s.id).ToList();
                var bottleMachines = _dashboardLevel.GetBottleSection(stations, ProjectId).ToList();
                if (!bottleMachines.Any())
                    continue;
                var bottle = bottleMachines.FirstOrDefault();
                var yields = yieldRepository.GetLocationYields(bottleMachines, dtStart, dtEnd).ToList();
                var yiedlineTotal = yields.Sum(f => f.yield);
                yiedTotal += yiedlineTotal;
                DateTime dtDay;
                for (dtDay = dtStart; dtDay.CompareTo(dtEnd) < 0; dtDay = dtDay.AddHours(1))
                {
                    var stepStarTime = dtDay;
                    var stepEndTime = dtDay.AddHours(1).AddSeconds(-1);
                    var targetVal = _dashboardLevel.BottleProductTarget(ProjectId, bottle, stepStarTime, stepEndTime);
                    if (targetVal == null)
                        continue;
                    targetTotal += targetVal.Val;
                }
            }
            list.Add(yiedTotal);
            list.Add(targetTotal);
            return list;
        }

        private void AddDefaultFactory(List<ResponseGetCnSummary> summaries, string name, int days)
        {
            summaries.Add(new ResponseGetCnSummary
            {
                actual = 600,
                theory = 650,
                delivery = 100,
                delivery_target = 100,
                name = name,
                rate = Math.Round(600 * 100.0 / 650, 0),
                safeday = days,
                quanlity = 0
            });
        }

        [HttpGet]
        public IActionResult GetTotalSet()
        {
            var set = _totalSetRepository.Get(q => q.project_id == ProjectId && q.status == (int) RowState.Valid);
            var entity = new ResponseGetTotalSet();
            if (set != null)
            {
                entity.complaint_count = set.complaint_count.ToStr();
                entity.delivery_rate = set.delivery_rate.ToStr();
                entity.factory_ftq = set.factory_ftq.ToStr();
                entity.factory_oee = set.factory_oee.ToStr();
                entity.passway_ftq = set.passway_ftq.ToStr();
                entity.passway_oee = set.passway_oee.ToStr();
                entity.safe_day = set.safe_day.ToStr();
            }
            return new ObjectResult(entity);
        }

        [HttpPost]
        public IActionResult SetTotalSet([FromBody]ResponseGetTotalSet request)
        {
            var set = _totalSetRepository.Get(q => q.project_id == ProjectId && q.status == (int)RowState.Valid);
            if (set != null)
            {
                set.complaint_count = request.complaint_count.ToStr();
                set.delivery_rate = request.delivery_rate.ToStr();
                set.factory_ftq = request.factory_ftq.ToStr();
                set.factory_oee = request.factory_oee.ToStr();
                set.passway_ftq = request.passway_ftq.ToStr();
                set.passway_oee = request.passway_oee.ToStr();
                set.safe_day = request.safe_day.ToStr();
                _totalSetRepository.Update(set);
            }
            else
            {
                set = new siger_dashboard_total_set
                {
                    project_id = ProjectId,
                    complaint_count = request.complaint_count.ToStr(),
                    delivery_rate = request.delivery_rate.ToStr(),
                    factory_ftq = request.factory_ftq.ToStr(),
                    factory_oee = request.factory_oee.ToStr(),
                    passway_ftq = request.passway_ftq.ToStr(),
                    passway_oee = request.passway_oee.ToStr(),
                    safe_day = request.safe_day.ToStr()
                };
                _totalSetRepository.Insert(set);
            }

            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }
    }
}