using OracleInternal.SqlAndPlsqlParser.LocalParsing;
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using WCS.BLL.Config;
using WCS.BLL.DbModels;
using WCS.BLL.HardWare;
using WCS.BLL.Manager;
using WCS.BLL.Services.IService;
using WCS.BLL.Tool;
using WCS.BLL.Tool.Api.ApiModel;
using WCS.DAL.Db;
using WCS.DAL.DbModels;
using WCS.Model;
using WCS.Model.ApiModel.InOutRecord;
using WCS.Model.ApiModel.InStore;
using WCS.Model.ApiModel.MXBackgroundThread;

namespace WCS.BLL.Services.Service
{
    public class InstoreService : IInstoreService
    {
        public InstoreService() { }

        public ResponseBase shelfGoInInStore(ShelfGoInInstoreRequest request)
        {
            try
            {
                //校验货架编码规则
                //取配置文件中得货架编码规则
                bool isValid = false;
                var patterns = LocalFile.Config.ModuleCodePatterns;
                if (patterns != null && patterns.Count > 0)
                {
                    foreach (var pattern in patterns)
                    {
                        isValid = Regex.IsMatch(request.ModuleCode, pattern);
                        //匹配到第一个符合条件的货架码 就直接退出循环 认为匹配成功
                        if (isValid)
                            break;
                    }
                }
                //如果配置文件缺失 使用默认正则进行匹配
                else
                {
                    isValid = Regex.IsMatch(request.ModuleCode, LocalFile.DefaultModuleCodePattern);
                }

                if (!isValid)
                {
                    return new ResponseBase()
                    {
                        Code = 202,
                        Message = $"模组编码{request.ModuleCode}不满足模组编码规则！",
                    };
                }
                //找到模组对应的货架
                var shelf = ShelfManager.Shelves.Where(t => t.ModulesStr.Contains(request.ModuleCode)).FirstOrDefault();
                if (shelf == null)//未找到
                {
                    return new ResponseBase()
                    {
                        Code = 201,
                        Message = "未找到模组对应的货架",
                    };
                }
                //已找到模组对应货架
                shelf.GoInInstore(request.IpAdress);

                if (shelf.CurrentMode == Mode.入库模式)
                    //成功进入入库模式
                    return new ShelfGoInInstoreResponse()
                    {
                        Code = 200,
                        Message = $"货架进入入库模式成功！{string.Join(",", shelf.ExceptionMessages)}",
                        Data = new ShelfGoInInstoreDto()
                        {
                            ShelfCode = shelf.ShelfCode,
                            ModulesStr = shelf.ModulesStr,
                        }
                    };
                else
                    return new ShelfGoInInstoreResponse()
                    {
                        Code = 201,
                        Message = $"货架进入入库模式失败：{string.Join(",", shelf.ExceptionMessages)}",
                        Data = null
                    };
            }
            catch (Exception ex)
            {
                return new ShelfGoInInstoreResponse()
                {
                    Code = 300,
                    Message = $"货架进入入库模式发生异常：{ex.Message}",
                    Data = null
                };
            }
        }

        public ResponseBase shelfGoOutInStore(ShelfGoOutInStoreRequest request)
        {
            //获取货架
            var shelf = ShelfManager.Shelves.Where(t => t.ShelfCode == request.ShelfCode).FirstOrDefault();
            if (shelf == null)//货架不存在
            {
                return new ResponseCommon()
                {
                    Code = 201,
                    Message = $"退出入库模式失败：货架[{request.ShelfCode}]不存在!",
                };
            }

            //判断扫码枪 是否被其他扫码枪所占用 如果占用 直接退出入库模式 不发指令
            shelf.GoOutInstore();

            if (shelf.ExceptionMessages == null || shelf.ExceptionMessages.Count == 0)
                //已退出
                return new ResponseCommon()
                {
                    Code = 200,
                    Message = $"货架[{request.ShelfCode}]已退出入库模式!",
                };
            else
                return new ResponseCommon()
                {
                    Code = 200,
                    Message = $"货架[{request.ShelfCode}]已退出入库模式!{string.Join(",", shelf.ExceptionMessages)}",
                };
        }

