using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Filters;
using Siger.ApiIMS.Result;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.FieldEnum;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Response;
using Siger.Middlelayer.IMSRepository.Entities;
using Siger.Middlelayer.IMSRepository.Repositories.Interface;
using Siger.Middlelayer.IMSRepository.Request;

namespace Siger.ApiIMS.Controllers
{
    [Route("IMS/[controller]/[action]")]
    [ApiController]
    [NoTokenValidateFilter]
    public class ToolClientController : ControllerBase
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerUserRepository _userRepository;
        private readonly ISigerProjectUserRepository _sigerProjectUserRepository;
        private readonly ISigerProjectRepository _sigerProjectRepository;
        private readonly ISigerProjectLineStorageAuthorityRepository _authorityRepository;
        private readonly ISigerProjectLineStorageRepository _storageRepository;
        private readonly IToollifeStoragePlatformRepository _platformRepository;
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly IToollifeUseRecordRepository _useRecordRepository;
        private readonly IToolLifeToolRepository _toolRepository;
        
        public ToolClientController(IUnitOfWork unitOfWork, ISigerUserRepository userRepository, ISigerProjectUserRepository sigerProjectUserRepository,
            ISigerProjectRepository sigerProjectRepository, ISigerProjectLineStorageAuthorityRepository authorityRepository,
            ISigerProjectLineStorageRepository storageRepository, IToollifeStoragePlatformRepository platformRepository,
            ISigerProjectMachineRepository machineRepository, IToollifeUseRecordRepository useRecordRepository, IToolLifeToolRepository toolRepository)
        {
            _unitOfWork = unitOfWork;
            _userRepository = userRepository;
            _sigerProjectUserRepository = sigerProjectUserRepository;
            _sigerProjectRepository = sigerProjectRepository;
            _authorityRepository = authorityRepository;
            _storageRepository = storageRepository;
            _platformRepository = platformRepository;
            _machineRepository = machineRepository;
            _useRecordRepository = useRecordRepository;
            _toolRepository = toolRepository;
        }

        [HttpGet]
        public IActionResult Login(string userName, string password, string ipaddress)
        {
            var pass = MD5Helper.Get32MD5(password);
            var user = _userRepository.Get(f => f.mobile == userName && f.password == pass && f.status == (int)RowState.Valid);
            if (user == null)
            {
                throw new BadRequestException(TlmEnum.LoginError);
            }
            
            var userprojectinfo = _sigerProjectUserRepository.Get(f => f.mid == user.id && f.status == (int)RowState.Valid);
            if (userprojectinfo == null)
            {
                throw new BadRequestException(TlmEnum.ProjectUserNotFound);
            }

            var project = _sigerProjectRepository.Get(q => q.id == userprojectinfo.projectid && q.status == (int)RowState.Valid);
            if (project == null)
            {
                throw new BadRequestException(TlmEnum.ProjectNotFound);
            }

            var authorities = _authorityRepository.GetList(q =>
                q.user_id == user.id && q.project_id == project.id && q.status == (int) RowState.Valid 
                && (q.manage_authority == 1 || q.use_authority == 1));
            if (!authorities.Any())
            {
                throw new BadRequestException(TlmEnum.StoragesNotFound);
            }

            var ids = authorities.Select(m => m.storage_id).Distinct().ToList();
            var storages = _storageRepository.GetList(q => ids.Contains(q.id) && q.project_id == project.id && q.status == (int) RowState.Valid);
            if (!storages.Any())
            {
                throw new BadRequestException(TlmEnum.StoragesNotFound);
            }

            var userStorages = new List<StorageInfo>();
            foreach (var storage in storages.ToList())
            {
                var auth = authorities.FirstOrDefault(q => q.storage_id == storage.id);
                if (auth == null)
                {
                    continue;
                }
                userStorages.Add(new StorageInfo
                {
                    Id = storage.id,
                    Code = storage.storage_code,
                    ComPort = $"COM{storage.com_port}",
                    UseAuth = auth.use_authority,
                    ManagerAuth = auth.manage_authority,
                    PrintCategory = storage.print_category,
                    PrintPort = storage.print_port
                });
            }
            var result = new ClientLoginResult
            {
                ProjectId = project.id,
                UserId = user.id,
                UserName = user.nickname,
                StorageInfoes = userStorages
            };

            return new ObjectResult(result);
        }

