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.Log;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Request;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.ApiConfig.Controller
{
    public class DictController :BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerDict _sigerDict;
        private readonly ISigerUserRepository _userRepository;
        private readonly IAccSqlRepository _accSqlRepository;
        public DictController(IUnitOfWork unitOfWork,ISigerDict sigerDict, ISigerUserRepository userRepository, IAccSqlRepository accSqlRepository)
        {
            _unitOfWork = unitOfWork;
            _sigerDict = sigerDict;
            _userRepository = userRepository;
            _accSqlRepository = accSqlRepository;
        }

        [HttpPost]
        public IActionResult FillOption([FromBody]RquestFillOption fillOption)
        {
            try
            {
                var lst = _accSqlRepository.FillOption(fillOption, ProjectId);
                return new ObjectResult(lst);
            }
            catch
            {
                return new ObjectResult(CommonEnum.SystemExcetion);
            }
        }

        /// <summary>
        /// 字典查询
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Getlist(string cat,string dkey,string dval, string dtStart, string dtEnd,int page=1, int pagesize=10)
        {
            var user = _userRepository.Get(UserId);
            Expression<Func<SigerTrDict, bool>> funcat;
            if (user.type == (int)UserType.SuperAdmin)
            {
                funcat = f => f.status == (int)RowState.Valid; 
            }
            else
            {
                funcat = f => f.projectId == ProjectId && f.status == (int)RowState.Valid;
            }
            Expression<Func<SigerTrDict, bool>> funkey = f => true;
            Expression<Func<SigerTrDict, bool>> funval = f => true;
            Expression<Func<SigerTrDict, bool>> funstart = f => true;
            Expression<Func<SigerTrDict, bool>> funend = f => true;
            Expression<Func<SigerTrDict, bool>> funcate = f => true;
            if (!string.IsNullOrEmpty(cat))
                funcate = f => f.cat.Contains(cat);
            if (!string.IsNullOrEmpty(dkey))
                funkey = f => f.dkey.Contains(dkey);
            if (!string.IsNullOrEmpty(dval))
                funval = f => f.dval.Contains(dval);
            if (!string.IsNullOrEmpty(dtStart) && DateTime.TryParse(dtStart, out DateTime start))
            {
                funstart = f => f.createtime > UnixTimeHelper.ConvertDataTimeLong(start);
            }
            if (!string.IsNullOrEmpty(dtEnd) && DateTime.TryParse(dtEnd, out DateTime end))
            {
                funend = f => f.createtime > UnixTimeHelper.ConvertDataTimeLong(end);
            }
            var predicate = funcat.And(funkey).And(funval).And(funval).And(funstart).And(funend).And(funcate);
            var data = _sigerDict.GetPagedList(page, pagesize, predicate);           
            return new PagedObjectResult(data, data.Total, page,pagesize);
        }
        /// <summary>
        ///  添加DICT 字典
        /// </summary>
        /// <param name="dict"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Add([FromBody]RequestDict dict) 
        {
            if (!CheckIsUserCanAlterDict(dict.cat))
            {
                throw new BadRequestException(RequestEnum.ManageCatOnlyBySuperAdministrator);//判断是超级管理员，如果是则不用筛选projectid
            }
            var model = _sigerDict.Get(t => (t.dval == dict.dval && t.dkey == dict.dkey || t.dkey == dict.dkey) && t.projectId == ProjectId
                && t.status == (int)RowState.Valid && t.cat == dict.cat);
            if (model != null)
            {
                throw new BadRequestException(RequestEnum.DataExist);
            }
            _sigerDict.Insert(new SigerTrDict {
                projectId = ProjectId,
                cat = dict.cat,
                dkey = dict.dkey,
                dval = dict.dval,
                createtime = UnixTimeHelper.GetNow()
             });
            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);
        }

        //private void CheckIsUsingDict(string dcat, string dkey)
        //{
        //    bool check = false;
        //    switch (dcat)
        //    {
        //        case AccDictCost.item:
        //            var checkItem = _checkItem.Get(t => t.Item == dkey && t.status == (int)RowState.Valid && t.projectId == ProjectId);
        //            if (checkItem != null)
        //            {
        //                check = true;
        //            }
        //            var bookingItem = _bookingItem.Get(t => t.Item == dkey && t.status == (int)RowState.Valid && t.projectId == ProjectId);
        //            if (bookingItem != null)
        //            {
        //                check = true;
        //            }
        //            break;
        //        case AccDictCost.status:
        //            var outStation = _outStation.Get(t => t.ResultStatus == dkey && t.status == (int)RowState.Valid && t.projectId == ProjectId);
        //            if (outStation != null)
        //                check = true;
        //            break;
        //        case AccDictCost.suppliertype:
        //            var material = _materials.Get(t => t.supplier == dkey && t.status == (int)RowState.Valid && t.projectId == ProjectId);
        //            if (material != null)
        //                check = true;
        //            break;
        //    }
        //    if (check)
        //    {
        //        throw new BadRequestException(RequestEnum.DictIsUsingDonotBeAlter);
        //    }
        //}

        /// <summary>
        /// 修改字典
        /// </summary>
        /// <param name="dict"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Modify([FromBody]RequestModifyDict dict)
        {
            if (!CheckIsUserCanAlterDict(dict.cat))
            {
                throw new BadRequestException(RequestEnum.ManageCatOnlyBySuperAdministrator);
            }
            var newObj = _sigerDict.Get(dict.id);
            if (newObj==null)
                throw new BadRequestException(CommonEnum.RecordNotFound);
            var model = _sigerDict.Get(t => (t.dval == dict.dval && t.dkey == dict.dkey || t.dkey == dict.dkey) && t.projectId == ProjectId && t.status == (int)RowState.Valid
                && t.cat == dict.cat && t.id != newObj.id);
            if (model != null)
            {
                throw new BadRequestException(RequestEnum.DataExist);
            }

            newObj.dval = dict.dval;
            newObj.dkey = dict.dkey;
            newObj.cat = dict.cat;
            _sigerDict.Update(newObj);
            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);
        }
        [HttpGet]
        public IActionResult Delete(int id)
        {
            var newObj = _sigerDict.Get(id);
            if (newObj == null)
                throw new BadRequestException(CommonEnum.RecordNotFound);
            if (!CheckIsUserCanAlterDict(newObj.cat))
            {
                throw new BadRequestException(RequestEnum.ManageCatOnlyBySuperAdministrator);
            }
            //CheckIsUsingDict(newObj.cat, newObj.dkey);
            newObj.status = (int)RowState.Invalid;
            _sigerDict.Update(newObj);
            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);
        }
        [HttpGet]
        public IActionResult GetDictByCat(string cat)
        {
            var list = new List<SigerTrDict>(); 
            var accdict = new AccDictCost();
            var propertyInfo = accdict.GetType().GetField(cat);
            if(propertyInfo == null)
            {
                //如果不在AccDictCost中，表示是超级管理员维护的数据，筛选非超级管理员添加的数据。
                list = _sigerDict.GetList(f => f.cat == cat && f.status == (int)RowState.Valid).OrderBy(q => q.id).ToList();
            }
            else
            {
                //在AccDictCost中表示用户自己添加维护的数据
                list = _sigerDict.GetList(f => f.cat == cat && f.status == (int) RowState.Valid && f.projectId == ProjectId).OrderBy(q => q.id).ToList();
            }
            return new ObjectResult(list);
        }

        [HttpGet]
        public IActionResult GetDictByCatOrderByLetter(string cat)
        {
            var list = new List<SigerTrDict>();
            var accdict = new AccDictCost();
            var propertyInfo = accdict.GetType().GetField(cat);
            if (propertyInfo == null)
            {
                list = _sigerDict.GetList(f => f.cat == cat && f.status == (int)RowState.Valid).OrderBy(q => q.id).ToList();
            }
            else
            {
                list = _sigerDict.GetList(f => f.cat == cat && f.status == (int)RowState.Valid && f.projectId == ProjectId).OrderBy(q => q.id).ToList();
            }
            var res = new List<ResponseDict>();
            foreach(var dict in list)
            {
                var model = Mapper<SigerTrDict, ResponseDict>.Map(dict);
                model.letter = PinYinHelper.ToPinYin(model.dval);
                res.Add(model);
            }
            var response = res.OrderBy(t => t.letter).ToList();
            return new ObjectResult(response);
        }

        private bool CheckIsUserCanAlterDict(string cat)
        {
            var accdict = new AccDictCostNoProjectId();
            var propertyInfo = accdict.GetType().GetField(cat);
            var user = _userRepository.Get(UserId);
            if (user.type == (int)UserType.SuperAdmin)
            {
                return true;
            }
            if (propertyInfo != null)
            {
                return false;//不能进行增删改查操作
            }
            return true;//可以维护的数据
        }

        [HttpGet]
        public IActionResult ExportAll(string cat, string dkey, string dval, string dtStart, string dtEnd)
        {
            var fileSetting = Config<FileSettings>.Get();
            if (fileSetting == null)
            {
                throw new BadRequestException(CommonEnum.GetCommCfgFailed);
            }
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);

            Expression<Func<SigerTrDict, bool>> Func = f => f.projectId == ProjectId && f.status == (int)RowState.Valid;
            Expression<Func<SigerTrDict, bool>> Funcat = f => true;
            Expression<Func<SigerTrDict, bool>> Funkey = f => true;
            Expression<Func<SigerTrDict, bool>> Funval = f => true;
            Expression<Func<SigerTrDict, bool>> Funstart = f => true;
            Expression<Func<SigerTrDict, bool>> Funend = f => true;
            Expression<Func<SigerTrDict, bool>> Funcate = f => true;
            if (!string.IsNullOrEmpty(cat))
                Funcate = f => f.cat.Contains(cat);
            if (!string.IsNullOrEmpty(dkey))
                Funkey = f => f.dkey.Contains(dkey);
            if (!string.IsNullOrEmpty(dval))
                Funval = f => f.dval.Contains(dval);
            if (!string.IsNullOrEmpty(dtStart) && DateTime.TryParse(dtStart, out DateTime start))
            {
                Funstart = f => f.createtime > UnixTimeHelper.ConvertDataTimeLong(start);
            }
            if (!string.IsNullOrEmpty(dtEnd) && DateTime.TryParse(dtEnd, out DateTime end))
            {
                Funend = f => f.createtime > UnixTimeHelper.ConvertDataTimeLong(end);
            }
            var predicate = Func.And(Funcat).And(Funkey).And(Funval).And(Funstart).And(Funend).And(Funcate);
            var query = _sigerDict.GetList(predicate);

            var dataList = new List<DictTemplate>();
            foreach (var item in query)
            {
                dataList.Add(new DictTemplate
                {
                    cat = item.cat,
                    dkey = item.dkey,
                    dval = item.dval,
                    creattime = UnixTimeHelper.ConvertIntDateTime(item.createtime)
                });
            }
            if (dataList.Any())
            {
                EpPlusExcelHelper<DictTemplate> helper = null;
                try
                {
                    helper = new EpPlusExcelHelper<DictTemplate>();
                    var temporaryFileName = $"字典_DictInfo_{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("ExportDict failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }

            throw new BadRequestException(CommonEnum.Fail);
        }
    }
}