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

namespace Siger.ApiConfig.Controller
{
    public class ProjectLevelSectionController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        private readonly ISigerProjectLevelRepository _levelRepository;
        private readonly ISigerProjectLevelSectionMachineRepository _levelSectionMachineRepository;
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly ISigerProjectMachineAttributionRepository _machineAttributionRepository;
        private readonly IWorkingCalendarRepository _calendarRepository;
        public ProjectLevelSectionController(IUnitOfWork unitOfWork, ISigerProjectLevelSectionRepository levelSectionRepository,
            ISigerProjectLevelRepository levelRepository, ISigerProjectLevelSectionMachineRepository levelSectionMachineRepository,
            ISigerProjectMachineRepository machineRepository, ISigerProjectMachineAttributionRepository machineAttributionRepository,
            IWorkingCalendarRepository calendarRepository)
        {
            _unitOfWork = unitOfWork;
            _levelRepository = levelRepository;
            _levelSectionRepository = levelSectionRepository;
            _levelSectionMachineRepository = levelSectionMachineRepository;
            _machineRepository = machineRepository;
            _machineAttributionRepository = machineAttributionRepository;
            _calendarRepository = calendarRepository;
        }

        [HttpGet]
        public IActionResult GetLevelSectionTree()
        {
            var list = _levelSectionRepository.GetLevelSectionTree(ProjectId);

            return new ObjectResult(list);
        }

        [HttpGet]
        public IActionResult GetLevelSectionTreeChildren(int canselected = 0)
        {
            var list = _levelSectionRepository.GetLevelSectionTree(ProjectId, canselected);

            var response = new ResponseLevelSectionChildren(ConvertToTree(list));

            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult GetLevelSectionTreeForTpm()
        {
            var list = _levelSectionRepository.GetLevelSectionTree(ProjectId).ToList();

            var lastSectionIds = _levelSectionMachineRepository.GetLastSection(ProjectId).Select(m => m.id).ToList();
            var machine_section_id = list.Any() ? list.Max(t => t.id) + 1 : 0;
            foreach (var section in lastSectionIds)
            {
                var machines = _machineAttributionRepository.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid && f.attribution == 1 && f.station == section);
                //_machineRepository.GetMachinesByLastSectionId(section, ProjectId).ToList();
                foreach (var machine in machines)
                {
                    list.Add(new LevelSectionTree
                    {
                        id = machine_section_id++,
                        name = machine.name,
                        title = machine.name,
                        disabled = false,
                        pid = section,
                        open = true,
                        machineid = machine.machine
                    });
                }
            }

            return new ObjectResult(ConvertToTreeForTpm(list));
        }

        [HttpPost]
        public IActionResult GetLevelSectionTreeForApp([FromBody]RequestGetLevelSection req)
        {
            var list = new List<LevelSectionTree>();
            var lastSectionIds = _levelSectionMachineRepository.GetLastSection(ProjectId).Select(m => m.id);
            if (req.ismine.ToStr() == "true")
            {
                var myMachineIds = _calendarRepository.GetList(q => q.date.Date == DateTime.Now.Date && q.project_id == ProjectId && q.user_mid == UserId
                && q.status == (int)RowState.Valid).Select(q => q.machine_id).Distinct().ToList();
                var myStaions = _machineAttributionRepository.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid
                && f.attribution == 1 && myMachineIds.Contains(f.machine)).Select(q => q.station).Distinct().ToList();
                var sectionList = _levelSectionMachineRepository.GetSectionTreeBySectionIds(myStaions, ProjectId).ToList();
                foreach (var section in sectionList)
                {
                    list.Add(new LevelSectionTree
                    {
                        id = section.id,
                        pid = section.parentid,
                        name = section.title,
                        open = true
                    });
                }
            }
            else
            {
                list = _levelSectionRepository.GetLevelSectionTree(ProjectId).ToList();
            }

