@page "/orderDetailReturn/{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>
        <RadzenDataGrid @ref="grid" Data="@data" ExpandMode="DataGridExpandMode.Multiple"
                        RowRender="@RowRender"
                        EmptyText="无数据" AllowAlternatingRows="false">

            <Template Context="di">
                <RadzenDataGrid Data="@di.ChannelStocks" EmptyText="无数据" @ref="di.Grid"
                                CellClick="@((DataGridCellMouseEventArgs<ChannelStock> args) => OnCellClick(args, di.Grid))">
                    <Columns>
                        <RadzenDataGridColumn Title="库位" Property="DrawerNo">
                            <Template Context="s">
                                @s.DrawerNo - @s.ColNo
                            </Template>
                        </RadzenDataGridColumn>
                        <RadzenDataGridColumn Title="库存" Property="Quantity"></RadzenDataGridColumn>
                        <RadzenDataGridColumn Title="入库数量" Property="AddQuantity">
                            <EditTemplate Context="cs">
                                <RadzenNumeric Disabled="status > 0" Style="display: block" Min="0" Max="@di.Quantity" Name="Quantity" @bind-Value=@cs.ReturnQuantity />
                                <RadzenNumericRangeValidator Style="position: absolute;z-index: 9999;" Min="0" Max="@di.Quantity" Text="请填写正确的添加数量" Component="Quantity" />
                                <RadzenCustomValidator Validator="@(() => di.ChannelStocks.Sum(cs2 => cs2.ReturnQuantity) == di.Quantity)" Component="Quantity" Text="添加总量应等于退药量" Style="position: absolute;z-index: 9999;" />
                            </EditTemplate>
                        </RadzenDataGridColumn>
                    </Columns>
                </RadzenDataGrid>
            </Template>
            <Columns>
                <RadzenDataGridColumn Property="Drug.DrugName" Title="药品" />
                <RadzenDataGridColumn Property="Drug.DrugSpec" Title="规格" />
                <RadzenDataGridColumn Property="data.ManuNo" Title="批次" />
                <RadzenDataGridColumn Property="data.EffDate" 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="!CanReturnDrug" 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="@Cancel" Variant="Variant.Flat" Text="取消" Style="width: 120px" />
        }
    </RadzenStack>
</RadzenStack>