        public async Task<ResponseBase> queryByMatSn(QueryByMatSnRequest request)
        {
            //判断物料是否已入库
            var inventory = await DbHelp.db.Queryable<InventoryDetail>().Where(t => t.MatSN == request.MatSn).FirstAsync();
            if (inventory != null)
            {
                return new ResponseCommon<MatInfo>()
                {
                    Code = 201,
                    Message = $"操作失败：物料{inventory.MatSN}已入库!库位为{inventory.StoreCode}",
                };
            }

            IShelfBase shelf = null;
            if (!request.SingleLightIn)
            {
                //获取货架
                shelf = ShelfManager.Shelves.Where(t => t.ShelfCode == request.ShelfCode).FirstOrDefault();
                if (shelf == null)//货架不存在
                {
                    return new ResponseCommon<MatInfo>()
                    {
                        Code = 201,
                        Message = $"操作失败：货架[{request.ShelfCode}]不存在!",
                    };
                }
                //判断当前是否是入库模式
                if (shelf.CurrentMode != Mode.入库模式)
                {
                    return new ResponseCommon<MatInfo>()
                    {
                        Code = 201,
                        Message = $"操作失败：货架[{request.ShelfCode}]不在入库模式!\r\n当前为{shelf.CurrentMode}",
                    };
                }
                //物料在入库模式，更新时间 避免被后台线程关闭
                shelf.SetCurrentModeTime = DateTime.Now;
            }

            #region 获取物料数据 //调用接口或者直接查询数据库
            // 调用接口
            if (LocalFile.Config.IsAccessWMS)
            {
                #region 调用WMS接口获取物料信息
                try
                {
                    var body = new
                    {
                        materialBar = request.MatSn
                    };
                    var Result = Tool.ApiHelp.GetDataFromHttp<ResponseCommon<List<queryByBarResponse>>>("http://192.168.2.23:9213/integrate/instock/queryBybar", body, "POST", true);

                    //查询到物料信息
                    if (Result != null && Result.Code == 200 && Result.Data != null && Result.Data.Count > 0)
                    {
                        var data = Result.Data.First();
                        if (!request.SingleLightIn && shelf != null)
                            shelf.InStoreData = new MatInfoResponse()
                            {
                                materialBar = data.materialBar,
                                materialCode = data.materialCode,
                                materialName = data.materialName,
                                materialQty = data.materialQty,
                                materialSpec = data.materialSpec,
                                batchNo = data.batchNo,
                                supplier = "",
                                customer = "",

                                InstoreUser = request.UserName
                            };

                        var matInfo = new MatInfo()
                        {
                            MatSn = data.materialBar,
                            MatCode = data.materialCode,
                            MatName = data.materialName,
                            MatBatch = data.batchNo,
                            MatQty = (int)data.materialQty,
                            MatSpec = data.materialSpec,
                            MatSupplier = "",
                            MatCustomer = "",
                        };

                        return new ResponseCommon<MatInfo>()
                        {
                            Code = 200,
                            Data = matInfo,
                            Message = "success"
                        };
                    }
                    else if (Result != null && Result.Code == 200 && (Result.Data == null || Result.Data.Count == 0))
                    {
                        //Mes系统中未获取到物料信息

                        //简单校验看是否满足海康物料
                        //海康物料 只扫了外箱码 未扫条码
                        if ((request.MatSn.Length == 54 || request.MatSn.Length == 56) && !request.MatSn.Contains("\\") && !request.MatSn.Contains("/"))
                        {

                            if (!request.SingleLightIn && shelf != null)
                                shelf.InStoreData = new MatInfoResponse()
                                {
                                    materialBar = request.MatSn,
                                    materialCode = "暂时未知",
                                    materialName = "暂时未知",
                                    materialQty = 0,
                                    materialSpec = "暂时未知",
                                    batchNo = "暂时未知",
                                    supplier = "",
                                    customer = "",

                                    InstoreUser = request.UserName
                                };

                            var matInfo = new MatInfo()
                            {
                                MatSn = request.MatSn,
                                MatCode = "暂时未知",
                                MatName = "暂时未知",
                                MatBatch = "暂时未知",
                                MatQty = 0,
                                MatSpec = "暂时未知",
                                MatSupplier = "",
                                MatCustomer = "",
                            };

                            return new ResponseCommon<MatInfo>()
                            {
                                Code = 200,
                                Data = matInfo,
                                Message = "success"
                            };
                        }

                        return new ResponseCommon<MatInfo>()
                        {
                            Code = 201,
                            Message = $"操作失败：调用Mes接口未获取到物料信息！",
                        };
                    }
                    else
                    {
                        return new ResponseCommon<MatInfo>()
                        {
                            Code = 201,
                            Message = $"操作失败：调用Mes接口失败！",
                        };
                    }
                }
                catch (Exception e)
                {
                    return new ResponseCommon<MatInfo>()
                    {
                        Code = 300,
                        Message = $"操作失败：调用Mes接口发生异常{e.Message}",
                    };
                }
                #endregion
            }
            //查询数据库是否存在这个物料
            else
            {
                var matInfo = await DbHelp.db.Queryable<MatInfo>().Where(t => t.MatSn == request.MatSn).FirstAsync();
                if (matInfo != null)
                {
                    if (!request.SingleLightIn && shelf != null)
                        shelf.InStoreData = new MatInfoResponse()
                        {
                            materialBar = matInfo.MatSn,
                            materialCode = matInfo.MatCode,
                            materialName = matInfo.MatName,
                            materialQty = matInfo.MatQty,
                            materialSpec = matInfo.MatSpec,
                            batchNo = matInfo.MatBatch,
                            supplier = matInfo.MatSupplier,
                            customer = matInfo.MatCustomer,

                            InstoreUser = request.UserName
                        };

                    return new ResponseCommon<MatInfo>()
                    {
                        Code = 200,
                        Data = matInfo,
                        Message = "success"
                    };
                }
                else
                    return new ResponseCommon<MatInfo>()
                    {
                        Code = 201,
                        Data = null,
                        Message = $"不存在物料{request.MatSn}"
                    };
            }
            #endregion
        }