        /// <summary>
        /// 获取全部称台
        /// </summary>
        /// <param name="storage_id"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetAllPlatforms(int storage_id, string name)
        {
            name = name.ToStr();
            var entities = _platformRepository.GetList(q => q.storage_id == storage_id && q.status == (int)RowState.Valid
                                                                                       && (name == "" || q.name.Contains(name))).OrderBy(m => m.platform);
            return new ObjectResult(entities.ToList());
        }

        /// <summary>
        /// 导入称台
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult ImportPlatforms([FromBody]RequestImportPlatform request)
        {
            if (request.platforms == null || !request.platforms.Any())
            {
                throw new BadRequestException(TlmEnum.ParameterError);
            }

            var exist = _platformRepository.Get(q => q.storage_id == request.storage_id && q.status == (int)RowState.Valid);
            if (exist != null)
            {
                throw new BadRequestException(TlmEnum.PlatformIsExist);
            }

            var storage = _storageRepository.Get(q => q.id == request.storage_id && q.status == (int)RowState.Valid);
            if (storage == null)
            {
                throw new BadRequestException(TlmEnum.StorageNotFound);
            }

            var materials = _platformRepository.GetAllMeterials(storage.project_id).ToList();
            if (!materials.Any())
            {
                throw new BadRequestException(TlmEnum.MaterialNotFound);
            }
            var index = 1;
            foreach (var platform in request.platforms.OrderBy(m => m.platform))
            {
                var platMaterial = materials.FirstOrDefault(q => q.key == platform.code);
                if (platMaterial == null)
                {
                    throw new BadRequestException(TlmEnum.MaterialNotFound);
                }
                var entity = new siger_project_ims_storage_platform
                {
                    storage_id = request.storage_id,
                    box_count = platform.box_count,
                    code = platform.code,
                    full_count = platform.full_count,
                    min = platform.min,
                    max = platform.max,
                    name = platform.name,
                    peeling_weight = platform.peeling_weight,
                    platform = platform.platform,
                    supplier = platform.supplier,
                    weight = platform.weight,
                    project_id = storage.project_id,
                    category = (StorageCategory)platform.category,
                    number = index.ToString("D2")
                };
                _platformRepository.Insert(entity);
                index++;
            }

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

            throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// 获取称台信息
        /// </summary>
        /// <param name="storage_id"></param>
        /// <param name="platform"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetPlatform(int storage_id, string platform)
        {
            var entity = _platformRepository.Get(q => q.storage_id == storage_id && q.platform == platform && q.status == (int)RowState.Valid);
            if (entity == null)
            {
                throw new BadRequestException(TlmEnum.PlatformNotExist);
            }
            return new ObjectResult(entity);
        }

        [HttpPost]
        public IActionResult EditPlatform([FromBody]RequestEditPlatform request)
        {
            var entity = _platformRepository.Get(q => q.storage_id == request.storage_id && q.platform == request.platform && q.status == (int)RowState.Valid);
            if (entity == null)
            {
                throw new BadRequestException(TlmEnum.PlatformNotExist);
            }

            entity.name = request.name;
            entity.code = request.code;
            entity.box_count = request.box_count;
            entity.full_count = request.full_count;
            entity.min = request.min;
            entity.max = request.max;
            entity.peeling_weight = request.peeling_weight;
            entity.supplier = request.supplier;
            entity.weight = request.weight;
            entity.category = (StorageCategory) request.category;

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

        [HttpGet]
        public IActionResult ResetStorage(int storage_id)
        {
            var storage = _storageRepository.Get(q => q.id == storage_id && q.status == (int)RowState.Valid);
            if (storage == null)
            {
                throw new BadRequestException(TlmEnum.StorageNotFound);
            }

            var entities = _platformRepository.GetList(q => q.storage_id == storage_id && q.status == (int)RowState.Valid);
            if (!entities.Any())
            {
                throw new BadRequestException(TlmEnum.PlatformNotExist);
            }

            foreach (var entity in entities.ToList())
            {
                entity.status = (int) RowState.Invalid;
                _platformRepository.Update(entity);
            }
            
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpGet]
        public IActionResult GetAllMeteriels(int projectId)
        {
            var meteriels = _platformRepository.GetAllMeterials(projectId);

            return new ObjectResult(meteriels);
        }

        [HttpGet]
        public IActionResult GetAllSuppliers(int projectId)
        {
            var suppliers = _platformRepository.GetAllSuppilers(projectId);

            return new ObjectResult(suppliers);
        }

        [HttpGet]
        public IActionResult GetAllTools(int projectId)
        {
            var tools = _toolRepository.GetList(q => q.project_id == projectId && q.status == (int)RowState.Valid)
                .Select(m => new
                {
                    key = m.id,
                    value = m.name
                }).ToList();

            return new ObjectResult(tools);
        }

        [HttpPost]
        public IActionResult SetMeteriel([FromBody]RequestSetMeteriel request)
        {
            var entity = _platformRepository.Get(q => q.id == request.Id && q.status == (int)RowState.Valid);
            if (entity == null)
            {
                throw new BadRequestException(TlmEnum.PlatformNotExist);
            }

            entity.code = request.Code;
            entity.name = request.Name;
            entity.supplier = request.Supplier;
            entity.min = request.Min;
            entity.max = request.Max;
            entity.weight = request.Weight;
            entity.peeling_weight = request.PeelingWeight;
            entity.full_count = request.FullCount;
            entity.box_count = request.BoxCount;
            entity.category = (StorageCategory)request.Category;
            entity.current_count = 0;
            entity.image_name = request.ImageName;
            entity.image_content = request.ImageBytes;

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

        [HttpGet]
        public IActionResult GetMachinesByStorage(int storage_id, int project_id)
        {
            var storage = _storageRepository.Get(q => q.id == storage_id && q.status == (int) RowState.Valid && q.project_id == project_id);
            if (storage == null)
            {
                throw new BadRequestException(TlmEnum.StorageNotFound);
            }

            var machineIds = _machineRepository.GetLevelSectionMachineIds(storage.section_id, project_id);
            if (!machineIds.Any())
            {
                throw new BadRequestException(TlmEnum.MachineNotExist);
            }
            var machines = _machineRepository.GetList(q =>
                    machineIds.Contains(q.id) && q.projectid == project_id && q.status == (int) RowState.Valid)
                .Select(m => new ResponseKeyValue(m.id.ToString(), m.code)).ToList();

            return new ObjectResult(machines);
        }

        [HttpGet]
        public IActionResult GetCuttersByMachine(int machine_id, int project_id)
        {
            var machine = _machineRepository.Get(q => q.id == machine_id && q.status == (int)RowState.Valid && q.projectid == project_id);
            if (machine == null)
            {
                throw new BadRequestException(TlmEnum.MachineNotExist);
            }

            if (machine.tool_count == 0)
            {
                throw new BadRequestException(TlmEnum.MachineToolNotExist);
            }
            var response = new List<string>();
            var prefix = string.Empty;
            var dicts = _machineRepository.GetDictKeyValues(project_id, AccDictCost.ToolPrefix).FirstOrDefault();
            if (dicts != null)
            {
                prefix = dicts.value;
            }

            for (var i = 1; i <= machine.tool_count; i++)
            {
                response.Add($"{prefix}{i:D2}");
            }
            return new ObjectResult(response);
        }

        [HttpGet]
        public IActionResult GetInstallInfo(int machine_id, string cutter_number, int storage_id, int type,int project_id)
        {
            return new ObjectResult(CommonEnum.Succefull);
        }

        [HttpPost]
        public IActionResult AddUseRecord([FromBody]RequestAddUseRecord request)
        {
            var entity = new siger_project_ims_use_record
            {
                cutter_number = request.CutterNumber,
                count = request.Count,
                machine_id = request.MachineId,
                project_id = request.ProjectId,
                storage_id = request.StorageId,
                use_userid = request.UserId,
                type = request.Type,
                recycle_id = request.RecycleId,
                residual_life = request.ResidualLife
            };
            _useRecordRepository.Insert(entity);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpGet]
        public IActionResult UpdateMeterielCount(int storage_id, int project_id, string number, int currentCount)
        {
            var entity = _platformRepository.Get(q => q.storage_id == storage_id && q.project_id == project_id && q.number == number && q.status == (int)RowState.Valid);
            if (entity == null)
            {
                throw new BadRequestException(TlmEnum.PlatformNotExist);
            }

            entity.current_count = currentCount;
            _platformRepository.Update(entity);
            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpGet]
        public IActionResult GetReturnPlatFormId(int storage_id, int project_id)
        {
            var returnPlat = _platformRepository.GetList(q => q.project_id == project_id && q.storage_id == storage_id
                                                           && q.status == (int) RowState.Valid && q.category == StorageCategory.Recovery
                                                           && q.current_count < q.max)
                .FirstOrDefault();
            if (returnPlat != null)
            {
                return new ObjectResult(returnPlat.number);
            }
            return new ObjectResult("");
        }
    }
}