@page "/selfDetail/{order}"
@using MasaBlazorApp3.Pojo.Config
@using MasaBlazorApp3.Pojo.Vo
@using MasaBlazorApp3.Util
@using Microsoft.Extensions.Options
@using Newtonsoft.Json
@using log4net

<RadzenStack Gap="1rem" Orientation="Orientation.Vertical" Style="height: 100%;">
    <RadzenStack>
        <RadzenStack class="rz-p-4 rz-border-radius-1" Style="border: var(--rz-grid-cell-border)" Orientation="Orientation.Horizontal" Gap="1rem">
            <RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">处方号:</RadzenText>
            <RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.OrderNo)</b></RadzenText>
            <RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">患者姓名:</RadzenText>
            <RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.PatientName)</b></RadzenText>
            <RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">性别:</RadzenText>
            <RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.Sex)</b></RadzenText>
            <RadzenText TextStyle="TextStyle.Overline" Class="rz-mt-2 rz-my-0" Style="color: var(--rz-text-tertiary-color);">年龄:</RadzenText>
            <RadzenText TextStyle="TextStyle.Body1" Class="rz-text-truncate"><b>@(order?.Age)</b></RadzenText>

        </RadzenStack>
        @if (CanTakeDrug)
        {
            <RadzenDataGrid Data="@data" AllowAlternatingRows="false">
                <Columns>
                    <RadzenDataGridColumn Property="ChannelStock" Title="库位">
                        <Template>
                            @context.ChannelStock.DrawerNo - @context.ChannelStock.ColNo
                        </Template>
                    </RadzenDataGridColumn>
                    <RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
                    <RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
                    <RadzenDataGridColumn Property="ChannelStock.ManuNo" Title="批次" />
                    <RadzenDataGridColumn Property="ChannelStock.EffDate" Title="效期" />
                    <RadzenDataGridColumn Property="Quantity" Title="数量" />
                </Columns>
            </RadzenDataGrid>
        }
        else
        {
            <RadzenDataGrid Data="@data" AllowAlternatingRows="false">
                <Columns>
                    <RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
                    <RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
                    <RadzenDataGridColumn Property="Quantity" Title="取药数量" />
                    <RadzenDataGridColumn Property="StockQuantity" Title="库存" />
                </Columns>
            </RadzenDataGrid>
        }



    </RadzenStack>
    <RadzenStack Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.Center" Gap="0.5rem">
        @if (status < 2)
        {
            <RadzenButton Click="@OpenDrawer" Disabled="!CanTakeDrug" IsBusy="status > 0" BusyText="取药中。。。" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Text="取药" Style="width: 120px" />
        }
        @if (status == 2)
        {
            <RadzenButton Click="@TakeFinish" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" Text="完成" Style="width: 120px" />
        }
        @if (status <= 2)
        {
            <RadzenButton Click="@((args) => CancelOpera())" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
        }
    </RadzenStack>
