using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Exceptions;
using Siger.ApiCommon.Result;
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.Log;
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;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.ApiConfig.Controller
{
    public class MachineTypeController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerProjectMachineTypeRepository _projectMachineTypeRepository;
        public MachineTypeController(IUnitOfWork unitOfWork, ISigerProjectMachineTypeRepository projectMachineTypeRepository)
        {
            _unitOfWork = unitOfWork;
            _projectMachineTypeRepository = projectMachineTypeRepository;
        }

        [HttpGet]
        public IActionResult GetMachineTypeItemTwo(string machineType1, string machineType2, string machineName, int page = 1, int pagesize = PageSize)
        {
            var parentType = machineType1.ToInt();
            var childType = machineType2.ToInt();

            var list = _projectMachineTypeRepository.GetPagedList(parentType, childType, machineName, ProjectId, page, pagesize);

            var response = new List<ResponseGetMachineType>();
            foreach (var machineType in list.Data)
            {
                response.Add(Mapper<MachineType, ResponseGetMachineType>.Map(machineType));
            }

            return new PagedObjectResult(response, list.Total, page, pagesize);
        }

        [HttpGet]
        public IActionResult GetAddMachineType()
        {
            var list = _projectMachineTypeRepository.GetList(q => q.parentid > 0 && q.status == (int)RowState.Valid && q.projectid == ProjectId);

            return new ObjectResult(list.OrderBy(m => m.title).ToList());
        }

        [HttpGet]
        public IActionResult GetEditDcategory()
        {
            var list = _projectMachineTypeRepository.GetList(q => q.parentid <= 0 && q.status == (int)RowState.Valid && q.projectid == ProjectId);

            return new ObjectResult(list.OrderBy(m => m.title).ToList());
        }

        [HttpGet]
        public IActionResult GetMachineTypeTree()
        {
            var list = MachineTypeTree(0);
            return new ObjectResult(list);
        }

        private List<ResponseTypeTree> MachineTypeTree(int parent)
        {
            var ret = new List<ResponseTypeTree>();
            var list = _projectMachineTypeRepository.GetList(q => q.parentid.Equals(parent) && q.status == (int)RowState.Valid && q.projectid == ProjectId).ToList();
            if (!list.Any())
            {
                return ret;
            }
            foreach (var item in list)
            {
                ret.Add(new ResponseTypeTree
                {
                    value = item.id,
                    label = item.title,
                    children = MachineTypeTree(item.id)
                });
            }
            return ret;
        }

        [HttpGet]
        public IActionResult GetLastMachineType(int id)
        {
            var list = _projectMachineTypeRepository.GetList(q => q.parentid == id && q.status == (int)RowState.Valid && q.projectid == ProjectId);

            return new ObjectResult(list.OrderBy(m => m.title).ToList());
        }

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

            var list = _projectMachineTypeRepository.GetList(q =>
                q.parentid == parentid && q.status == (int)RowState.Valid);

            foreach (var sigerProjectMachineType in list)
            {
                response.Add(Mapper<siger_project_machine_type, ResponseIdTitle>.Map(sigerProjectMachineType));
            }

            return new ObjectResult(response);
        }

        [HttpPost]
        public IActionResult AddDcategory([FromBody] RequestAddMachineType request)
        {
            var isExist = _projectMachineTypeRepository.IsExist(q => q.title == request.title && q.status == (int)RowState.Valid && q.projectid == ProjectId);
            if (isExist)
            {
                throw new BadRequestException(RequestEnum.NameHasExist);
            }

            var entity = new siger_project_machine_type
            {
                description = request.description,
                title = request.title,
                parentid = request.parentid,
                projectid = ProjectId
            };
            _projectMachineTypeRepository.Insert(entity);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.SystemExcetion);
        }

        [HttpGet]
        public IActionResult GetDcategoryItem(int id)
        {
            var entity = _projectMachineTypeRepository.Get(id);
            if (entity == null || entity.status != (int)RowState.Valid)
            {
                throw new BadRequestException(RequestEnum.MachineTypeNotFound);
            }
            var response = new ResponseGetMachineTypeInfo();
            response.id = entity.id;
            response.title = entity.title;
            response.description = entity.description;
            if (entity.parentid != 0)
            {
                var parentEntity = _projectMachineTypeRepository.Get(entity.parentid);
                if (parentEntity == null || parentEntity.status != (int)RowState.Valid)
                {
                    throw new BadRequestException(RequestEnum.MachineTypeNotFound);
                }
                response.parentid = parentEntity.id;
                response.pretitle = parentEntity.title;
            }

            return new ObjectResult(new List<ResponseGetMachineTypeInfo> { response });
        }

        [HttpPost]
        public IActionResult EditMachineType([FromBody] RequestUpdateMachineType request)
        {
            var entity = _projectMachineTypeRepository.Get(request.machinetypeid);
            if (entity == null || entity.status != (int)RowState.Valid)
            {
                throw new BadRequestException(RequestEnum.MachineTypeNotFound);
            }

            entity.description = request.description;
            entity.title = request.title;
            _projectMachineTypeRepository.Update(entity);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.SystemExcetion);
        }

        [HttpPost]
        public IActionResult DeleteDcategory(int id)
        {
            var entity = _projectMachineTypeRepository.Get(id);
            if (entity == null || entity.status != (int)RowState.Valid)
            {
                throw new BadRequestException(RequestEnum.MachineTypeNotFound);
            }

            entity.status = (int)RowState.Invalid;
            _projectMachineTypeRepository.Update(entity);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.SystemExcetion);
        }

        [HttpGet]
        public IActionResult ListTypeByParentID(int id)
        {
            var types = _projectMachineTypeRepository.GetList(q =>
                    q.projectid == ProjectId && q.status == (int)RowState.Valid && q.parentid == id)
                .Select(m => new
                {
                    m.id,
                    m.title
                });
            return new ObjectResult(types);
        }

        [HttpGet]
        public IActionResult ExportMachineType(string machineType1, string machineType2, string machineName)
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var parentType = machineType1.ToInt();
            var childType = machineType2.ToInt();
            var machineTypes = _projectMachineTypeRepository.ExportMachineTypes(parentType, childType, machineName, ProjectId).ToList();
            if (!machineTypes.Any())
            {
                throw new BadRequestException(RequestEnum.MachineTypeNotFound);
            }
            var temporaryFileName = $"machinetypelist_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<MachineTypeList>();
            try
            {
                var types = new List<MachineTypeList>();
                var index = 1;
                foreach (var pro in machineTypes)
                {
                    var type = new MachineTypeList
                    {
                        No = index,
                        ParentType = pro.t2,
                        ChildType = pro.t1,
                        Description = pro.description,
                        Num = pro.nums.ToString()
                    };
                    types.Add(type);
                    index++;
                }

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

        [HttpGet]
        public IActionResult GetParentChildTypes()
        {
            var types = _projectMachineTypeRepository.GetList(q =>
                q.projectid == ProjectId && q.status == (int)RowState.Valid && q.parentid == 0).ToList();

            var responses = new List<ResponseIdTitle>();
            foreach (var machineType in types)
            {
                var childTypes = _projectMachineTypeRepository.GetList(q =>
                    q.parentid == machineType.id && q.projectid == ProjectId && q.status == (int)RowState.Valid);

                foreach (var type in childTypes.ToList())
                {
                    var response = new ResponseIdTitle
                    {
                        id = type.id,
                        title = machineType.title + "-" + type.title
                    };
                    responses.Add(response);
                }
            }

            return new ObjectResult(responses);
        }

        [HttpGet]
        public IActionResult ListTypeTree()
        {
            var types = _projectMachineTypeRepository.GetLevelMachineTypes(ProjectId);

            return new ObjectResult(ConvertToTree(types));
        }

        private LevelSectionTree ConvertToTree(IEnumerable<LevelSectionTree> models)
        {
            var section = new Dictionary<int, LevelSectionTree>();
            foreach (var item in models)
            {
                if (section.ContainsKey(item.id))
                {
                    continue;
                }
                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;
        }
    }
}