using Kingdee.BOS;
using Kingdee.BOS.Core.Bill;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core.Metadata.EntityElement;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.JSON;
using Kingdee.BOS.Log;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceFacade.KDServiceFx;
using Kingdee.BOS.Util;
using Kingdee.BOS.WebApi.FormService;
using Kingdee.BOS.WebApi.ServicesStub;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LQKJ.WebApi.Stub
{
    public class Save : MapPropertyService
    {
        public bool cleanEntry { get; set; }
        public Context Context { get; set; }

        public IBillView BillView { get; set; }

        /**
         * 是否新增
         */
        public bool IsNew { get; set; }
        public override void Execute()
        {
            throw new NotImplementedException();
        }

        public void Map(JSONObject model, DynamicObject dynamicObject)
        {
            this.MapProperty(model, dynamicObject);
        }

        public Element GetElement(string elementName)
        {
            Element element = base.BillBusinessInfo.GetElement(elementName);
            if (7 == 0 || element != null)
            {
                return element;
            }
            int num = elementName.IndexOf("#");
            if (num > -1)
            {
                string key = elementName.Substring(num + 2);
                element = base.BillBusinessInfo.GetElement(key);
            }
            return element;
        }


        /// <summary>
        /// 映射属性
        /// </summary>
        /// <param name="billSynObj"></param>
        /// <param name="targetObj"></param>
        /// <param name="rowIndex"></param>
        /// <param name="NeedUpDateFields"></param>
        private void MapProperty(JSONObject model, DynamicObject targetObj, int rowIndex = 0)
        {
            //为空直接忽略
            if (model == null) return;
            if (targetObj == null) return;

            foreach (var curField in model)
            {
                if (curField.Value != null)
                {
                    string text = curField.Key.Trim();
                    try
                    {
                        Element element = this.GetElement(text);
                        if (element == null) continue;

                        if (element is SubHeadEntity)
                        {
                            DynamicObjectCollection dynamicObjectCollection = targetObj[(element as SubHeadEntity).EntryName] as DynamicObjectCollection;
                            string entryKey = (element as SubHeadEntity).Key;
                            string entryPKField = (element as SubHeadEntity).EntryPkFieldName;
                            this.MapCProperty(curField.Value as JSONArray, dynamicObjectCollection, entryKey, entryPKField);
                        }
                        else if (element is EntryEntity)
                        {
                            DynamicObjectCollection dynamicObjectCollection = targetObj[(element as EntryEntity).EntryName] as DynamicObjectCollection;
                            string entryKey = (element as EntryEntity).Key;
                            string entryPKField = (element as EntryEntity).EntryPkFieldName;
                            if (cleanEntry)
                            {
                                dynamicObjectCollection.Clear();
                            }
                            this.MapCProperty(curField.Value as JSONArray, dynamicObjectCollection, entryKey, entryPKField);
                        }
                        else if (element is Field)
                        {
                            Field field = element as Field;

                            if (field.Entity is SubHeadEntity)
                            {
                                DynamicObjectCollection dynamicObjectCollection = targetObj[field.Entity.EntryName] as DynamicObjectCollection;
                                if (dynamicObjectCollection.Count == 0)
                                {
                                    dynamicObjectCollection.Add(dynamicObjectCollection.DynamicCollectionItemPropertyType.CreateInstance() as DynamicObject);
                                }
                                SetValue(field, curField, dynamicObjectCollection[0], rowIndex);
                                continue;
                            }

                            SetValue(field, curField, targetObj, rowIndex);
                        }
                    }
                    catch (KDException ex)
                    {
                        if (ex.Code == "FE")
                        {
                            throw ex;
                        }
                        string sMessage = $"给字段({text})设置值({curField.Value}):{ ex.Message}";
                        KDException kdException = new KDException("FE", sMessage);
                        throw kdException;
                    }
                    catch (Exception ex)
                    {
                        string sMessage = $"给字段({text})设置值({curField.Value}):{ ex.Message}";
                        KDException kdException = new KDException("FE", sMessage);
                        throw kdException;
                    }
                }
            }
        }

        private void SetValue(Field field, KeyValuePair<string, object> curField, DynamicObject targetObj, int rowIndex)
        {
            Logger.Info("setValue.Key", field.Key);
            Logger.Info("setValue.Value", curField.Value == null ? "null" : curField.Value.ToString());
            
            #region 设置字段的值
            if (field is RelatedFlexGroupField)
            {// 维度关联字段
                /*
                var fieldTargetObj = Convert.ToString(curField.Value);
                if (fieldTargetObj == "0" || string.IsNullOrWhiteSpace(fieldTargetObj)) return;

                if (this._mapFlexFieldHelper == null)
                {
                    this._mapFlexFieldHelper = new MapFlexFieldHelper(this.ServiceContext, this.Model, this.BillBusinessInfo);
                }

                this._mapFlexFieldHelper.SetFlexValue(field as RelatedFlexGroupField, targetObj, JSONObject.Parse(fieldTargetObj), rowIndex);
                */

                long orgId = 0;
                List<Field> fields = BillView.BillBusinessInfo.GetFieldList();
                foreach(Field toOrgField in fields)
                {
                    OrgField orgField = toOrgField as OrgField;
                    if (orgField == null) continue;

                    if (orgField.IsMainOrg == 1)
                    {
                        OrgField mainOrgField = orgField;
                        orgId = mainOrgField.RefIDDynamicProperty.GetValue<long>(BillView.Model.DataObject);
                    }
                }


                var flexValue = curField.Value as string;
                if (string.IsNullOrWhiteSpace(flexValue)) return;
                FlexService flexService = new FlexService(this.Context, "BD_FLEXITEMDETAILV", orgId);
                var flexResult = flexService.FlexSave(flexValue);

                object id;

                if (flexResult.IsSuccess)
                {
                    id = flexResult.OperateResult[0].PKValue;
                    SetSimpleProperty(field, targetObj, id, rowIndex);
                }
                else
                {
                    string message = string.Empty;

                    if (flexResult.OperateResult != null)
                    {
                        var operations = flexResult.OperateResult;
                        foreach (var item in operations)
                        {
                            message += item.Message + ";";
                        }
                    }

                    if (flexResult.ValidationErrors != null)
                    {
                        var errors = flexResult.ValidationErrors;
                        foreach (var item in errors)
                        {
                            message += item.Message + ";";
                        }
                    }
                    throw new KDBusinessException("####", message);

                }
            }
            //多选基础资料
            else if (field is MulBaseDataField || field is MulAssistantField)
            {
                SetMulField(field, targetObj, curField.Value, rowIndex);
            }
            //批次字段和基础资料文本字段
            else if (field is LotField || field is BaseDataTextField)
            {
                SetLotAndBaseDataTextField(field, targetObj, curField.Value, rowIndex);
            }
            //基础资料
            else if (field is BaseDataField)
            {
                //会去掉强依赖，对于Number来搜索的，还是按正常的方式进行
                SetBaseDataField(field as BaseDataField, targetObj, curField.Value, rowIndex);
                if (targetObj[field.PropertyName] == null)
                {
                    Logger.Info(field.Key, "未賦值");
                }
                else
                {
                    Logger.Info(field.Key, "已賦值");
                }
                Logger.Info("setValue.Key", field.Key);
            }
            //大文本字段赋值处理，暂时不处理，现在还没有大文本字段
            else if (field is LargeTextField)
            {
                //SetLargeTextField(field as LargeTextField, targetObj, obj, sourceObj, rowIndex);
            }
            else if (field is CheckBoxField)
            {
                string curValue = curField.Value as string;
                SetSimpleProperty(field, targetObj, curValue == "0" ? false : true, rowIndex);
            }
            else
            {
                SetSimpleProperty(field, targetObj, curField.Value is System.DBNull ? null : curField.Value, rowIndex);
                if (targetObj[field.PropertyName] == null)
                {
                    Logger.Info(field.Key, "未賦值");
                }
                else
                {
                    Logger.Info("setValue.PropertyName", targetObj[field.PropertyName].ToString());
                    Logger.Info(field.Key, "已賦值");
                }
                Logger.Info("setValue.Key", field.Key);
            }
            #endregion
        }

    /// <summary>
    /// 单据体
    /// </summary>
    /// <param name="enity">单据体控件</param>
    /// <param name="sourceRows">源数据值</param>
    /// <param name="targetRows">目标行</param>
    /// <param name="NeedUpDateFields"></param>
    /// <param name="specialReferenceTable"></param>
    private void MapCProperty(JSONArray entry, DynamicObjectCollection targetRows, string entryKey, string entryPKField)
        {
            Dictionary<string, DynamicObject> targetDic = new Dictionary<string, DynamicObject>();
            Dictionary<string, DynamicObject> targetSICDic = new Dictionary<string, DynamicObject>();
            List<DynamicObject> removedRows = new List<DynamicObject>();
            foreach (DynamicObject targetRow in targetRows)
            {
                DealSrcInfo(entryKey, targetSICDic, removedRows, targetRow);

                if (targetRow["Id"] == null) continue;
                if (targetRow["Id"].ToString() == "0") continue;
                if (string.IsNullOrWhiteSpace(targetRow["Id"].ToString())) continue;

                targetDic.Add(targetRow["Id"].ToString(), targetRow);
            }
          
            foreach (var removeRow in removedRows)
            {
                //targetRows.Remove(removeRow);
            }

            int entryCount = entry.Count;
            HashSet<DynamicObject> entryRowHash = new HashSet<DynamicObject>();
            int index = 0;
            foreach (JSONObject entryRow in entry)
            {
                SetSrcEntryValue(entryRow, targetSICDic,targetRows);
                object pkValue;
                DynamicObject curRow;
                //根据接口传过来的行内码，对某行进行赋值
                if (entryRow.TryGetValue(entryPKField, out pkValue) && pkValue != null && targetDic.TryGetValue(pkValue.ToString(), out curRow))
                {
                    MapProperty(entryRow, curRow, targetRows.IndexOf(curRow));
                    entryRowHash.Add(curRow);
                    index++;
                }
            }

            List<DynamicObject> removeRows = new List<DynamicObject>();

            foreach (DynamicObject targetRow in targetRows)
            {
                if (targetRow["Id"] == null) continue;
                if (targetRow["Id"].ToString() == "0") continue;
                if (string.IsNullOrWhiteSpace(targetRow["Id"].ToString())) continue;
                var id = targetRow["Id"].ToString();

                if (entryRowHash.Contains(targetRow)) continue;

                removeRows.Add(targetRow);
            }
            /**
             * 如果需要删除，则对其进行删除，这个后面再增加。
             */
            if(this.IsDeleteEntry)
            { 
                foreach (var removeRow in removeRows)
                {
                    //targetRows.Remove(removeRow);
                }
            }

            if (index < entry.Count && this.IsNew)
            {
                this.Model.BatchCreateNewEntryRow(entryKey, entry.Count - index);
            }

            foreach (JSONObject entryRow in entry)
            { 
                object pkValue;
                DynamicObject curRow;
                if (entryRow.TryGetValue(entryPKField, out pkValue) && pkValue != null && targetDic.TryGetValue(pkValue.ToString(), out curRow))
                {
                    continue;
                }
                
                MapProperty(entryRow, targetRows[index], index);
                index++;
            }
        }

        private void SetSrcEntryValue(JSONObject item, Dictionary<string, DynamicObject> targetSICDic, DynamicObjectCollection targetRows)
        {
            if (!item.ContainsKey("ERP_SIC")) return;
            var SIC = item["ERP_SIC"];
            if (SIC == null || !string.IsNullOrWhiteSpace(SIC.ToString()) || SIC.ToString() != "0") return;
            DynamicObject target;
            if (!targetSICDic.TryGetValue(SIC.ToString(), out target))return;
            MapProperty(item, target, targetRows.IndexOf(target));
        }

        private void DealSrcInfo(string entryKey, Dictionary<string, DynamicObject> targetSICDic, List<DynamicObject> removedRows, DynamicObject targetRow)
        {
            string entryLinkKey = entryKey + "_Link";
            if (!targetRow.DynamicObjectType.Properties.ContainsKey(entryLinkKey)) return;

            var entityLink = targetRow[entryKey + "_Link"] as DynamicObjectCollection;
            if (entityLink.Count == 0) return;
            var sid = entityLink[0]["SId"];
            if (sid == null || !string.IsNullOrWhiteSpace(sid.ToString()) || sid.ToString() != "0") return;
            if (!targetSICDic.ContainsKey(sid.ToString()))
            {
                targetSICDic.Add(sid.ToString(), targetRow);
            }
            else
            {
                removedRows.Add(targetRow);
            }
        }
    }
}