        /// <summary>
        /// 单灯出库时查询物料信息 这里返回库存的数据
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ResponseBase> queryByMatSnOut(QueryByMatSnRequest request)
        {
            //判断物料是否已入库
            var inventory = await DbHelp.db.Queryable<InventoryDetail>().Where(t => t.MatSN == request.MatSn).FirstAsync();
            if (inventory == null)
            {
                return new ResponseCommon<MatInfo>()
                {
                    Code = 201,
                    Message = $"操作失败：物料不在库存内，无法进行出库！",
                };
            }
            else
            {
                return new ResponseCommon<MatInfo>()
                {
                    Code = 200,
                    Message = $"Success",
                    Data = new MatInfo()
                    {
                        Id = inventory.Id,
                        MatSn = inventory.MatSN,
                        MatCode = inventory.MatCode,
                        MatName = inventory.MatName,
                        MatBatch = inventory.MatBatch,
                        MatQty = inventory.MatQty,
                        MatSpec = inventory.MatSpec,
                        MatSupplier = inventory.MatSupplier,
                        MatCustomer = inventory.MatCustomer,
                    }
                };
            }
        }

        public async Task<ResponseBase> queryInstoreStatus(QueryByMatSnRequest request)
        {
            //获取货架
            var shelf = ShelfManager.Shelves.Where(t => t.ShelfCode == request.ShelfCode).FirstOrDefault();
            if (shelf == null)//货架不存在
            {
                return new ResponseCommon()
                {
                    Code = 201,
                    Message = $"货架[{request.ShelfCode}]不存在!",
                };
            }

            //判断当前是否是入库模式
            if (shelf.CurrentMode != Mode.入库模式)
            {
                return new ResponseCommon()
                {
                    Code = 201,
                    Message = $"货架[{request.ShelfCode}]已退出入库模式!\r\n当前为{shelf.CurrentMode}",
                };
            }

            //配置这个时间相当于需要入库扫码后需要等待的时间
            var timeOut = LocalFile.Config.InstoreTimeOut;
            var timeSpan = TimeSpan.FromMilliseconds(0);
            var beginTime = DateTime.Now;
            while (timeSpan <= TimeSpan.FromMilliseconds(timeOut))
            {
                timeSpan = DateTime.Now - beginTime;
                //已入库当前扫码的物料时 查询数据库
                if (shelf.InStoreData == null || (shelf.InStoreData as object) == null)
                {
                    await Task.Delay(50);
                    var inventoryDetail = DbHelp.db.Queryable<InventoryDetail>()
                                                   .Where(t => t.MatSN == request.MatSn)
                                                   .First();
                    if (inventoryDetail != null)
                    {
                        return new ResponseCommon()
                        {
                            Code = 200,
                            Message = $"入库成功！物料已放入库位{inventoryDetail.StoreCode}",
                            Data = new
                            {
                                StoreCode = inventoryDetail.StoreCode,
                            }
                        };
                    }
                    else
                        break;
                }
                //延时处理
                Thread.Sleep(50);
            }
            //超时未成功入库
            shelf.InStoreData = null;
            return new ResponseCommon()
            {
                Code = 201,
                Message = $"超时未入库！请重新扫码后入库！",
                Data = new
                {
                    StoreCode = string.Empty,
                }
            };
        }

    }
}