@code {
    @inject Radzen.DialogService dialogService;
    @inject IOrderInfoDao orderInfoDao;
    @inject IChannelListDao channelListDao;
    @inject IOptions<DrawerConfig> setting;
    @inject NotificationService _message
    @inject PortUtil PortUtil;
    private readonly ILog logger = LogManager.GetLogger(typeof(OrderDetailDialog));
    RadzenDataGrid<OperationVo<MachineRecord>> grid;

    int status;

    [Parameter] public OrderInfo order { get; set; }
    private bool CanReturnDrug = true;

    public List<OperationVo<MachineRecord>> data { get; set; }



    protected override async Task OnInitializedAsync()
    {
        data = await orderInfoDao.getReturnInfoByOrderNo(order.OrderNo);
        // 如果有【stockQuantity】字段说明有药品库存不足
        if (data.Any(it => it.ChannelStocks == null))
        {
            CanReturnDrug = false;
        }
        base.OnInitializedAsync();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        base.OnAfterRender(firstRender);

        if (firstRender)
        {
            await Task.Delay(15);
            await grid.ExpandRows(grid.PagedView.Where(it => it.ChannelStocks.Count > 0));
        }
    }

    async Task OpenDrawer()
    {
        this.status = 1;
        // 解析需要打开的抽屉列表
        List<ChannelStock> channels = new();
        for (int i = 0; i < data.Count; i++)
        {
            channels = channels.Concat(data[i].ChannelStocks.Where(cs => cs.AddQuantity > 0)).ToList();
        }

        List<int> drawerNos = channels.GroupBy(it => it.DrawerNo).Select(it => it.Key).ToList();

        // 根据抽屉类型来决定打开前是否需要查询数量
        int index = 0;
        var BeforeQuantity = new int[9];
        var AfterQuantity = new int[9];
        await new PromiseUtil<int>().taskAsyncLoop(500, 0, async (options, next, stop) =>
    {
        var drawerNo = drawerNos[index];
        try
        {
            if (this.status == 0)
            {
                stop();
            }
            // 开启抽屉
            else if (this.status == 1)
            {
                if (options._data == 0)
                {
                    BeforeQuantity = new int[9];
                    AfterQuantity = new int[9];
                    // 判断是否为单支抽屉
                    if (setting.Value.single.Contains(drawerNo))
                    {
                        byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
                        BeforeQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
                        logger.Info($"单支抽屉【{drawerNo}】，开抽屉前检测数量【{string.Join(",", BeforeQuantity)}】");

                        await PortUtil.NoLightOnByCol(drawerNo, data.Select(ot => ot.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).Select(cs => cs.ColNo)).Cast<int>().ToArray());
                    }
                    var b = await PortUtil.OpenDrawerStatus(drawerNo);
                    if (b)
                    {
                        PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
                        PortUtil.SpeakAsync($"{drawerNo}号抽屉已经打开，请，放置退回药品");
                        options._data = 1;
                        next();
                    }
                    else
                    {
                        _message.Notify(
                        new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "提示", Detail = $"抽屉【{drawerNo}】打开失败，请检测硬件", Duration = 4000 }
                    );
                        logger.Info($"处方退药抽屉【{drawerNo}】打开失败");
                        PortUtil.PowerOff();
                        RestData();
                        stop();
                    }
                }
                // 检测状态
                else if (options._data == 1)
                {
                    // 查询抽屉是否为关闭状态
                    var b = await PortUtil.CheckDrawerStatus2(drawerNo);
                    // 关闭则改变状态并终止循环
                    if (b)
                    {
                        options._data = 0;
                        if (setting.Value.single.Contains(drawerNo))
                        {
                            PortUtil.PowerOff();
                        }
                        if (index == drawerNos.Count - 1)
                        {
                            PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
                            PortUtil.SpeakAsync($"退药完成，请，点击完成按钮进行确认");
                            this.status = 2;
                            stop();
                        }
                        else
                        {
                            index += 1;
                            next();
                        }
                    }
                    else
                    {
                        if (setting.Value.single.Contains(drawerNo))
                        {
                            byte[] quantity = await PortUtil.CheckQuantityByDrawer(drawerNo);
                            AfterQuantity = quantity.Select(it => Convert.ToInt32(it)).ToArray().Skip(3).Take(9).ToArray();
                            logger.Info($"单支抽屉【{drawerNo}】，抽屉未关检测数量【{string.Join(",", AfterQuantity)}】");

                            data.ForEach(cl =>
                        {
                            cl.ChannelStocks.Where(cs => cs.DrawerNo == drawerNo).ToList().ForEach(cs =>
                            {
                                logger.Info($"单支抽屉【{drawerNo}】，应退药品数量【{cs.AddQuantity}】,现实退数量【{AfterQuantity[cs.ColNo - 1] - BeforeQuantity[cs.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();
        }
    });
    }

    void RestData()
    {
        PortUtil.PowerOff();
        PortUtil.speechSynthesizer.SpeakAsyncCancelAll();
        this.status = 0;
    }
    void Cancel()
    {
        RestData();
        // 关闭弹窗
        dialogService.Close(false);
    }
    async Task TakeFinish()
    {
        
        // 保存账册、操作记录
        var b = await orderInfoDao.OrderReturnFinish(data, order.OrderNo);
        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();
    }

    void RowRender(RowRenderEventArgs<OperationVo<MachineRecord>> args)
    {
        args.Expandable = args.Data.ChannelStocks != null && args.Data.ChannelStocks.Count > 0;
    }


    void OnCellClick(DataGridCellMouseEventArgs<ChannelStock> args, RadzenDataGrid<ChannelStock> Grid)
    {
        Grid.EditRow(args.Data);
    }



}