            var secondLevelId = _levelSectionMachineRepository.GetSecondLevelId(ProjectId);
            var sectionTree = new List<ResponseLevelSectionTreeList>();
            foreach (var levelSection in list)
            {
                if (lastSectionIds.Contains(levelSection.id))
                {
                    var machineid = 0;
                    var machines = _machineAttributionRepository.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid && f.attribution == 1 && f.station == levelSection.id);
                    if (machines.Any())
                    {
                        var mids = machines.Select(s => s.machine).Distinct().ToList();
                        var machineData = _machineRepository.GetList(f => mids.Contains(f.id));
                        machineid = machineData.FirstOrDefault(f => f.category == 1)?.id ?? machineData.FirstOrDefault()?.id ?? 0;
                    }
                    sectionTree.Add(new ResponseLevelSectionTreeList
                    {
                        id = levelSection.id,
                        name = levelSection.name,
                        open = true,
                        pid = levelSection.pid,
                        isleaf = true,
                        machineid = machineid
                    });
                }
                else
                {
                    sectionTree.Add(new ResponseLevelSectionTreeList
                    {
                        id = levelSection.id,
                        name = levelSection.name,
                        open = levelSection.levelId != secondLevelId,
                        pid = levelSection.pid,
                    });
                }
            }

            return new ObjectResult(new ResponseLevelSectionList
            {
                sectionTree = sectionTree
            });
        }

        [HttpGet]
        public IActionResult GetLevelSectionMachineTree()
        {
            var levelSections = _levelSectionRepository.GetLevelSectionMachines(ProjectId);

            var response = new ResponseLevelSectionChildren(ConvertToTree(levelSections));

            return new ObjectResult(response);
        }

        private IList<LevelSectionTree> ConvertToTree(IEnumerable<LevelSectionTree> models)
        {
            var section = new Dictionary<int, LevelSectionTree>();
            foreach (var item in models)
            {
                section.Add(item.id, item);
            }
            var result = new List<LevelSectionTree>();
            foreach (var item in section.Values)
            {
                if (item.pid == 0)
                {
                    result.Add(item);
                }
                else
                {
                    if (section.ContainsKey(item.pid))
                    {
                        section[item.pid].AddChilrden(item);
                    }
                }
            }
            return result;
        }

        private LevelSectionTree ConvertToTreeForTpm(IEnumerable<LevelSectionTree> models)
        {
            var section = new Dictionary<int, LevelSectionTree>();
            foreach (var item in models)
            {
                section.Add(item.id, item);
            }
            var result = new LevelSectionTree
            {
                id = 0,
                pid = 0,
                name = "设备",
            };
            var response = new List<LevelSectionTree>();
            foreach (var item in section.Values)
            {
                if (item.pid == 0)
                {
                    response.Add(item);
                }
                else
                {
                    if (section.ContainsKey(item.pid))
                    {
                        section[item.pid].AddChilrden(item);
                    }
                }
            }

            result.children = response;
            return result;
        }

        [HttpPost]
        public IActionResult DelLevelSection(int id)
        {
            //删除子级产线
            var childIds = _levelSectionRepository.GetLevelSectionIds(id, ProjectId).ToList();
            if (!childIds.Any())
                throw new BadRequestException(CommonEnum.RecordNotFound);
            var sections = _levelSectionRepository.GetList(q =>
                    childIds.Contains(q.id) && q.projectid == ProjectId && q.status == (int)RowState.Valid).ToList();
            foreach (var levelSection in sections)
            {
                var entity = _levelSectionRepository.Get(levelSection.id);
                if (entity == null)
                {
                    continue;
                }
                if (_machineAttributionRepository.IsExist(f => f.station == levelSection.id))
                {
                    throw new BadRequestException(ConfigEnum.MachineAlreadyBind);
                }
                _levelSectionRepository.Delete(entity);
                ////删除设备结构树
                //var attrs = _machineAttributionRepository.GetList(q => q.station == entity.id && q.projectid == ProjectId);
                //foreach (var attribution in attrs.ToList())
                //{
                //    var attr = _machineAttributionRepository.Get(attribution.id);
                //    if (attr != null)
                //    {
                //        _machineAttributionRepository.Delete(attr);
                //    }
                //}
            }
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }

            throw new BadRequestException(CommonEnum.SystemExcetion);
        }

        [HttpGet]
        public IActionResult GetMachineInfo(string sectionid)
        {
            if (string.IsNullOrEmpty(sectionid))
            {
                throw new BadRequestException(RequestEnum.SectionIDNotNull);
            }
            return new ObjectResult(_levelSectionMachineRepository.GetSectionMachine(ProjectId, sectionid.ToInt()));
        }

        [HttpGet]
        public IActionResult GetStations()
        {
            return new ObjectResult(_levelSectionMachineRepository.GetStations(ProjectId));
        }

        [HttpGet]
        public IActionResult GetLevelsBySection(int sectionId)
        {
            var response = new List<ResponseIdTitle>();

            var sectionIds = _levelSectionMachineRepository.GetLevelSectionIds(sectionId, ProjectId);
            sectionIds = sectionIds.Where(m => m != sectionId);

            var levelSections = _levelSectionRepository.GetList(q =>
                sectionIds.Contains(q.id) && q.projectid == ProjectId && q.status == (int)RowState.Valid);

            if (levelSections.Any())
            {
                var levelIds = levelSections.Select(m => m.levelid).Distinct().ToList();

                var levelEntities = _levelRepository.GetList(q =>
                    levelIds.Contains(q.id) && q.status == (int)RowState.Valid && q.projectid == ProjectId);

                if (levelEntities.Any())
                {
                    foreach (var sigerProjectLevel in levelEntities.ToList())
                    {
                        response.Add(new ResponseIdTitle
                        {
                            id = sigerProjectLevel.id,
                            title = sigerProjectLevel.title
                        });
                    }
                }
            }

            return new ObjectResult(response.OrderBy(q=>q.id));
        }



        [HttpGet]
        public IActionResult GetLevelidsBySection(int sectionId)
        {
            var ret = new List<ResponseIdTitle>();

            var sectionIds = _levelSectionMachineRepository.GetLevelSectionIds(sectionId, ProjectId);

            var levelids = _levelSectionRepository.GetList(q =>
                sectionIds.Contains(q.id) && q.projectid == ProjectId && q.status == (int)RowState.Valid).Select(s=>s.levelid).Distinct();

            if (levelids.Any())
            {
                var levelEntities = _levelRepository.GetList(q =>
                    levelids.Contains(q.id) && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                if (levelEntities.Any())
                {
                    foreach (var sigerProjectLevel in levelEntities.ToList())
                    {
                        ret.Add(new ResponseIdTitle
                        {
                            id = sigerProjectLevel.id,
                            title = sigerProjectLevel.title
                        });
                    }
                }
            }
            return new ObjectResult(ret);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="reverselevel">倒数层数=>1工位 =>2工站 =>3产线</param>
        /// <param name="parentid"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetSectionSelect(int reverselevel, int parentid)
        {
            var levels = _levelRepository.GetList(t => t.status == (int)RowState.Valid && t.projectid == ProjectId).OrderByDescending(t => t.id).ToList();
            if (levels.Count < reverselevel)
            {
                throw new BadRequestException(RequestEnum.LevelNotFound);
            }
            var res = _levelSectionRepository.GetSectionIdNamesByLevel(levels[reverselevel - 1].id, parentid, ProjectId).ToList();
            foreach (var r in res)
            {
                var i = _levelSectionRepository.ConvetTitle(r.name);
                var indexStr = r.name.Substring(i, r.name.Length - i);
                int.TryParse(indexStr, out int _index);
                r.index = _index;
            }
            var result = res.OrderBy(o => o.index).ToList();
            return new ObjectResult(result);
        }


        [HttpGet]
        public IActionResult GetTemplate()
        {
           

            return new ObjectResult(CreateMachineTemplate());
        }

        private string CreateMachineTemplate()
        {
            var columnNames = new List<string>();
            var titles = _levelRepository.GetLevelTitles(0, ProjectId);
            columnNames.AddRange(titles);

            var helper = new EpPlusForSectionHelper();
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"西格云平台-产线结构导入模板_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);
            helper.GenerateExcel(columnNames, fileName);
            return $"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}";
        }

        /// <summary>
        /// 取产线层级
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetSectionTreeForUserSetting(bool spread = false)
        {
            var list = _levelSectionRepository.GetLevelSectionTree(ProjectId).ToList();
            var responses = new List<LevelSectionTree>();
            foreach (var levelSectionTree in list)
            {
                levelSectionTree.disabled = false;
                levelSectionTree.spread = spread;
                responses.Add(levelSectionTree);
            }

            var response = new ResponseLevelSectionChildren(ConvertToTree(responses));

            return new ObjectResult(response);
        }


        [HttpGet]
        public IActionResult GetNCLevelSectionTreeChildren()
        {
            var lastSections = _levelSectionMachineRepository.GetLastSection(ProjectId).ToList();
            var machineSections = _levelSectionMachineRepository
                .GetList(t => lastSections.Select(q => q.id).Contains(t.section_id) && t.status == (int)RowState.Valid).ToList();
            var machineSectionIds = machineSections.Select(q => q.machine_id).ToList();
            var machineIds = _machineRepository.GetList(t => machineSectionIds.Contains(t.id) && t.projectid == ProjectId &&
                t.status == (int)RowState.Valid && t.category == (int)MachineCategory.NC).Select(t => t.id).ToList();
            var levels = _levelRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).ToList();
            var lastSectionIds = machineSections.Where(t => machineIds.Contains(t.machine_id)).Select(t => t.section_id).ToList();
            lastSections = lastSections.Where(t => lastSectionIds.Contains(t.id)).ToList();
            levels.Reverse();
            var i = 1;
            var list = new List<LevelSectionTree>();
            list.AddRange(from section in lastSections
                          select new LevelSectionTree
                          {
                              id = section.id,
                              name = section.title,
                              title = section.title,
                              pid = section.parentid,
                              levelId = section.levelid,
                              open = true
                          });
            var parentIds = lastSections.Select(t => t.parentid).ToList();
            foreach (var level in levels)
            {
                if (i > 1)
                {
                    var sections = _levelSectionRepository.GetList(t => parentIds.Contains(t.id)).ToList();
                    if (!sections.Any())
                    {
                        break;
                    }
                    parentIds = sections.Select(t => t.parentid).ToList();
                    list.AddRange(from section in sections
                                  select new LevelSectionTree
                                  {
                                      id = section.id,
                                      name = section.title,
                                      title = section.title,
                                      pid = section.parentid,
                                      levelId = section.levelid,
                                      open = true
                                  });
                }
                i++;
            }
            var response = new ResponseLevelSectionChildren(ConvertToTree(list));

            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult GetNCStations()
        {
            return new ObjectResult(_levelSectionMachineRepository.GetNCStations(ProjectId));
        }

        [HttpGet]
        public IActionResult GetNCMachineInfo(string sectionid)
        {
            if (string.IsNullOrEmpty(sectionid))
            {
                throw new BadRequestException(RequestEnum.SectionIDNotNull);
            }
            return new ObjectResult(_levelSectionMachineRepository.GetNCSectionMachine(ProjectId, sectionid.ToInt()));
        }
        /// <summary>
        /// Vue产线结构
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetSectionTree()
        {
            var maxLevel = _levelRepository.GetList(f => f.status == (int)RowState.Valid && f.projectid == ProjectId)
                .OrderByDescending(q => q.id).FirstOrDefault();
            var alltreedata = _levelSectionRepository.getAllTreeData(ProjectId);
            var resp = _levelSectionRepository.GetSectionChildren(alltreedata, 0, ProjectId, maxLevel?.levelid ?? 0);
            return new ObjectResult(resp);
        }

        /// <summary>
        /// APP-SKF 设备状态一览
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetLineLocation()
        {
            var res = new List<ResponseIdName>();
            var machines = _machineRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid).ToList();
            if (!machines.Any())
            {
                return new ObjectResult(res);
            }

            var levels = _levelRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).OrderByDescending(t => t.id).ToList();
            if (levels.Count < 2)
            {
                return new ObjectResult(res);
            }
            var secondLevelId = levels[1].id;
            levels = levels.Where(t => t.id <= secondLevelId).ToList();
            var sections = _levelSectionRepository.GetLevelSectionTree(ProjectId).ToList();
            var secondSections = sections.Where(t => t.levelId == secondLevelId).ToList();

            foreach (var section in secondSections)
            {
                var location = new List<string>();
                var sectionId = section.id;
                foreach (var level in levels)
                {
                    var Section = sections.FirstOrDefault(t => t.id == sectionId);
                    if (Section != null)
                    {
                        location.Add(Section.title);
                        sectionId = Section.pid;
                    }
                }
                location.Reverse();
                res.Add(new ResponseIdName
                {
                    id = section.id,
                    name = string.Join('-', location)
                });
            }

            return new ObjectResult(res);
        }

        [HttpGet]
        public IActionResult GetTwoLevelSection()
        {
            var responses = new List<ResponseTwoLevelSection>();
            var levels = _levelRepository.GetList(t => t.projectid == ProjectId && t.status == (int)RowState.Valid).OrderByDescending(t => t.id).ToList();
            if (levels.Count < 2)
            {
                var sections = _levelSectionRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid).ToList();
                foreach (var section in sections)
                {
                    responses.Add(new ResponseTwoLevelSection
                    {
                        id = section.id,
                        title = section.title
                    });
                }
            }
            else
            {
                var twoLevel = levels[1];
                var sections = _levelSectionRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid && q.levelid == twoLevel.id).ToList();
                foreach (var section in sections)
                {
                    var entity = new ResponseTwoLevelSection
                    {
                        id = section.id,
                        title = section.title
                    };

                    var children = _levelSectionRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid && q.parentid == section.id).ToList();
                    if (children.Any())
                    {
                        foreach (var child in children)
                        {
                            entity.children.Add(new TwoLevelSection
                            {
                                id = child.id,
                                title = child.title
                            });
                        }
                    }

                    responses.Add(entity);
                }
            }

            return new ObjectResult(responses);
        }

        [HttpGet]
        public IActionResult CheckLevel(int sectionId)
        {
            var maxLevel = _levelRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid)
                .OrderByDescending(q => q.id).FirstOrDefault();
            if (maxLevel == null)
            {
                throw new BadRequestException(RequestEnum.LevelNotFound);
            }

            var section = _levelSectionRepository.Get(q => q.id == sectionId && q.status == (int)RowState.Valid);
            if (section == null)
            {
                throw new BadRequestException(RequestEnum.LevelNotFound);
            }

            if (section.levelid < maxLevel.id)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpPost]
        public IActionResult AddLevelSection([FromBody]RequestUpdateCustomLevel request)
        {
            if (request.id == 0)
            {
                var parentlevel = _levelRepository.Get(q => q.projectid == ProjectId && q.status == (int)RowState.Valid && q.parentid == 0);
                if (parentlevel == null)
                {
                    throw new BadRequestException(RequestEnum.LevelNotFound);
                }
                var level = new siger_project_level_section
                {
                    parentid = 0,
                    dutymid = 0,
                    levelid = parentlevel.id,
                    projectid = ProjectId,
                    status = (int)RowState.Valid,
                    title = request.title
                };
                var result = _levelSectionRepository.AddLevelSection(level);
                if (result > 0)
                {
                    return new ObjectResult(result);
                }
                throw new BadRequestException(CommonEnum.Fail);
            }
            else
            {
                var entity = _levelSectionRepository.Get(q => q.id == request.id && q.projectid == ProjectId && q.status == (int)RowState.Valid);
                if (entity == null)
                {
                    throw new BadRequestException(RequestEnum.LevelNotFound);
                }

                var exist = _levelSectionRepository.Get(q => q.parentid == request.id && q.title == request.title
                                                                                      && q.projectid == ProjectId && q.status == (int)RowState.Valid);
                if (exist != null)
                {
                    throw new BadRequestException(RequestEnum.LevelExist);
                }

                var levels = _levelRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid).OrderBy(m => m.id).Select(m => m.id).ToList();
                int nextLevel = 0;
                for (var i = 0; i < levels.Count; i++)
                {
                    if (levels[i] == entity.levelid && i < levels.Count - 1)
                    {
                        nextLevel = levels[i + 1];
                    }
                }

                if (nextLevel == 0)
                {
                    throw new BadRequestException(RequestEnum.LevelNotFound);
                }

                var level = new siger_project_level_section
                {
                    parentid = request.id,
                    dutymid = 0,
                    levelid = nextLevel,
                    projectid = ProjectId,
                    status = (int)RowState.Valid,
                    title = request.title
                };
                var result = _levelSectionRepository.AddLevelSection(level);
                if (result > 0)
                {
                    return new ObjectResult(result);
                }
                throw new BadRequestException(CommonEnum.Fail);
            }
        }

        /// <summary>
        /// 获取产线层级 （产线层级倒数第二级别)
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetLine()
        {
            var datalist = _levelSectionRepository.GetAccLines(ProjectId);
            return new ObjectResult(datalist);
        }
        /// <summary>
        /// 获取产线层级 （产线层级倒数第一级别)
        /// </summary>
        /// <param name="line">产线ID</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetStation(int line)
        {
            var datalist = _levelSectionRepository.GetAccStationByline(ProjectId, line);
            return new ObjectResult(datalist);
        }

    }
}