</RadzenStack>
@code {
    @inject Radzen.DialogService dialogService;
    @inject NotificationService _message
    @inject PortUtil PortUtil;
    @inject ISelfTakeDao selfTakeDao;
    @inject IOptions<DrawerConfig> setting;
    private readonly ILog logger = LogManager.GetLogger(typeof(OrderDetailDialog));

    int status;

    [Parameter] public OrderInfo order { get; set; }
    [Parameter] public List<OrderDetail> orderDetails { get; set; }


    private bool CanTakeDrug = true;
    //开抽屉前操作标识
    List<string> DrawerNoColNoList = new List<string>();
    public List<OrderTakeVo> data { get; set; }
    //称重取药数量
    int[] WeightFinnalQuantity { get; set; } = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    protected override async Task OnInitializedAsync()
    {
        data = await selfTakeDao.getTakeInfoByOrderNo(orderDetails);
        // 如果有【stockQuantity】字段说明有药品库存不足
        if (data.Any(it => it.ChannelStock == null))
        {
            CanTakeDrug = false;
        }
        base.OnInitializedAsync();
    }

    async Task OpenDrawer()
    {
        this.status = 1;
        // 解析需要打开的抽屉列表
        List<OrderTakeVo> drawerNos = this.data.GroupBy(it => it.ChannelStock.DrawerNo).Select(it => it.First()).ToList();

        // 根据抽屉类型来决定打开前是否需要查询数量
        var promiseUtil = new PromiseUtil<int>();

        await promiseUtil.taskAsyncLoop(500, 0, async (options, next, stop) =>
        {
            var orderTakeVo = drawerNos[options._data];
            var drawerNo = orderTakeVo.ChannelStock.DrawerNo;
            try
            {
                if (this.status == 0)
                {
                    stop();
                }
                // 开启抽屉
                else if (this.status == 1)
                {
                    if (orderTakeVo.Status == 0)
                    {
                        // 判断是否为单支抽屉
                        if (setting.Value.single.Contains(drawerNo))
                        {
                            byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
                            orderTakeVo.BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
                            logger.Info($"单支抽屉，开抽屉前检测数量【{string.Join(",", orderTakeVo.BeforeQuantity)}】");

                            await PortUtil.HasLightOnByCol(drawerNo, data.Where(ot => ot.ChannelStock.DrawerNo == drawerNo).Select(ot => ot.ChannelStock.ColNo).ToArray());
                        }
                        for (int i = 0; i < data.Count; i++)
                        {
                            if (!DrawerNoColNoList.Contains(data[i].ChannelStock.DrawerNo.ToString() + data[i].ChannelStock.ColNo))
                            {
                                if (data[i].ChannelStock.BoardType.ToString().Contains("6"))
                                {
                                    PortUtil.DrawerNo = data[i].ChannelStock.DrawerNo;
                                    PortUtil.ColNoLst.Add(data[i].ChannelStock.ColNo);

                                    data[i].BeforeQuantity[data[i].ChannelStock.ColNo - 1] = await PortUtil.CheckQuantityForSingle(data[i].ChannelStock.ColNo);
                                    logger.Info($"称重抽屉，开抽屉前检测数量【{string.Join(",", data[i].BeforeQuantity)}】");
                                    await Task.Delay(200);
                                }

                                //是药盒抽屉开药盒
                                if (data[i].ChannelStock.BoardType.ToString().Contains("3"))
                                {
                                    PortUtil.DrawerNo = drawerNo;
                                    await PortUtil.OpenBoxByColNo(data[i].ChannelStock.ColNo);
                                    await Task.Delay(200);
                                }
                                DrawerNoColNoList.Add(data[i].ChannelStock.DrawerNo.ToString() + data[i].ChannelStock.ColNo);
                            }
                        }
                        var b = await PortUtil.OpenDrawerStatus(drawerNo);
                        if (b)
                        {
                            PortUtil.Operate = true;
                            PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
                            PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开，请，取药");
                            orderTakeVo.Status = 1;
                            next();
                        }
                        else
                        {
                            _message.Notify(
                            new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败，请检测硬件", Duration = 4000 }
                        );
                            logger.Info($"抽屉打开失败");
                            if (setting.Value.single.Contains(drawerNo))
                            {
                                PortUtil.PowerOff(drawerNo);
                            }
                            RestData();
                            stop();
                        }
                    }
                    // 检测状态
                    else if (orderTakeVo.Status == 1)
                    {
                        // 查询抽屉是否为关闭状态
                        var b = await PortUtil.CheckDrawerStatus2(drawerNo);
                        // 关闭则改变状态并终止循环
                        if (b)
                        {

                            data.ForEach(cl =>
                            {
                                if (cl.ChannelStock.DrawerNo == drawerNo)
                                {
                                    cl.GetQuantity = cl.Quantity;

                                }
                            });
                            PortUtil.Operate = false;
                            orderTakeVo.Status = 2;
                            if (options._data == drawerNos.Count - 1)
                            {
                                PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
                                PortUtil.SpeakAsync($"取药完成，请，点击完成按钮进行确认");
                                this.status = 2;
                                string alertMessage = string.Empty;
                                //检查是否称重抽屉，核对实际取出数量是否与应取数量一致，不一致则弹出提示
                                for (int i = 0; i < data.Count; i++)
                                {
                                    if (data[i].ChannelStock.BoardType.ToString().Contains("6"))
                                    {
                                        PortUtil.DrawerNo = drawerNo;
                                        PortUtil.ColNoLst.Add(data[i].ChannelStock.ColNo);

                                        orderTakeVo.AfterQuantity[data[i].ChannelStock.ColNo - 1] = await PortUtil.CheckQuantityForSingle(data[i].ChannelStock.ColNo);
                                        logger.Info($"称重抽屉，关抽屉后检测数量【{string.Join(",", orderTakeVo.AfterQuantity)}】");
                                        WeightFinnalQuantity[data[i].ChannelStock.ColNo - 1] = orderTakeVo.BeforeQuantity[data[i].ChannelStock.ColNo - 1] - orderTakeVo.AfterQuantity[data[i].ChannelStock.ColNo - 1];
                                        if (data[i].Quantity != WeightFinnalQuantity[data[i].ChannelStock.ColNo - 1])
                                        {
                                            //称重自动计数数量与实际要取数量不一致弹出提示，确认后保存数据
                                            alertMessage += $"{data[i].Drug.DrugName}应取数量【{data[i].Quantity}】，实际取出数量【{WeightFinnalQuantity[data[i].ChannelStock.ColNo - 1]}】";

                                        }
                                        await Task.Delay(200);
                                    }

                                    if (data[i].ChannelStock.BoardType.ToString().Contains("2"))
                                    {
                                        byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
                                        orderTakeVo.AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
                                        logger.Info($"单支抽屉，关抽屉后检测数量【{string.Join(",", orderTakeVo.AfterQuantity)}】");
                                        WeightFinnalQuantity[data[i].ChannelStock.ColNo - 1] = data[i].BeforeQuantity[data[i].ChannelStock.ColNo - 1] - orderTakeVo.AfterQuantity[data[i].ChannelStock.ColNo - 1];
                                        if (data[i].Quantity != WeightFinnalQuantity[data[i].ChannelStock.ColNo - 1])
                                        {
                                            alertMessage += $"{data[i].Drug.DrugName}应取数量【{orderTakeVo.Quantity}】,实际取出数量【{WeightFinnalQuantity[data[i].ChannelStock.ColNo - 1]}】";
                                        }
                                    }
                                }
                                if (!string.IsNullOrEmpty(alertMessage))
                                {
                                    //弹出确认对话框
                                    alertMessage += "应取数与实际取出数不一致确认要保存吗？";
                                    //弹出确认提示框
                                    var confirm = await dialogService.OpenAsync<ConfirmDialog>(
                                          $"保存确认",
                                          new Dictionary<string, object>() { { "confirmInfo", alertMessage } },
                                          new DialogOptions() { Width = "45vw", Resizable = true, Draggable = true, ShowClose = false });
                                    logger.Info(alertMessage);
                                    if (!confirm)
                                    {
                                        RestData();
                                        logger.Info("取消保存");
                                        // 关闭弹窗
                                        dialogService.Close(false);
                                    }
                                }
                                if (setting.Value.single.Contains(drawerNo))
                                {
                                    PortUtil.PowerOff(drawerNo);
                                }
                                stop();
                            }
                            else
                            {
                                options._data += 1;
                                next();
                            }
                        }
                        else
                        {
                            // if (setting.Value.single.Contains(drawerNo))
                            // {
                            //     byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
                            //     orderTakeVo.AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
                            //     logger.Info($"单支抽屉，抽屉未关检测数量【{string.Join(",", orderTakeVo.AfterQuantity)}】");

                            //     data.ForEach(cl =>
                            //     {
                            //         if (cl.ChannelStock.DrawerNo == drawerNo)
                            //         {
                            //             logger.Info($"单支抽屉【{drawerNo}】，应取药品数量【{orderTakeVo.Quantity}】,现实取数量【{orderTakeVo.BeforeQuantity[cl.ChannelStock.ColNo - 1] - orderTakeVo.AfterQuantity[cl.ChannelStock.ColNo - 1]}】");
                            //         }

                            //     });
                            // }
                            next(); // continue iteration
                        }
                    }


                }
            }
            catch (Exception e)
            {
                RestData();
                logger.Info($"处方取药发生错误，{e.Message}");
                _message.Notify(
                    new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"发生错误，{e.Message}", Duration = 4000 }
                );
                if (setting.Value.single.Contains(drawerNo))
                {
                    PortUtil.PowerOff();
                }
                stop();
            }
        });
    }
    async Task CancelOpera()
    {
        RestData();
        dialogService.Close(false);
    }
    void RestData()
    {
        PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
        this.status = 0;
    }

    async Task TakeFinish()
    {

        // 保存账册、操作记录
        var b = await selfTakeDao.OrderTakeFinish(data, order);
        if (!b)
        {
            _message.Notify(new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"数据保存失败", Duration = 4000 });
            logger.Error($"自选取药保存数据库失败，数据{JsonConvert.SerializeObject(data)}");
            // 关闭弹窗
            dialogService.Close(false);
        }
        else
        {
            // 关闭弹窗
            dialogService.Close(true);

        }
        //重置状态
        this.RestData();
    }

}
