using Microsoft.AspNetCore.Components;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.Extensions.DependencyInjection;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using PropertyChanged;
using Rdh.ElectronicMedicineKit.EntityFrameworkCore;
using Rdh.ElectronicMedicineKit.Models;
using Rdh.SocketServer.Client.BLL;
using Rdh.SocketServer.Client.Models;
using Rdh.SocketServer.Client.MQ;
using RDH.Data;
using RDH.Data.BLL;
using RDH.Data.Models;
using Serilog;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;
using System.Windows;
using System.Windows.Input;
using TouchSocket.Core.ByteManager;
using TouchSocket.Sockets;

namespace Rdh.SocketServer.Client.ViewModels
{
    [AddINotifyPropertyChangedInterface]
    public class MainWindowViewModel : BindableBase
    {
        private readonly IRegionManager _regionManager;
        private readonly ApplicationDbContext _dbContext;
        private readonly ITcpService _tcpService;
        private readonly Encoding _encoding;
        private List<PortableStorageType> _listStorageTypes;
        public const String ViewOfData = "有效数据",
            ViewOfInvalid = "无效数据",
            ViewOfClient = "客户端",
            ViewOfLog = "日志";
        #region Constructor
        public MainWindowViewModel(IRegionManager regionManager, IServiceProvider serviceProvider, ApplicationDbContext dbContext)
        {
            ListLogs = new ObservableCollection<LogModel>();
            _regionManager = regionManager;
            _dbContext = dbContext;
            var servers = serviceProvider.GetServices<ITcpService>();
            _tcpService = servers?.FirstOrDefault(x => x.ServerName == "ElectronicMedicineKit");
            _encoding = Encoding.GetEncoding("gb2312");
            if (_tcpService != null)
            {
                if (_tcpService is TcpService service)
                {
                    service.Connecting += (client, e) =>
                    {
                        Log($"{client.ID}正在建立连接");
                    };//有客户端正在连接
                    service.Connected += (client, e) =>
                    {
                        Log($"已从{client.ID}建立连接");
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            ListClients.Add(new TimeFlagModel<SocketClient>(client));
                        });
                    };//有客户端连接
                    service.Disconnected += (client, e) =>
                    {
                        Log($"已从{client.ID}断开连接");
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            lock (ListClients) 
                            {
                                for (Int32 i = 0; i < ListClients.Count; i++) 
                                {
                                    if (ListClients[i].Model.IP == client.IP) 
                                    {
                                        ListClients.RemoveAt(i);
                                        i--;
                                    }
                                }
                            }
                        });
                    };//有客户端断开连接
                    service.Received += Reveiced;
                }
                Task.Factory.StartNew(() => DataHandle());
            }

            _dbContext.Database.EnsureCreated();
            DeleteDataCommand = new DelegateCommand(DeleteDataCommandHandler);
            ClearCommand = new DelegateCommand<String>(ClearCommandHandler);
        }
        #endregion

        #region Properties
        public ObservableCollection<Pocket> Pockets { get; set; } = new ObservableCollection<Pocket>();
        public Pocket SelectedData { get; set; }
        public ObservableCollection<Pocket> InvalidPockets { get; set; } = new ObservableCollection<Pocket>();
        public ObservableCollection<LogModel> ListLogs { get; set; }
        public ObservableCollection<TimeFlagModel<SocketClient>> ListClients { get; set; } = new ObservableCollection<TimeFlagModel<SocketClient>>();
        public ICommand ClearCommand { get; set; }
        public ICommand DeleteDataCommand { get; set; }
        public string Title { get; set; }
        #endregion

        public void Init() 
        {
            Task.Run(() =>
            {
                try
                {
                    using (ConnectionSessionScope conn = new ConnectionSessionScope())
                    {
                        PortableStorageTypeBLL portableStorageTypeBLL = new PortableStorageTypeBLL();
                        _listStorageTypes = portableStorageTypeBLL.ListModels(100, 0);
                    }
                }
                catch (Exception ex)
                {
                    Log($"加载药箱类型出错：{ex.Message}", -1);
                    Serilog.Log.Warning($"{ex.StackTrace}");
                }
            });
        }

        #region Private Methods
        #region 页面命令处理
        //删除数据按钮
        private void DeleteDataCommandHandler() 
        {
            if (SelectedData == null) 
            {
                return;
            }
            RemovePocket(SelectedData);
            Log($"删除数据:{SelectedData.Data}");
        }
        //清空按钮
        private void ClearCommandHandler(String view)
        {
            switch (view)
            {
                case ViewOfLog:
                    this.ListLogs.Clear();
                    break;
                case ViewOfInvalid:
                    InvalidPockets.Clear();
                    break;
            }
        }
        #endregion
        private void Reveiced(SocketClient client, ByteBlock byteBlock, IRequestInfo requestInfo)
        {
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                Log($"Received from:{client.IP}");
                EleMedKitData? data = requestInfo as EleMedKitData;
                if (data == null)
                {
                    InvalidPockets.Add(new Pocket(client, null));
                }
                else
                {
                    if (data.Message == null)
                    {
                        Pockets.Add(new Pocket(client, data));
                    }
                    else
                    {
                        Log($"解析失败：{data.Message}", -1);
                        InvalidPockets.Add(new Pocket(client, data));
                    }
                }
            }));
        }
        private void DataHandle()
        {
            while (true)
            {
                Pocket? curPocket = PeekData();
                if (curPocket != null)
                {
                    EleMedKitProtocol responseData = null;
                    switch (curPocket.Data.ProtocolDataInfo.Command)
                    {
                        case EleMedKitCommand.RequestClock:
                            ClockResponseProtocol clockResponseProtocol = new ClockResponseProtocol();
                            responseData = clockResponseProtocol;
                            break;
                        case EleMedKitCommand.RequestSupplyList:
                            try
                            {
                                ResponseSupplyDrugProtocol responseSupplyDrugProtocol = new ResponseSupplyDrugProtocol();
                                responseSupplyDrugProtocol.ListSupplyResult = new List<DrugLotProtocol>();
                                RequestSupplyDrugProtocol requestSupplyDrugProtocol = (RequestSupplyDrugProtocol)curPocket.Data.ProtocolDataInfo;
                                responseSupplyDrugProtocol.UserInfo = requestSupplyDrugProtocol.UserInfo;
                                responseSupplyDrugProtocol.EleMedKitCode = requestSupplyDrugProtocol.EleMedKitCode;
                                String? state = null;
                                StorageSpacePortableLink? requestStorageLink = null;
                                using (ConnectionSessionScope conn = new ConnectionSessionScope()) 
                                {
                                    requestStorageLink = GetRequestStorageLink(null, requestSupplyDrugProtocol.EleMedKitCode, out state);
                                }
                                if (state != null
                                    || requestStorageLink == null)
                                {
                                    Log("检查药箱信息不通过", -1);
                                    break;
                                }
                                responseSupplyDrugProtocol.MedKitTypeCode = GetPortableTypeCode(requestStorageLink);
                                if (requestSupplyDrugProtocol.ListBarcode != null
                                   && requestSupplyDrugProtocol.ListBarcode.Count > 0)
                                {
                                    IEnumerable<ItemBarcodeLibrary> barcodeLibraries = new ShouShuShiBLL()
                                        .ListBarcodeInfo(requestSupplyDrugProtocol.ListBarcode.ToArray());
                                    if (barcodeLibraries != null && barcodeLibraries.Count() > 0)
                                    {
                                        IEnumerable<IGrouping<Guid?, ItemBarcodeLibrary>> itemGroups = barcodeLibraries.GroupBy(x => x.ItemKey);
                                        using (TransactionScope transaction = new TransactionScope())
                                        {
                                            using (ConnectionSessionScope conn = new ConnectionSessionScope())
                                            {
                                                UserInfo? requestUser = GetRequestUserInfo(new UserInfoBLL(), requestSupplyDrugProtocol.UserInfo, out state);
                                                if (state != null || requestUser == null)
                                                {
                                                    Log("检查用户信息不通过:" + state, -1);
                                                    break;
                                                }
                                                foreach (IGrouping<Guid?, ItemBarcodeLibrary> barcodeLibrary in itemGroups)
                                                {
                                                    PortableStorageItemBLL portableStorageItemBLL = new PortableStorageItemBLL();
                                                    PortableStorageItem? requestPortableStorageItem = GetRequestPortableItem(portableStorageItemBLL,
                                                        requestStorageLink, barcodeLibrary.Key.GetValueOrDefault());
                                                    if (requestPortableStorageItem == null)
                                                    {
                                                        //在药箱的配药列表未找到指定药品时，将返回的条码信息标记为“多”
                                                        responseSupplyDrugProtocol.ListSupplyResult.AddRange(barcodeLibrary.Select(x => new DrugLotProtocol
                                                        {
                                                            Barcode = x.Barcode,
                                                            SupplyState = SupplyStateCodes.Add,
                                                        }));
                                                        continue;
                                                    }
                                                    #region 更新药品库存及记录
                                                    //增加药品操作记录
                                                    ItemTransactionBLL itemTransactionBLL = new ItemTransactionBLL();
                                                    ItemTransaction itemTransaction = new ItemTransaction
                                                    {
                                                        Key = Guid.NewGuid(),
                                                        CreateTime = DateTime.Now,
                                                        //DeviceKey = requestStorageLink.StorageSpace.DeviceKey,
                                                        ItemKey = barcodeLibrary.Key,
                                                        CreateBy = requestUser.Key,
                                                        TransactionType = TransactionTypeCodes.MedKitSupplyPlan.ToString(),
                                                        Quantity = barcodeLibrary.Count(),
                                                        Ext02 = requestStorageLink.PortableStorage?.Code,
                                                    };
                                                    //增加库存更新记录
                                                    StorageSpaceItemTransactionBLL storageSpaceItemTransactionBLL = new StorageSpaceItemTransactionBLL();
                                                    StorageSpaceItemTransaction ssiTransaction = new StorageSpaceItemTransaction
                                                    {
                                                        Key = Guid.NewGuid(),
                                                        CreateBy = requestUser.Key,
                                                        CreateTime = DateTime.Now,
                                                        StorageSpaceItemKey = requestPortableStorageItem.Key,
                                                        ItemTransactionKey = itemTransaction.Key,
                                                    };
                                                    #endregion
                                                    PortableStorageItemLotBLL portableStorageItemLotBLL = new PortableStorageItemLotBLL();
                                                    SPILItemTransactionBLL sPILItemTransactionBLL = new SPILItemTransactionBLL();
                                                    #region 更新批号库存和记录
                                                    Int32 totalIncrease = 0;
                                                    foreach (ItemBarcodeLibrary b in barcodeLibrary)
                                                    {
                                                        PortableStorageItemLot portableStorageItemLot = portableStorageItemLotBLL.GetByItemBarcode(b.Barcode);
                                                        if (portableStorageItemLot == null)
                                                        {
                                                            portableStorageItemLot = new PortableStorageItemLot
                                                            {
                                                                Key = Guid.NewGuid(),
                                                                CreateTime = DateTime.Now,
                                                                PortableStorageItemkey = requestPortableStorageItem.Key,
                                                                Quantity = 1,
                                                                ItemKey = requestPortableStorageItem.ItemKey,
                                                                LotKey = b.ItemLotKey,
                                                                Ext01 = b.Barcode,
                                                            };
                                                            totalIncrease += 1;
                                                            portableStorageItemLotBLL.Save(portableStorageItemLot);
                                                            SPILItemTransaction spilTransaction = new SPILItemTransaction
                                                            {
                                                                Key = Guid.NewGuid(),
                                                                CreateTime = DateTime.Now,
                                                                Quantity = 1,
                                                                ItemLotKey = b.ItemLotKey,
                                                                ItemTransactionKey = itemTransaction.Key,
                                                                StorageSpaceItemLotKey = portableStorageItemLot.Key,
                                                                Ext01 = b.Barcode,
                                                            };
                                                            sPILItemTransactionBLL.Save(spilTransaction);
                                                        }
                                                        //生成返回数据
                                                        responseSupplyDrugProtocol.ListSupplyResult.Add(new DrugLotProtocol
                                                        {
                                                            Barcode = b.Barcode,
                                                            SupplyState = SupplyStateCodes.Success,
                                                            DrugKey = barcodeLibrary.Key.GetValueOrDefault().ToString(),
                                                            DrugLotCode = b.ItemLotInfo.LotNo,
                                                        });
                                                    }
                                                    #endregion
                                                    if (totalIncrease > 0) 
                                                    {
                                                        itemTransactionBLL.Save(itemTransaction);
                                                        //增加药箱药品库存
                                                        requestPortableStorageItem.CurrentQuantity = requestPortableStorageItem.CurrentQuantity.GetValueOrDefault() + barcodeLibrary.Count();
                                                        portableStorageItemBLL.Update(requestPortableStorageItem);
                                                        storageSpaceItemTransactionBLL.Save(ssiTransaction);
                                                    }
                                                }
                                                transaction.Complete();
                                            }
                                        }
                                    }
                                }
                                responseData = responseSupplyDrugProtocol;
                            }
                            catch (Exception ex)
                            {
                                Log("查询药品条码信息出错：" + ex.Message, -1);
                            }
                            break;
                        case EleMedKitCommand.RequestLocation:
                            try
                            {
                                LocationResponseProtocol locationResponse = new LocationResponseProtocol();
                                LocationRequestProtocol locationRequest = (LocationRequestProtocol)curPocket.Data.ProtocolDataInfo;
                                #region 获取基站绑定的手术间
                                IEnumerable<RDH.Data.Models.OperationRoom> rooms = new ShouShuShiBLL().ListOperationRoomByStation(locationRequest.StationCode);
                                if (rooms != null && rooms.Count() > 0)
                                {
                                    //以3位字符显示手术间号（左侧补0）
                                    locationResponse.SectionCode = rooms.First().RoomId.PadLeft(3, '0');
                                    locationResponse.EleMedKitCode = locationRequest.EleMedKitCode;
                                    responseData = locationResponse;
                                    #region 记录定位
                                    //记录时，使用纯编号（没有左侧的补0）
                                    String simpleMedkitCode = locationRequest.EleMedKitCode.TrimStart('0');
                                    String simpleStationCode = locationRequest.StationCode.TrimStart('0');
                                    PortableStorageTrackBLL portableStorageTrackBLL = new PortableStorageTrackBLL();
                                    PortableStorageTrack lastTrack = portableStorageTrackBLL.GetLastTrackByItem(simpleMedkitCode);
                                    if (lastTrack == null
                                        || lastTrack.CreateTime.GetValueOrDefault().Date < DateTime.Now.Date
                                        || lastTrack.TrackCode != simpleStationCode)
                                    {
                                        using (ConnectionSessionScope scope = new ConnectionSessionScope())
                                        {
                                            PortableStorageTrack curTrack = new PortableStorageTrack();
                                            curTrack.CreateTime = DateTime.Now;
                                            curTrack.ItemCode = simpleMedkitCode;
                                            curTrack.TrackCode = simpleStationCode;
                                            portableStorageTrackBLL.Save(curTrack);
                                        }
                                    }
                                    #endregion
                                }
                                else 
                                {
                                    Log($"基站编号[{locationRequest.StationCode}]未配置手术间");
                                }
                                #endregion
                            }
                            catch (Exception ex)
                            {
                                Log("处理定位信息出错：" + ex.Message, -1);
                            }
                            break;
                        case EleMedKitCommand.RequestPatientOperation:
                            try
                            {
                                RequestPatientOperationProtocol requestProtocol = (RequestPatientOperationProtocol)curPocket.Data.ProtocolDataInfo;
                                if (requestProtocol.RoomCode == null)
                                {
                                    Log("请求手术信息时，手术间编号为空", -1);
                                }
                                else
                                {
                                    ResponsePatientOperationProtocol responseProtocol = new ResponsePatientOperationProtocol();
                                    responseProtocol.EleMedKitCode = requestProtocol.EleMedKitCode;
                                    responseProtocol.ListOperations = new List<PatientOperationProtocol>();
                                    IEnumerable<RDH.Data.Models.PatientOperationInfo> operationInfos = new ShouShuShiBLL()
                                        .ListOperattionInfoByRoom(requestProtocol.RoomCode.TrimStart('0'));
                                    if (operationInfos != null)
                                    {
                                        responseProtocol.ListOperations.AddRange(operationInfos.Select(x => new PatientOperationProtocol
                                        {
                                            Key = x.Key.GetValueOrDefault().ToString(),
                                            OperationName = SubString(x.OperationName, 10),
                                            PatientCode = x.PatientInfo.PatientId,
                                            Age = GetAge(x.PatientInfo.Birthday),
                                            Gender = GetGender(x.PatientInfo.Gender),
                                            OperationPart = "-",
                                            PatientName = x.PatientInfo.Name,
                                        }));
                                    }
                                    responseData = responseProtocol;
                                }
                            }
                            catch (Exception ex)
                            {
                                Log("查询手术排班信息出错：" + ex.Message, -1);
                            }
                            break;
                        case EleMedKitCommand.RequestPatientOperationUsage:
                            try
                            {
                                ResponseOperationUsageProtocol responseUsageData = new ResponseOperationUsageProtocol();
                                RequestOperationUsageProtocol requestUsageProtocol = (RequestOperationUsageProtocol)curPocket.Data.ProtocolDataInfo;
                                using (TransactionScope transaction = new TransactionScope())
                                {
                                    using (ConnectionSessionScope conn = new ConnectionSessionScope())
                                    {
                                        #region 数据验证
                                        responseUsageData.EleMedKitCode = requestUsageProtocol.EleMedKitCode;
                                        //检查药品列表
                                        if (requestUsageProtocol.ListDrugs == null
                                            || requestUsageProtocol.ListDrugs.Count == 0)
                                        {
                                            Log("用药信息为空", -1);
                                            break;
                                        }
                                        //检查用户信息
                                        String state;
                                        UserInfoBLL userInfoBLL = new UserInfoBLL();
                                        UserInfo? requestUser = GetRequestUserInfo(userInfoBLL, requestUsageProtocol.UserInfo, out state);
                                        if (state != null)
                                        {
                                            Log("检查用户信息不通过:" + state, -1);
                                            break;
                                        }
                                        //检查手术排班信息
                                        if (requestUsageProtocol.OperationInfo == null)
                                        {
                                            Log("手术排班信息为空", -1);
                                            break;
                                        }
                                        Guid operationKey;
                                        if (!Guid.TryParse(requestUsageProtocol.OperationInfo.Key, out operationKey))
                                        {
                                            Log("手术排班ID无效：" + requestUsageProtocol.OperationInfo.Key, -1);
                                            break;
                                        }
                                        PatientOperationInfoBLL patientOperationInfoBLL = new PatientOperationInfoBLL();
                                        PatientOperationInfo requestOperation = patientOperationInfoBLL.Get(new PatientOperationInfo
                                        {
                                            Key = operationKey
                                        });
                                        if (requestOperation == null)
                                        {
                                            Log("未找到请求的手术排班：" + requestUsageProtocol.OperationInfo.Key, -1);
                                            break;
                                        }
                                        #endregion
                                        OperationTakeItemBagBLL operationTakeItemBagBLL = new OperationTakeItemBagBLL();
                                        OperationTakeItemBag curTakeBag = operationTakeItemBagBLL.GetByOperation(requestOperation);
                                        #region 保存OperationTakeItemBag
                                        if (curTakeBag == null)
                                        {
                                            curTakeBag = new OperationTakeItemBag();
                                            curTakeBag.CreateTime = DateTime.Now;
                                            curTakeBag.CreateBy = requestUser.Key;
                                            curTakeBag.Key = Guid.NewGuid();
                                            curTakeBag.OperationKey = requestOperation.Key;
                                            curTakeBag.SnapshotKey = Guid.NewGuid();
                                            curTakeBag.Ext02 = requestUsageProtocol.RoomCode;
                                            curTakeBag.Ext05 = requestUsageProtocol.EleMedKitCode;
                                            operationTakeItemBagBLL.Save(curTakeBag);
                                        }
                                        //else
                                        //{
                                        //    Log("重复接收到用药信息：" + requestOperation.OperationId, -1);
                                        //    break;
                                        //}
                                        #endregion
                                        PortableStorageItemBLL portableStorageItemBLL = new PortableStorageItemBLL();
                                        PortableStorageItemLotBLL portableStorageItemLotBLL = new PortableStorageItemLotBLL();
                                        StorageSpaceItemTransactionBLL storageSpaceItemTransactionBLL = new StorageSpaceItemTransactionBLL();
                                        SPILItemTransactionBLL sPILItemTransactionBLL = new SPILItemTransactionBLL();
                                        OperationTakeItemBLL operationTakeItemBLL = new OperationTakeItemBLL();
                                        IEnumerable<OperationTakeItem> takeHistory = operationTakeItemBLL.ListTakeItemsByTakeBag(curTakeBag);
                                        Boolean drugHandleFlag = true;
                                        #region 根据请求的标签获取对应库存
                                        List<PortableStorageItemLot> usageWithInventory = new List<PortableStorageItemLot>();
                                        foreach (DrugUsageProtocol d in requestUsageProtocol.ListDrugs)
                                        {
                                            OperationTakeItem? historyItem = takeHistory == null
                                                ? null
                                                : takeHistory.FirstOrDefault(x => x.ItemKey.GetValueOrDefault().ToString() == d.DrugKey);
                                            if (historyItem != null) 
                                            {
                                                Log($"重复接收到药品用药信息,药品：{historyItem.Item.ItemCommonName}");
                                            }
                                            else
                                            {
                                                if (d.UsageCode == DrugUsageCodes.Used
                                                    || d.UsageCode == DrugUsageCodes.Lost
                                                    || d.UsageCode == DrugUsageCodes.LastUsed)
                                                {
                                                    PortableStorageItemLot inventoryLot = portableStorageItemLotBLL.GetByItemBarcode(d.Barcode);
                                                    //if (inventoryLot == null)
                                                    //{
                                                    //    Log("未找到药品条码标签：" + d.Barcode, -1);
                                                    //    drugHandleFlag = false;
                                                    //    break;
                                                    //}
                                                    //if (inventoryLot.PortableStorageItem.Item.Key.ToString() != d.DrugKey)
                                                    //{
                                                    //    Log("上传的药品ID与数据库不符：" + d.DrugKey, -1);
                                                    //    drugHandleFlag = false;
                                                    //    break;
                                                    //}
                                                    if (inventoryLot != null) 
                                                    {
                                                        usageWithInventory.Add(inventoryLot);
                                                    }
                                                }
                                            }
                                        }
                                        if (!drugHandleFlag)
                                        {
                                            break;
                                        } 
                                        #endregion
                                        #region 更新库存和业务记录
                                        IEnumerable<IGrouping<Guid, PortableStorageItemLot>> inventoryLogGroup = usageWithInventory
                                            .GroupBy(x => x.LotKey.GetValueOrDefault());
                                        //保存OperationTakeItem
                                        foreach (IGrouping<Guid, PortableStorageItemLot> g in inventoryLogGroup)
                                        {
                                            OperationTakeItem operationTakeItem = new OperationTakeItem
                                            {
                                                Key = Guid.NewGuid(),
                                                SnapshotKey = Guid.NewGuid(),
                                                ItemKey = g.First().ItemKey,
                                                Ext01 = g.First().LotKey.GetValueOrDefault().ToString(),
                                                TakeBagKey = curTakeBag.Key,
                                                TakeQuantity = g.Count(),
                                            };
                                            operationTakeItemBLL.Save(operationTakeItem);
                                            //更新PortableStorageItem
                                            PortableStorageItem psi = g.First().PortableStorageItem;
                                            psi.CurrentQuantity = psi.CurrentQuantity.GetValueOrDefault() - g.Count();
                                            portableStorageItemBLL.Update(psi);
                                            //保存StorageSpaceItemTransaction
                                            StorageSpaceItemTransaction ssiTransaction = new StorageSpaceItemTransaction()
                                            {
                                                Key = Guid.NewGuid(),
                                                CreateBy = requestUser.Key,
                                                CreateTime = DateTime.Now,
                                                StorageSpaceItemKey = psi.Key,
                                                ItemTransactionKey = curTakeBag.Key,
                                                Ext01 = g.Count().ToString(),
                                            };
                                            storageSpaceItemTransactionBLL.Save(ssiTransaction);
                                        }
                                        //更新批号库存
                                        foreach (PortableStorageItemLot psil in usageWithInventory)
                                        {
                                            SPILItemTransaction sPILItemTransaction = new SPILItemTransaction()
                                            {
                                                Key = Guid.NewGuid(),
                                                StorageSpaceItemLotKey = psil.Key,
                                                Quantity = 1,
                                                ItemTransactionKey = curTakeBag.Key.GetValueOrDefault(),
                                                ItemLotKey = psil.LotKey,
                                                Ext01 = psil.Ext01,
                                            };
                                            sPILItemTransactionBLL.Save(sPILItemTransaction);
                                            portableStorageItemLotBLL.Delete(psil);
                                        }
                                        #endregion
                                        #region 更新手术状态
                                        //完成时间
                                        requestOperation.OperationOverTime = DateTime.Now;
                                        patientOperationInfoBLL.UpdateCurrent(requestOperation); 
                                        #endregion
                                        transaction.Complete();
                                    }
                                }
                                responseData = responseUsageData;
                            }
                            catch (Exception ex)
                            {
                                Log(ex.Message, -1);
                            }
                            break;
                        case EleMedKitCommand.RequestReturnMedKit:
                            try
                            {
                                Log("请求归还");
                                ResponseMedKitReturnProtocol responseReturnProtocol = new ResponseMedKitReturnProtocol();
                                RequestMedKitReturnProtocol requestReturnProtocol = (RequestMedKitReturnProtocol)curPocket.Data.ProtocolDataInfo;
                                responseReturnProtocol.EleMedKitCode = requestReturnProtocol.EleMedKitCode;
                                String? state = null;
                                StorageSpacePortableLink? requestStorageLink = null;
                                UserInfo? requestUser = null;
                                using (ConnectionSessionScope conn = new ConnectionSessionScope())
                                {
                                    requestStorageLink = GetRequestStorageLink(null, requestReturnProtocol.EleMedKitCode, out state);
                                    if (state != null
                                        || requestStorageLink == null)
                                    {
                                        Log("检查药箱信息不通过", -1);
                                        break;
                                    }
                                    UserInfoBLL userInfoBLL = new UserInfoBLL();
                                    requestUser = GetRequestUserInfo(userInfoBLL, requestReturnProtocol.UserInfo, out state);
                                    if (state != null || requestUser == null)
                                    {
                                        Log("检查用户信息不通过:" + state, -1);
                                        break;
                                    }
                                }
                                responseReturnProtocol.State = new StateProtocol()
                                {
                                    IsSuccess = true
                                };
                                responseData = responseReturnProtocol;
                                state = MQService.Singleton.RequestReturnMedKit(requestUser, requestStorageLink);
                                if (state != null)
                                {
                                    Log("向药箱柜发送退药请求失败：" + state, -1);
                                }
                            }
                            catch (Exception ex)
                            {
                                Log("归还出错：" + ex.Message, -1);
                            }
                            break;
                        case EleMedKitCommand.RequestDrugLend:
                            try
                            {
                                Log("请求借药");
                                RequestDrugLendProtocol requestLendProtocol = (RequestDrugLendProtocol)curPocket.Data.ProtocolDataInfo;
                                StorageSpacePortableLink? requestStorageLink = null;
                                String? state = null;
                                using (ConnectionSessionScope conn = new ConnectionSessionScope())
                                {
                                    requestStorageLink = GetRequestStorageLink(null, requestLendProtocol.EleMedKitCode, out state);
                                    if (state != null
                                        || requestStorageLink == null)
                                    {
                                        Log("检查药箱信息不通过", -1);
                                        break;
                                    }
                                    //根据药箱定位，获取最近的手术间
                                    PortableStorageTrackBLL portableStorageTrackBLL = new PortableStorageTrackBLL();
                                    PortableStorageTrack lastTrack = portableStorageTrackBLL.GetLastTrackByItem(requestLendProtocol.EleMedKitCode.TrimStart('0'));
                                    if (lastTrack == null) 
                                    {
                                        Log($"未找到药箱[{requestLendProtocol.EleMedKitCode}]最近的定位信息");
                                        break;
                                    }
                                    OperationRoomBLL operationRoomBLL = new OperationRoomBLL();
                                    RDH.Data.Models.OperationRoom currentRoom = operationRoomBLL.GetOperationRoomBySignalStation(lastTrack.TrackCode.PadLeft(3, '0'));
                                    if (currentRoom == null) 
                                    {
                                        Log($"未找到基站[{lastTrack.TrackCode}]配置的手术间");
                                        break;
                                    }
                                    //根据手术间，获取最近的借药信息
                                    SPILItemTransactionBLL sPILItemTransactionBLL = new SPILItemTransactionBLL();
                                    IEnumerable<SPILItemTransaction> transactions = sPILItemTransactionBLL.ListMekKitDrugLendTransactionByRoom(currentRoom.RoomName.TrimStart('0'));
                                    if (transactions == null || transactions.Count() == 0)
                                    {
                                        Log($"未找到手术间[{currentRoom.RoomName}]的借药记录");
                                        break;
                                    }
                                    //生成返回信息
                                    ResponseLendDrugProtocol response = new ResponseLendDrugProtocol();
                                    response.EleMedKitCode = requestLendProtocol.EleMedKitCode;
                                    response.ListLendResult = new List<SimpleDrugLotProtocol>();
                                    foreach (SPILItemTransaction t in transactions)
                                    {
                                        response.ListLendResult.Add(new SimpleDrugLotProtocol
                                        {
                                            DrugKey = t.ItemTransaction.ItemKey.ToString(),
                                            DrugLotCode = t.ItemLotInfo.LotNo,
                                            Barcode = t.Ext06
                                        });
                                    }
                                    responseData = response;
                                    //更新借药成功的状态
                                    ItemTransactionBLL itemTransactionBLL = new ItemTransactionBLL();
                                    ItemTransaction itemTransaction = transactions.First().ItemTransaction;
                                    itemTransaction.Ext10 = "1";
                                    itemTransactionBLL.Update(itemTransaction);
                                    //ResponseLendDrugProtocol response = new ResponseLendDrugProtocol();
                                    //response.EleMedKitCode = requestLendProtocol.EleMedKitCode;
                                    //response.ListLendResult = new List<SimpleDrugLotProtocol>();
                                    //response.ListLendResult.Add(new SimpleDrugLotProtocol()
                                    //{
                                    //    Barcode = "E00000000000000000000011",
                                    //    DrugKey = "81992454-f7a9-4385-aae5-78a3ce7af412",
                                    //    DrugLotCode = "20230807",
                                    //});
                                    //response.ListLendResult.Add(new SimpleDrugLotProtocol()
                                    //{
                                    //    Barcode = "E00000000000000000000002",
                                    //    DrugKey = "39383086-f0aa-4ed0-bbe8-e1bf7fba719f",
                                    //    DrugLotCode = "20230817",
                                    //});
                                    //responseData = response;
                                }
                            }
                            catch (Exception ex)
                            {
                                Log("借药出错：" + ex.Message, -1);
                            }
                            break;
                        case EleMedKitCommand.RequestStartPatientOperation:
                            try
                            {
                                Log("开启手术");
                                RequestStartPatientOperationProtocol requestLendProtocol = (RequestStartPatientOperationProtocol)curPocket.Data.ProtocolDataInfo;
                                StorageSpacePortableLink? requestStorageLink = null;
                                String? state = null;
                                using (ConnectionSessionScope conn = new ConnectionSessionScope())
                                {
                                    requestStorageLink = GetRequestStorageLink(null, requestLendProtocol.EleMedKitCode, out state);
                                    if (state != null
                                        || requestStorageLink == null)
                                    {
                                        Log("检查药箱信息不通过", -1);
                                        break;
                                    }
                                    #region 检查手术ID
                                    Guid operationKey;
                                    if (!Guid.TryParse(requestLendProtocol.PatientOperationID, out operationKey))
                                    {
                                        Log("手术排班ID无效：" + requestLendProtocol.PatientOperationID, -1);
                                        break;
                                    }
                                    PatientOperationInfoBLL patientOperationInfoBLL = new PatientOperationInfoBLL();
                                    PatientOperationInfo requestOperation = patientOperationInfoBLL.Get(new PatientOperationInfo
                                    {
                                        Key = operationKey
                                    });
                                    if (requestOperation == null)
                                    {
                                        Log("未找到请求的手术排班：" + requestLendProtocol.PatientOperationID, -1);
                                        break;
                                    }
                                    #endregion
                                    requestOperation.ClientTime = DateTime.Now;
                                    patientOperationInfoBLL.Update(requestOperation);
                                }
                            }
                            catch (Exception ex)
                            {
                                Log("开启手术出错：" + ex.Message, -1);
                            }
                            break;
                    }
                    if (responseData != null)
                    {
                        Log("服务器反馈：" + responseData.ToString());
                        Byte[] responseBytes = _encoding.GetBytes(responseData.ToString());
                        try
                        {
                            _tcpService.SendAsync(curPocket.ClientId, responseBytes, 0, responseBytes.Length);
                            curPocket.IsHandled = true;
                            DebugHelper.Log("已处理消息");
                            RemovePocket(curPocket);
                        }
                        catch (Exception ex)
                        {
                            Log("服务器反馈出错：" + ex.Message, -1);
                        }
                    }
                    else
                    {
                        DebugHelper.Log("未处理的消息");
                        RemovePocket(curPocket);
                    }
                    Thread.Sleep(1);
                }
                else
                {
                    Thread.Sleep(1000);
                }
            }
        }
        private Pocket? PeekData()
        {
            lock (Pockets)
            {
                return Pockets.FirstOrDefault();
            }
        }
        private void RemovePocket(Pocket pocket)
        {
            lock (Pockets)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    try
                    {
                        Pockets.Remove(pocket);
                        DebugHelper.Log("删除消息");
                    }
                    catch (Exception ex)
                    {
                        DebugHelper.Log("删除消息失败：" + ex.Message);
                    }
                });
            }
        }
        private void Log(String content, Int32 logLevel = 0)
        {
            if (Thread.CurrentThread.ManagedThreadId != Application.Current.Dispatcher.Thread.ManagedThreadId)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    Log(content, logLevel);
                });
            }
            else
            {
                Serilog.Log.Debug(content, logLevel);
                this.ListLogs.Add(new LogModel()
                {
                    Content = content,
                    LogLevel = logLevel
                });
                if (this.ListLogs.Count > 100)
                {
                    this.ListLogs.RemoveAt(0);
                }
            }
        }
        #region 业务处理
        private String GetAge(DateTime birth)
        {
            Int32 year = DateTime.Now.Year - birth.Year,
                month = DateTime.Now.Month - birth.Month,
                day = DateTime.Now.Day - birth.Day;
            if (year > 0)
            {
                if (month >= 0)
                {
                    if (day >= 0)
                    {
                        return year.ToString() + "岁";
                    }
                }
                if (year - 1 > 0)
                {
                    return (year - 1).ToString() + "岁";
                }
                month += 12;
            }
            if (month > 0)
            {
                return month.ToString() + "月";
            }
            return day.ToString() + "天";
        }
        private String GetGender(Boolean flag)
        {
            return flag ? "女" : "男";
        }
        private String SubString(String source, Int32 maxLength) 
        {
            return source == null
                ? String.Empty
                : source.Length > maxLength
                ? source.Substring(0, maxLength) + ".."
                : source;
        }
        //获取指定药箱的类型代码
        private String GetPortableTypeCode(StorageSpacePortableLink link) 
        {
            if (_listStorageTypes != null) 
            {
                PortableStorageType? storageType = _listStorageTypes.FirstOrDefault(x => x.TypeName == link.Ext02);
                if (storageType != null) 
                {
                    return storageType.TypeCode;
                }
            }
            return "X";
        }
        //根据请求的用户信息，获取用户数据
        private UserInfo? GetRequestUserInfo(UserInfoBLL userInfoBLL, UserInfoProtocol? requestUserData, out String? state)
        {
            if (requestUserData == null)
            {
                state = "传入的用户信息无效";
                return null;
            }
            //避免药箱bug，当传入的usercode为空时，使用默认的管理员账号
            if (String.IsNullOrEmpty(requestUserData.UserCode)) 
            {
                requestUserData.UserCode = "admin";
            }
            UserInfo? rlt = userInfoBLL.GetByUserId(requestUserData.UserCode);
            if (rlt == null)
            {
                state = "未找到用户信息：" + requestUserData.UserCode;
                return null;
            }
            state = null;
            return rlt;
        }
        private StorageSpacePortableLink? GetRequestStorageLink(StorageSpacePortableLinkBLL? storageSpacePortableLinkBLL, String? medKitCode, out String? state)
        {
            Int32 codeNumber;
            if (!Int32.TryParse(medKitCode, out codeNumber))
            {
                state = "请求的药箱号为空";
                return null;
            }
            if (storageSpacePortableLinkBLL == null)
            {
                storageSpacePortableLinkBLL = new StorageSpacePortableLinkBLL();
            }
            StorageSpacePortableLink? rlt = storageSpacePortableLinkBLL.GetByStorageCode(null, codeNumber.ToString());
            if (rlt == null)
            {
                state = "未找到设备信息";
                return null;
            }
            state = null;
            return rlt;
        }
        private PortableStorageItem? GetRequestPortableItem(PortableStorageItemBLL? portableStorageItemBLL, StorageSpacePortableLink storageLink, Guid itemKey)
        {
            if (portableStorageItemBLL == null)
            {
                portableStorageItemBLL = new PortableStorageItemBLL();
            }
            PortableStorageItem? rlt = portableStorageItemBLL.GetByStorageAndItem(storageLink.PortableStorageKey.GetValueOrDefault(), itemKey);
            return rlt;
        }
        #endregion 
        #endregion
    }
}
