using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiTPM.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Extensions;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.TpmRepository.Entities;
using Siger.Middlelayer.TpmRepository.Repositories.Interface;
using Siger.Middlelayer.TpmRepository.Request;
using Siger.Middlelayer.TpmRepository.Response;

namespace Siger.ApiTPM.Controllers
{
    public class AppSparepartController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISparepartRecordRepository _recordRepository;
        private readonly IRepairRepository _repairRepository;
        private readonly ISparepartRepository _sparepartRepository;
        private readonly ISparepartAuditRepository _sparepartAuditRepository;
        private readonly ISparepartAuditDetailRepository _auditDetailRepository;
        private readonly ISigerProjectSparepartCodeRepository _codeRepository;
        private readonly ISigerProjectMachineAttributionRepository _attributionRepository;
        private readonly IPlanItemRepository _itemRepository;
        public AppSparepartController(IUnitOfWork unitOfWork, ISparepartRecordRepository recordRepository, ISparepartRepository sparepartRepository,
            IRepairRepository repairRepository, ISparepartAuditRepository sparepartAuditRepository, ISparepartAuditDetailRepository auditDetailRepository,
            ISigerProjectSparepartCodeRepository codeRepository, ISigerProjectMachineAttributionRepository attributionRepository,
            IPlanItemRepository itemRepository)
        {
            _unitOfWork = unitOfWork;
            _recordRepository = recordRepository;
            _repairRepository = repairRepository;
            _sparepartRepository = sparepartRepository;
            _sparepartAuditRepository = sparepartAuditRepository;
            _auditDetailRepository = auditDetailRepository;
            _codeRepository = codeRepository;
            _attributionRepository = attributionRepository;
            _itemRepository = itemRepository;
        }

        /// <summary>
        /// 备件出库单号列表
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetSparepartOut([FromBody]RequestGetAppSparepart req)
        {
            int type = req.type > 0 ? req.type : 0;
            int repairid = req.repairid > 0 ? req.repairid : 0;

            if (repairid > 0)
            {
                var sparepartoutresult = _repairRepository.Get(t =>
                    t.id == repairid && t.projectid == ProjectId && t.status == (int)RowState.Valid);
                var sparepartHelper = new SparepartHelper(ProjectId, UserId, _recordRepository, _sparepartRepository);
                var outCodes = sparepartHelper.GetSparepartOutCode(sparepartoutresult.sparepartout, repairid, type);
                if (outCodes.Any())
                {
                    return new ObjectResult(outCodes);
                }
            }
            throw new ServerException(500131);
        }

        /// <summary>
        /// 获取设备相关的备件
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetSparepart([FromBody]RequestListByMachineId req)
        {
            var res = _sparepartRepository.GetSparepartListByMachineId(req.machineID.ToInt(), ProjectId);

            return new ObjectResult(res);
        }

        /// <summary>
        /// 获取设备相关的备件，从设备结构树中获取
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetReplaceSpareparts([FromBody]RequestListByMachineId req)
        {
            var attribution = _attributionRepository.Get(q =>
                q.machine == req.machineID.ToInt() && q.status == (int)RowState.Valid && q.projectid == ProjectId);
            if (attribution == null)
            {
                return new ObjectResult(new List<RepsonseGetSparepartList>());
            }
            var attributions = _attributionRepository.GetSonLevelMachineAttribution(attribution.id, ProjectId).ToList();
            if (attributions.Any())
            {
                var machineIds = attributions.Select(m => m.sparepart_id).Distinct().ToList();
                var res = _sparepartRepository.GetReplaceSparepartsByMachineId(machineIds, ProjectId);
                return new ObjectResult(res);
            }

            return new ObjectResult(new List<RepsonseGetSparepartList>());
        }

