using AutoMapper;
using Kean.Application.Command.Interfaces;
using Kean.Domain;
using Kean.Domain.Task.Commands;
using Kean.Domain.Wcs.Commands;
using Microsoft.Extensions.Logging;
using Orleans;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Kean.Application.Command.Implements
{
    /// <summary>
    /// 控制交互命令服务实现
    /// </summary>
    public class WcsService : IWcsService
    {
        private readonly ILogger<WcsService> _logger; // 日志
        private readonly ICommandBus _bus; // 命令总线
        private readonly INotification _notifications; // 总线通知
        private readonly IMapper _mapper; // 模型映射
        private readonly IClusterClient _cluster; // 筒仓客户端

        /// <summary>
        /// 依赖注入
        /// </summary>
        public WcsService(
            ILogger<WcsService> logger,
            ICommandBus bus,
            INotification notifications,
            IMapper mapper,
            IClusterClient cluster)
        {
            _logger = logger;
            _bus = bus;
            _notifications = notifications;
            _mapper = mapper;
            _cluster = cluster;
        }

        /*
         * 实现 Kean.Application.Command.Interfaces.IWcsService.AccessInputs 方法
         */
        public async Task AccessInputs()
        {
            // 扫描
            var command = new ScanInputsCommand();
            await _bus.Execute(command);
            if (command.Inputs.Any())
            {
                var stopwatch = new Stopwatch();
                var grain = _cluster.GetGrain<IAggregateGrain>(Guid.Empty);
                foreach (var item in command.Inputs)
                {
                    // 接受
                    if (string.IsNullOrEmpty(item.Remark) || item.Remark == "0")
                    {
                    }
                    else
                    {
                        item.Parameters = $"errorMessage:{item.Remark}";
                    }

                    var accept = _mapper.Map<AcceptInputCommand>(item);

                    var hash = accept.GetHashCode();
                    _logger.LogInformation("过程[{Hash}]开始:WCS申请:ID[{Id}],类型[{Function}],设备[{Device}],条码[{Barcode}],参数[{Parameters}]", hash, item.Id, item.Function, item.Device, item.Barcode, item.Parameters);
                    stopwatch.Start();
                    //await _bus.Execute(accept);
                    //var errorMessage = _notifications.FirstOrDefault()?.ErrorMessage;
                    //_notifications.Clear();

                    try
                    {
                        var result = await grain.AcceptInput(accept);
                        var fallback = result.Fallback;
                        var errorMessage = result.Failure?.ErrorMessage;
                        //

                        var log = _mapper.Map<LogInputCommand>(item);
                        if (errorMessage == null)
                        {
                            if (result.Fallback != null)
                            {
                                log.Para02 = (result.Fallback).Para02;
                            }

                            // 成功记录
                            await _bus.Execute(log);
                            _notifications.Clear();
                        }
                        else
                        {
                            _logger.LogWarning("过程[{Hash}]中断:{Failure}", hash, result.Failure);
                            // 失败记录
                            log.ErrorMessage = errorMessage;
                            await _bus.Execute(log);
                            _notifications.Clear();

                            // 降级
                            //while (accept.Fallback != null)
                            //{
                            //    _logger.LogInformation("过程[{Hash}]中断:降级:{Function}", hash, accept.Fallback.Function);
                            //    await _bus.Execute(accept = accept.Fallback);
                            //    _notifications.Clear();
                            //}
                            while (fallback != null)
                            {
                                _logger.LogInformation("过程[{Hash}]中断:降级:{Function}", hash, fallback.Function);
                                result = await grain.AcceptInput(fallback);
                                fallback = result.Fallback;
                            }
                            //
                        }
                        _logger.LogInformation("过程[{Hash}]结束:耗时{TimeSpan}ms。", hash, stopwatch.ElapsedMilliseconds);
                        stopwatch.Reset();
                    }
                    catch (Exception ex) 
                    {
                        _logger.LogDebug("过程[{Hash}]异常:原因:{0}", hash, ex.Message);
                    }
                    
                }
            }
        }

        /*
         * 实现 Kean.Application.Command.Interfaces.IWcsService.AccessOutputs 方法
         */
        public async Task AccessOutputs()
        {
            // 扫描
            var command = new ScanOutputsCommand();
            await _bus.Execute(command);
            if (command.UnsyncedOutputs.Any())
            {
                var stopwatch = new Stopwatch();
                var grain = _cluster.GetGrain<IAggregateGrain>(Guid.Empty);
                foreach (var item in command.UnsyncedOutputs)
                {
                    // 同步
                    var sync = _mapper.Map<SyncOutputCommand>(item);
                    var hash = sync.GetHashCode();
                    _logger.LogInformation("过程[{Hash}]开始:WCS同步:ID[{Id}],条码[{Barcode}],状态[{PreState}->{State}],, Manage任务[{Task}]", hash, item.Id, item.Barcode, item.PreState, item.State, item.Task);
                    stopwatch.Start();
                    //await _bus.Execute(sync);
                    //var result = _notifications.FirstOrDefault();
                    //_notifications.Clear();
                    try
                    {
                        var result = await grain.SyncOutput(sync);
                        if (result != null)
                        {
                            _logger.LogWarning("过程[{Hash}]中断:{Failure}。", hash, result);
                            if (result.PropertyName == "TaskState" && (result.AttemptedValue == "AgvFail" || result.AttemptedValue == "WmsResultFail"))
                            {
                                SetTaskStateCommand errorCommand = new SetTaskStateCommand();
                                errorCommand.Id = item.Task;
                                errorCommand.State = result.AttemptedValue.ToString();
                                errorCommand.Message = result.ErrorMessage;
                                errorCommand.Type = "TaskWcs";

                                await grain.SetTaskState(errorCommand);
                            }
                            else
                            {
                                SetTaskStateCommand errorCommand = new SetTaskStateCommand();
                                errorCommand.Id = item.Task;
                                errorCommand.State = "Fail";
                                errorCommand.Message = result.ErrorMessage;
                                errorCommand.Type = "TaskWcs";

                                await grain.SetTaskState(errorCommand);
                            }
                        }
                        _logger.LogInformation("过程[{Hash}]结束:耗时{TimeSpan}ms。", hash, stopwatch.ElapsedMilliseconds);
                        stopwatch.Reset();
                    }
                    catch (Exception e) 
                    {
                        _logger.LogDebug("过程[{Hash}]异常:原因:{0}", hash, e.Message);
                    }
                   
                }
            }
        }

        /*
         * 实现 Kean.Application.Command.Interfaces.IWcsService.AccessInputs 方法
         */
        public async Task AccessStation()
        {
            // 扫描
            var command = new ScanStationCommand();
            await _bus.Execute(command);
            if (command.UnsyncedStationModels.Any())
            {
                var stopwatch = new Stopwatch();
                var grain = _cluster.GetGrain<IAggregateGrain>(Guid.Empty);
                foreach (var item in command.UnsyncedStationModels)
                {
                    // 同步并清除LED信息
                    var sync = _mapper.Map<SyncStationCommand>(item);
                    var hash = sync.GetHashCode();
                    _logger.LogInformation($"过程[{hash}]开始:WCS Station同步:站台[{item.Device}],IsFull[{item.Isfull}]");
                    stopwatch.Start();
                    //await _bus.Execute(sync);
                    //var result = _notifications.FirstOrDefault();
                    //_notifications.Clear();
                    var result = await grain.SyncStation(sync);
                    if (result != null)
                    {
                        _logger.LogWarning("过程[{Hash}]中断:{Failure}。", hash, result);
                    }
                    _logger.LogInformation("过程[{Hash}]结束:耗时{TimeSpan}ms。", hash, stopwatch.ElapsedMilliseconds);
                    stopwatch.Reset();
                }
            }
        }
    }
}