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

namespace Siger.ApiACC.Controllers
{
    public class RoutingOutStationController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerRoutingOutStation _sigerRoutingOut;
        private readonly ISigerDict _sigerDict;
        private readonly ISigerRoutingInStation _sigerRoutingIn;
        private readonly ISigerProjectLevelSectionRepository _sigerProjectLevelSection;
        private readonly ISigerRoutingEventNo _routingEventNo;

        public RoutingOutStationController(IUnitOfWork unitOfWork, ISigerRoutingOutStation sigerRoutingOutStation, ISigerDict sigerDict, ISigerRoutingInStation sigerRoutingIn
            , ISigerProjectLevelSectionRepository sigerProjectLevelSection, ISigerRoutingEventNo routingEventNo)
        {
            _unitOfWork = unitOfWork;
            _sigerRoutingOut = sigerRoutingOutStation;
            _sigerDict = sigerDict;
            _sigerRoutingIn = sigerRoutingIn;
            _sigerProjectLevelSection = sigerProjectLevelSection;
            _routingEventNo = routingEventNo;
        }
        [HttpGet]
        public IActionResult Getlist(int line, int station, int eventno, string status, int page = 1, int pagesize = 10)
        {
            var data = _sigerRoutingOut.GetRoutingOutStationPage(ProjectId, line, station, eventno, status, page, pagesize);
            return new PagedObjectResult(data.Data, data.Total, page, pagesize);
        }