        /// <summary>
        /// 获取全部的库位
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetSparepartLocations()
        {
            return new ObjectResult(_sparepartRepository
                .GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid && q.is_substitute == 0)
                .Select(q => q.warehouse).Distinct().ToList());
        }

        /// <summary>
        /// 获取所有非替换件
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetUnReplaceSpareparts(string location, string name)
        {
            Expression<Func<siger_project_sparepart, bool>> funcommon = q => q.projectid == ProjectId
                                                                             && q.status == (int)RowState.Valid && q.is_substitute == 0;
            Expression<Func<siger_project_sparepart, bool>> funlocation = f => true;
            if (!string.IsNullOrWhiteSpace(location))
            {
                funlocation = f => f.warehouse.Contains(location);
            }
            Expression<Func<siger_project_sparepart, bool>> funName = f => true;
            if (!string.IsNullOrWhiteSpace(name))
            {
                funName = f => f.title.Contains(name);
            }
            var predicate = funcommon.And(funlocation).And(funName);
            var sparts = _sparepartRepository.GetList(predicate).Take(100)
                .Select(m => new RepsonseGetSparepartList
                {
                    sparepartid = m.id,
                    record_code = m.code,
                    stitle = m.title,
                    sku = m.sku,
                    price = m.price,
                    location = m.warehouse,
                    need_audit = m.approvaluser_mid == 0 ? 0 : 1
                });
            return new ObjectResult(sparts);
        }

        /// <summary>
        /// 备件替换前，获取之前选择的数据
        /// </summary>
        /// <param name="repair_id"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetPrepareSpareparts(int repair_id)
        {
            var audit = _sparepartAuditRepository.Get(q => q.repair_id == repair_id && q.status == (int)RowState.Valid && q.project_id == ProjectId);
            if (audit == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var details = _auditDetailRepository.GetList(q => q.audit_id == audit.id && q.status == (int)RowState.Valid).ToList();
            if (!details.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var responses = new List<ResponsePrepareSpareparts>();

            var spids = details.Select(q => q.sparepart_id);
            var spareparts = _sparepartRepository.GetList(q =>
                spids.Contains(q.id) && q.status == (int)RowState.Valid && q.projectid == ProjectId).ToList();
            foreach (var sparepart in spareparts)
            {
                var response = new ResponsePrepareSpareparts
                {
                    sparepartid = sparepart.id,
                    is_replace = sparepart.is_substitute,
                    name = sparepart.title,
                    sku = sparepart.sku,
                    code = sparepart.code,
                    location = sparepart.warehouse
                };
                var apply = details.FirstOrDefault(q => q.sparepart_id == sparepart.id);
                if (apply != null)
                {
                    response.apply_count = apply.apply_count;
                    response.qrcode = apply.qrcode;
                }
                responses.Add(response);
            }

            return new ObjectResult(responses);
        }

        /// <summary>
        /// 检查二维码是否已入库
        /// </summary>
        /// <param name="qrcode"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult CheckQrCode(string qrcode)
        {
            if (string.IsNullOrWhiteSpace(qrcode))
            {
                throw new BadRequestException(RequestEnum.ParameterError);
            }

            var instock = _codeRepository.Get(q => q.sparepart_code == qrcode && q.status == (int)RowState.Valid &&
                                                    q.project_id == ProjectId);
            if (instock == null)
            {
                throw new BadRequestException(RequestEnum.SparepartQrCodeNotInStock);
            }
            return new ObjectResult(CommonEnum.Succefull);
        }

        /// <summary>
        /// 确认收货
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult SubmitPrepare([FromBody]RequestSubmitPrepare request)
        {
            var spareparts = request.spareparts;
            if (spareparts == null || !spareparts.Any())
            {
                spareparts = new List<SubmitPrepareInfo>();
            }

            var audit = _sparepartAuditRepository.Get(q => q.id == request.id && q.status == (int)RowState.Valid);
            if (audit == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var machineId = 0;
            var workorder = string.Empty;
            var repair = _repairRepository.Get(audit.repair_id);
            if (audit.mode == 1)
            {
                if (repair == null)
                {

                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
                machineId = repair.machineid;
                workorder = repair.work_order;
            }
            else if (audit.mode == 2)
            {
                var item = _itemRepository.Get(audit.repair_id);
                if (item == null)
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
                machineId = item.machineid;
                workorder = $"P{item.id}";
            }
            else
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            //检查备件二维码是否为空和入库
            foreach (var prepareInfo in spareparts)
            {
                if (!string.IsNullOrWhiteSpace(prepareInfo.qrcode))
                {
                    var instock = _codeRepository.Get(q => q.sparepart_code == prepareInfo.qrcode
                                                           && q.status == (int)RowState.Valid &&
                                                           q.project_id == ProjectId);
                    if (instock == null)
                    {
                        throw new BadRequestException(RequestEnum.SparepartQrCodeNotInStock);
                    }
                }
            }

            audit.category = SparepartAuditCategory.Prepare;
            audit.approval_status = 4; //备货完成
            _sparepartAuditRepository.Update(audit);
            //修改备件
            var spids = string.Empty;
            foreach (var prepareInfo in spareparts)
            {
                spids += prepareInfo.sparepartid + "*" + prepareInfo.apply_count + ",";
                var sparepart = _sparepartRepository.Get(f => f.id == prepareInfo.sparepartid);
                //备件出库
                var sparecord = new siger_project_sparepart_record
                {
                    number = prepareInfo.apply_count,
                    machineid = machineId,
                    order_code = workorder == string.Empty ? audit.repair_id.ToStr() : workorder,
                    type = (int)StockCategory.OutStock,
                    IO_type = (int)InStockCategory.Emergency,
                    sparepartid = prepareInfo.sparepartid,
                    relation_repair = 1,
                    create_mid = UserId,
                    operate_mid = (audit?.creator_mid ?? UserId).ToStr(),//应该显示报修人
                    create_time = UnixTimeHelper.GetNow(),
                    projectid = ProjectId,
                    price = sparepart?.price ?? 0
                };
                sparecord.sum_price = sparecord.number * sparecord.price;
                sparecord.last_sku = sparepart?.sku ?? 0;
                _recordRepository.Insert(sparecord);
            }

            if (audit.mode == 1 && repair != null)
            {
                repair.sparepartid = spids.TrimEnd(',');
                _repairRepository.Update(repair);
            }

            if (_unitOfWork.Commit() < 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }

            var result = _sparepartAuditRepository.AddReplcaeSpareparts(request, UserId, audit.id);
            if (result < 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }

            return new ObjectResult(CommonEnum.Succefull);
        }
    }
}