using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QMFrameWork.Data;
using QMAPP.FJC.DAL.QT;
using QMAPP.FJC.Entity.QT;
using QMAPP.FJC.TRACING.DAInterface;
using QMAPP.FJC.DAL.Produce;
using QMAPP.FJC.DAL.Basic;
using QMAPP.FJC.Entity.Operation;
using QMAPP.FJC.DAL.Operation;
using QMAPP.FJC.Entity.Basic;
using QMAPP.MD.Entity;
using QMAPP.MD.DAL;
using QMAPP.MD.Entity.View;
using QMAPP.FJC.Entity.ProductionPlan;
using QMAPP.FJC.Entity;
using QMAPP.FJC.Entity.Injection;
using QMAPP.FJC.DAL.Injection;

namespace QMAPP.FJC.TRACING.StateActions
{
    /// <summary>
    /// 提交数据关联派工单
    /// </summary>
    public class SetWorkingOrder : IStateAction
    {
        /// <summary>
        /// 执行
        /// </summary>
        /// <param name="data"></param>
        public void Execute(DAObject data)
        {
            //如果当前工序未确定生产产品物料号
            if (string.IsNullOrWhiteSpace(data.WorkLocState.CurrentState.MATERIAL_CODE))
            {
                //搜索确认产品物料号
                //SearchMaterial(data);
            }
            SetOrder(data, false);
        }
        /// <summary>
        /// 更新派工单
        /// </summary>
        /// <param name="product"></param>
        /// <param name="data"></param>
        /// <param name="workcellend"></param>
        private void SetOrder(DAObject data,bool workcellend)
        {
            var workorder = LocateWorkOrder(data, data.WorkLocState.CurrentState.MATERIAL_CODE);
            data.WorkOrderID = workorder.PID;
            data.WorkLocState.CurrentState.BOM_CODE = workorder.PBOM_CODE;
            if (string.IsNullOrWhiteSpace(workorder.REMARK))
            {
                //workorder.REMARK = product.PRODUCTCODE;
            }
            
            
            if (!workcellend)
            {
                workorder.WORKLOC_CODE = data.WorkLocState.WORKLOC_CODE;
                workorder.MOULD_CODE = data.MouldCode;
                workorder.STATE = 2;
            }
            
            
            data.AddToPersistentList(workorder, workorder.PID);
        }
        /// <summary>
        /// 定位派工单
        /// </summary>
        private WorkOrder LocateWorkOrder(DAObject data, string MATERIAL_CODE)
        {
            DAL.ProductionPlan.WorkOrderDAL workorderdal = new DAL.ProductionPlan.WorkOrderDAL();
            var order = workorderdal.GetWorkingOrderInLoc(data.WorkLocState.WORKLOC_CODE, data.MouldCode);
            if (order != null)
            {
                var lastorder = data.GetPersistentEntity<WorkOrder>(order.PID);
                if (lastorder != null && (lastorder.IsDelete || lastorder.WORKCELL_CODE != data.WorkLocState.WORKCELL_CODE || (order.STATE!=lastorder.STATE && lastorder.STATE==1)))
                {
                    order = null;
                }
            }

            if (order == null && data.OrderPlan != null)
            {
                order = data.OrderPlan;
            }
            if (order == null)
            {
                order = workorderdal.GetFirstMatchOrder(data.WorkLocState.WORKCELL_CODE, MATERIAL_CODE);
            }
            if (order == null)
            {
                throw new Exception("查找派工单失败!");
            }
            return order;
        }
        /// <summary>
        /// 搜索确定加工后的产品物料号及加工消耗的物料号
        /// </summary>
        /// <param name="data"></param>
        /// <returns>返回加工消耗物料</returns>
        private string[] SearchMaterial(DAObject data)
        {
            var materials = (from da in data.WorkLocState.DataCache
                             where !string.IsNullOrWhiteSpace(da.MATERIAL_CODE)
                             select da.MATERIAL_CODE).ToArray();

            BomLocation bomlocation = null;
            if (data.OrderPlan != null)
            {
                if (string.Equals(data.MaterialCode, data.OrderPlan.MATERIAL_CODE))
                {
                    bomlocation = new BomLocation
                    {
                        BOMCode = data.OrderPlan.PBOM_CODE,
                        ItemNo = 0,
                        SubCount = 1
                    };
                }
                else
                {
                    bomlocation = GetBomLocation(data.OrderPlan.PBOM_CODE, materials.Distinct().ToArray());
                    if (bomlocation == null)
                    {
                        throw new Exception("采集数据有误,无法确定生产BOM,请检查采集点配置和BOM配置!");
                    }
                }
            }
            else
            {
                bomlocation = GetBomLocation(materials.Distinct().ToArray());
                if (bomlocation == null) //未定位到
                {
                    materials = (from da in data.WorkLocState.DataCache
                                 where !string.IsNullOrWhiteSpace(da.MATERIAL_CODE)
                                       && !string.Equals(da.DA_MODE, "2") //过滤掉可省略的采集点
                                 select da.MATERIAL_CODE).ToArray();
                    bomlocation = GetBomLocation(materials.Distinct().ToArray());
                    if (bomlocation == null) //仍未定位到BOM信息 抛出异常
                    {
                        if (materials.Length == 1) //单一物料加工
                        {
                            data.WorkLocState.CurrentState.MATERIAL_CODE = materials[0];
                            var dai = data.WorkLocState.DataCache.FirstOrDefault(p => p.MATERIAL_CODE == materials[0]);
                            data.WorkLocState.CurrentState.PROCESS_CODE = dai.DA_VALUE;
                            data.WorkLocState.CurrentState.PRODUCT_PID = dai.OBJ_PID;
                            return materials.Distinct().ToArray();
                        }
                        else
                        {
                            throw new Exception("采集数据有误,无法确定生产BOM,请检查采集点配置和BOM配置!");
                        }
                    }
                }
            }

            PbomDAL pbidal = new PbomDAL();
            if (materials.Length == 1) //单一物料加工
            {
                var oneitem = pbidal.GetBomDetail(new MD.Entity.PbomItem { PBOM_CODE = bomlocation.BOMCode, MATERIAL_CODE = materials[0], GMP = data.WorkLocState.WORKCELL_CODE });
                if (oneitem == null)//并且当前工序不是此物料的发料工序
                {
                    data.WorkLocState.CurrentState.MATERIAL_CODE = materials[0];
                    var dai = data.WorkLocState.DataCache.FirstOrDefault(p => p.MATERIAL_CODE == materials[0]);
                    data.WorkLocState.CurrentState.PROCESS_CODE = dai.DA_VALUE;
                    data.WorkLocState.CurrentState.PRODUCT_PID = dai.OBJ_PID;
                    return materials.Distinct().ToArray();
                }
            }

            string upperlevelmaterial = "";
            if (bomlocation.ItemNo > 0) //如果Bom定位为明细项
            {
                var bomitem = pbidal.GetByLocate(bomlocation);
                if (bomitem != null)
                {
                    upperlevelmaterial = bomitem.MATERIAL_CODE;
                }
            }
            else //如果Bom定位为Bom头
            {
                var bom = pbidal.GetByCode(bomlocation.BOMCode);
                if (bom != null)
                {
                    upperlevelmaterial = bom.MATERIAL_CODE;
                }
            }
            data.WorkLocState.CurrentState.MATERIAL_CODE = upperlevelmaterial; //取得产品物料号

            return materials.Distinct().ToArray();
        }
        /// <summary>
        /// 根据物料组获取上层物料号
        /// </summary>
        /// <param name="materials"></param>
        /// <returns></returns>
        private BomLocation GetBomLocation(params string[] materials)
        {
            PbomDAL pbidal = new PbomDAL();
            var bomlocations = pbidal.LocateBom(materials);
            //确定物料组成数量一致
            var bomlocation = bomlocations.FirstOrDefault(p => p.SubCount == materials.Length);
            return bomlocation;
        }
        /// <summary>
        /// 在已知BOM的情况下根据物料组获取上层物料号
        /// </summary>
        /// <param name="bomcode"></param>
        /// <param name="materials"></param>
        /// <returns></returns>
        private BomLocation GetBomLocation(string bomcode, params string[] materials)
        {
            PbomDAL pbidal = new PbomDAL();
            var bomlocations = pbidal.LocateBom(materials);
            //确定BOM编号一致
            var bomlocation = bomlocations.FirstOrDefault(p => p.BOMCode == bomcode);
            return bomlocation;
        }
    }
}