        [HttpPost]
        public IActionResult Add([FromBody]RequestRoutingOutStation outStation)
        {
            var eveno = _routingEventNo.Get(f => f.projectId == ProjectId && f.EventNo == outStation.eventno);
            if (eveno == null)
                throw new BadRequestException(AccEnum.Busi_EventNo_Null);
            if (_sigerRoutingOut.IsExist(t => t.Line == outStation.line && t.Station == outStation.station && t.EventNo == outStation.eventno && t.status == (int)RowState.Valid && t.projectId == ProjectId))
            {
                throw new BadRequestException(RequestEnum.RoutingOutExist);
            }
            var outState = GetStatus(outStation.station, eveno.Descr);
            if (_sigerRoutingOut.IsExist(t => t.ResultStatus == outState && t.status == (int)RowState.Valid && t.projectId == ProjectId))
            {
                throw new BadRequestException(RequestEnum.RoutingOutStatusExist);
            }

            _sigerRoutingOut.Insert(new SigerTrRoutingOutStation
            {
                Line = outStation.line,
                Station = outStation.station,
                ResultStatus = outState,
                projectId = ProjectId,
                EventNo = outStation.eventno
            });
            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);
        }
        [HttpPost]
        public IActionResult Modify([FromBody]RequestUpdateRoutingOutStation outStation)
        {
            var NewObj = _sigerRoutingOut.Get(outStation.id);
            if (NewObj == null)
                throw new BadRequestException(CommonEnum.RecordNotFound);

            if (_sigerRoutingOut.IsExist(t => t.Line == outStation.line && t.Station == outStation.station && t.EventNo == outStation.eventno && t.id != NewObj.id && t.status == (int)RowState.Valid && t.projectId == ProjectId))
            {
                throw new BadRequestException(RequestEnum.RoutingOutExist);
            }
           
            NewObj.Line = outStation.line;
            NewObj.Station = outStation.station;
            _sigerRoutingOut.Update(NewObj);
            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);
        }
        [HttpGet]
        public IActionResult Delete(int id)
        {
            var NewObj = _sigerRoutingOut.Get(id);
            if (NewObj == null)
                throw new BadRequestException(CommonEnum.RecordNotFound);

            var routin = _sigerRoutingIn.Get(t => t.ResultStatus == NewObj.ResultStatus && t.status == (int)RowState.Valid && t.projectId == ProjectId);
            if (routin != null && NewObj.EventNo == (int)EventNo_Status.Success)
                throw new BadRequestException(RequestEnum.IsUsedNotDelete);//正在使用，不能删除


            NewObj.status = (int)RowState.Invalid;
            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpGet]
        public IActionResult exportAll(int line, int station, int eventno, string status)
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);

            Expression<Func<SigerTrRoutingOutStation, bool>> Funcat = f => f.projectId == ProjectId && f.status == RowState.Valid.GetHashCode();
            Expression<Func<SigerTrRoutingOutStation, bool>> Funkey = f => true;
            Expression<Func<SigerTrRoutingOutStation, bool>> Funline = f => true;
            Expression<Func<SigerTrRoutingOutStation, bool>> Funeventno = f => true;
            Expression<Func<SigerTrRoutingOutStation, bool>> Funstatus = f => true;
            if (line > 0)
                Funline = f => f.Line == line;
            if (station > 0)
                Funkey = f => f.Station == station;
            if (eventno != 0)
                Funeventno = f => f.EventNo == eventno;
            if (!string.IsNullOrEmpty(status) && status != "0")
                Funstatus = f => f.ResultStatus == status;
            var predicate = Funcat.And(Funkey).And(Funline).And(Funeventno).And(Funstatus);
            var Data = _sigerRoutingOut.GetList(predicate).ToList();
            if (!Data.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var dataList = new List<RoutingOutStationTemplate>();
            foreach (var item in Data)
            {
                var lines = _sigerProjectLevelSection.Get(t => t.id == item.Line && t.projectid == ProjectId && t.status == (int)RowState.Valid);
                var stations = _sigerProjectLevelSection.Get(t => t.id == item.Station && t.projectid == ProjectId && t.status == (int)RowState.Valid);
                dataList.Add(new RoutingOutStationTemplate
                {
                    status = _sigerDict.GetDictValue(ProjectId, AccDictCost.status, item.ResultStatus),
                    line = lines != null ? lines.title : "",
                    station = stations != null ? stations.title : "",
                    eventno = _sigerDict.GetDictValue(ProjectId, AccDictCostNoProjectId.eventno, item.EventNo.ToStr())
                });
            }
            if (dataList.Any())
            {
                EpPlusExcelHelper<RoutingOutStationTemplate> helper = null;
                try
                {
                    helper = new EpPlusExcelHelper<RoutingOutStationTemplate>();
                    var temporaryFileName = $"出站维护模板_RoutingOutStationInfo_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
                    helper.GenerateExcel(dataList, Path.Combine(rootDir, temporaryFileName));
                    return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
                }
                catch (Exception e)
                {
                    Logger.WriteLineError("ExportRoutingOutStation failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }

            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpGet]
        public IActionResult GetStatus(int line, int station, string eventno)
        {
            var model = _sigerRoutingOut.Get(t => t.Line == line && t.Station == station && t.EventNo == eventno.ToInt() && t.projectId == ProjectId && t.status == (int)RowState.Valid);
            if (model != null)
            {
                return new ObjectResult(model.ResultStatus);
            }

            throw new BadRequestException(CommonEnum.RecordNotFound);
        }

        [HttpGet]
        public IActionResult GetEventNoList(int line, int station)
        {
            var eventno = _sigerRoutingOut.GetList(t => t.Line == line && t.Station == station && t.projectId == ProjectId && t.status == (int)RowState.Valid).ToList();
            var response = new List<ResponseIdText>();
            if (eventno.Any())
            {
                foreach (var item in eventno)
                {
                    var eveno = _routingEventNo.Get(f=>f.EventNo==item.EventNo && f.projectId==ProjectId);
                    response.Add(new ResponseIdText
                    {
                        id = item.EventNo.ToStr(),
                        Text= eveno!=null?eveno.Descr:item.EventNo.ToStr()
                    });
                }
            }
            return new ObjectResult(response);
        }
        /// <summary>
        /// 出站状态
        /// </summary>
        /// <param name="sectionId"></param>
        /// <param name="even"></param>
        /// <returns></returns>
        private string GetStatus(int sectionId,string even)
        {
            var section = _sigerProjectLevelSection.Get(f => f.id == sectionId);
            if (section == null)
                return Guid.NewGuid().ToString();
            var str = $"{section.id}-{section.title}->{even}";
            int i = 0;
            while (i < 100)
            {
                i++;
                if (!_sigerRoutingOut.IsExist(f => f.Station == sectionId && f.ResultStatus == str))
                    break;
                str += $"-{i}";
            }

            return str;
        }
    }
}