using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DirectService.Tools;
using JLHHJSvr.BLL;
using JLHHJSvr.Com;
using JLHHJSvr.Com.Model;
using JLHHJSvr.Helper;
using LJLib.DAL.SQL;
using LJLib.Net.SPI.Server;
using LJLib.SQLEX;
using Newtonsoft.Json;

namespace JLHHJSvr.Excutor
{
    internal sealed class BatchModifyMattressInterfaceConfigExcutor : ExcutorBase<BatchModifyMattressInterfaceConfigRequest, BatchModifyMattressInterfaceConfigResponse>
    {
        protected override void ExcuteInternal(BatchModifyMattressInterfaceConfigRequest request, object state, BatchModifyMattressInterfaceConfigResponse rslt)
        {
            var tokendata = BllHelper.GetToken(request.token);
            rslt.items = new List<u_task_log_mx>();
            if (tokendata == null)
            {
                rslt.ErrMsg = "会话已经中断，请重新登录";
                return;
            }

            if (!ValidateRequest(request, rslt, out var inputList))
            {
                return;
            }

            using (var con = GlobalVar.ConnectionString.NewSqlConnection())
            using (var cmd = con.CreateCommand())
            {
                con.Open();

                if (!UserHelper.CheckFuncPower(cmd, tokendata.empid, 177))
                {
                    rslt.ErrMsg = "没有床垫清单批量批改配置权限";
                    return;
                }

                var mattressIds = inputList.Select(t => t).ToList();
                var context = new HelperBase.Context() { tokendata = tokendata };
                var mattressHelper = HelperBase.GetHelper<MattressHelper>(cmd, context);

                var mattressMap = mattressHelper.GetMattressList(mattressIds, "mattressid,mattresscode,mattressname,erp_configcodetype")
                    .GroupBy(t => t.mattressid)
                    .ToDictionary(t => t.Key, t => t.First());

                var targetRowsMap = GetTargetConfigRows(cmd, request, mattressIds)
                    .GroupBy(t => t.mattressid.Value)
                    .ToDictionary(t => t.Key, t => t.ToList());

                var l1InterfaceMap = GetL1InterfaceRows(cmd, mattressIds)
                    .GroupBy(t => t.mattressid.Value)
                    .ToDictionary(t => t.Key, t => t.ToList());

                var taskid = ScheduleTaskHelper.CreateTaskLog(cmd, new u_task_log
                {
                    task_type = ScheduleTaskHelper.TaskTypeBatchModifyMattressInterfaceConfig,
                    run_mode = 1,
                    status = 1,
                    total_count = inputList.Count,
                    request_json = GetTaskRequestJson(request),
                    create_emp = tokendata.username
                });
                rslt.taskid = taskid;

                var workItems = CreateWorkItems(inputList, mattressMap);
                ScheduleTaskHelper.InsertTaskLogItems(cmd, taskid, workItems.Select(t => new u_task_log_mx
                {
                    printid = t.printid,
                    biz_id = t.mattressid,
                    biz_code = t.result.biz_code,
                    biz_name = t.mattressname,
                    status = 1
                }).ToList());

                foreach (var workItem in workItems)
                {
                    mattressMap.TryGetValue(workItem.mattressid, out var mattress);
                    if (!targetRowsMap.TryGetValue(workItem.mattressid, out var targetRows)) targetRows = new List<u_mattress_interface>();
                    if (!l1InterfaceMap.TryGetValue(workItem.mattressid, out var interfaceRows)) interfaceRows = new List<u_mattress_interface>();
                    var result = workItem.result;

                    try
                    {
                        if (mattress == null)
                        {
                            result.err_msg = "床垫报价记录不存在,请检查!";
                            return;
                        }

                        if (mattress.erp_configcodetype != request.configcodetype)
                        {
                            result.err_msg = "配置名称不匹配!";
                            return;
                        }

                        if (LockHelper.CheckIsLock(cmd, MattressHelper.BillKeyWord, mattress.mattressid, tokendata.username, out string lockMsg)
                            || LockHelper.CheckIsLock(cmd, InterfaceHelper.BillKeyWord, mattress.mattressid, tokendata.username, out lockMsg))
                        {
                            result.err_msg = lockMsg;
                            return;
                        }

                        if (targetRows.Count == 0)
                        {
                            result.status = 4;
                            result.err_msg = "配置行不存在";
                            return;
                        }
                        if (targetRows.Count > 1)
                        {
                            result.err_msg = $"床垫报价:{mattress}存在重复配置行,请先手动处理!";
                            return;
                        }

                        var target = targetRows[0];
                        if (target.bj_inputtype != 1)
                        {
                            result.status = 4;
                            result.err_msg = "配置不是录入类型,请检查!";
                            return;
                        }

                        using (cmd.Transaction = cmd.Connection.BeginTransaction())
                        {
                            try
                            {
                                UpdateConfigName(cmd, request, mattress.mattressid, target.printid.Value);
                                UpdatePrefetchedInterfaceName(interfaceRows, target.printid.Value, request.new_bj_namemx);

                                //var l1Helper = HelperBase.GetHelper<ERPHelper>(cmd);
                                //l1Helper.context = new HelperBase.Context() { tokendata = tokendata };
                                //l1Helper.GetMattressMsg(mattress, interfaceRows);
                                //var errMsg = l1Helper.SaveMtrldef(mattress, interfaceRows);
                                //if (!string.IsNullOrEmpty(errMsg))
                                //{
                                //    throw new Exception(errMsg);
                                //}

                                //if (mattress.erp_mtrlid > 0)
                                //{
                                //    mattress.creatmtrl_flag = 1;
                                //    mattress.creatmtrl_auditingrep = tokendata.username;
                                //    mattress.creatmtrl_auditingdate = DateTime.Now;
                                //    DbSqlHelper.Update(cmd, mattress, "erp_mtrlid,creatmtrl_flag,erp_mtrlcode,creatmtrl_auditingrep,creatmtrl_auditingdate");
                                //}

                                cmd.Transaction.Commit();
                                result.status = 2;
                                result.err_msg = "Success.";
                            }
                            catch (Exception ex)
                            {
                                cmd.Transaction.Rollback();
                                result.status = 3;
                                result.err_msg = ex.Message;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        result.status = 3;
                        result.err_msg = ex.Message;
                    }

                    rslt.items.Add(result);
                }

                FinishTaskLog(cmd, taskid, rslt.items);
            }

            rslt.totalCount = rslt.items.Count;
            rslt.successCount = rslt.items.Count(t => t.status == 2);
            rslt.failCount = rslt.items.Count(t => t.status == 3);
            rslt.skipCount = rslt.items.Count(t => t.status == 4);
        }

        private bool ValidateRequest(BatchModifyMattressInterfaceConfigRequest request, BatchModifyMattressInterfaceConfigResponse rslt, out List<int> inputList)
        {
            inputList = new List<int>();

            if (request.list == null || !request.list.Any())
            {
                rslt.ErrMsg = "请选择需要批改的床垫清单";
                return false;
            }
            if (request.list.Count > 200)
            {
                rslt.ErrMsg = string.Format("单次最多批改{0}条，请分批处理", 200);
                return false;
            }

            request.bj_pzname = (request.bj_pzname ?? string.Empty).Trim();
            request.new_bj_namemx = (request.new_bj_namemx ?? string.Empty).Trim();

            if (request.configcodetype <= 0 || request.erp_pzid <= 0 || string.IsNullOrWhiteSpace(request.bj_pzname))
            {
                rslt.ErrMsg = "配置名称参数不完整";
                return false;
            }
            if (string.IsNullOrWhiteSpace(request.new_bj_namemx))
            {
                rslt.ErrMsg = "批改后明细名称不能为空";
                return false;
            }
            if (request.new_bj_namemx.Length > 200)
            {
                rslt.ErrMsg = "批改后明细名称长度不能超过200个字符";
                return false;
            }

            inputList = request.list
                .Where(t => t > 0)
                .GroupBy(t => t)
                .Select(t => t.First())
                .ToList();

            if (!inputList.Any())
            {
                rslt.ErrMsg = "床垫ID参数为空";
                return false;
            }

            return true;
        }

        private List<BatchModifyMattressInterfaceConfigWorkItem> CreateWorkItems(List<int> inputList, Dictionary<int, u_mattress> mattressMap)
        {
            var printid = 1;
            return inputList.Select(input =>
            {
                mattressMap.TryGetValue(input, out var mattress);
                return new BatchModifyMattressInterfaceConfigWorkItem
                {
                    printid = printid++,
                    mattressid = input,
                    mattressname = mattress == null ? string.Empty : mattress.mattressname,
                    result = new u_task_log_mx
                    {
                        biz_code = mattress.mattresscode,
                        status = 3,
                        err_msg = string.Empty
                    }
                };
            }).ToList();
        }

        private string GetTaskRequestJson(BatchModifyMattressInterfaceConfigRequest request)
        {
            return JsonConvert.SerializeObject(new
            {
                request.list,
                request.configcodetype,
                request.erp_pzid,
                request.bj_pzname,
                request.new_bj_namemx
            });
        }

        private void FinishTaskLog(SqlCommand cmd, int taskid, List<u_task_log_mx> items)
        {
            var successCount = items.Count(t => t.status == 2);
            var failCount = items.Count(t => t.status == 3);
            var skipCount = items.Count(t => t.status == 4);
            ScheduleTaskHelper.UpdateTaskLogItemResults(cmd, taskid, items.Select((item, index) => new u_task_log_mx
            {
                printid = index + 1,
                status = item.status,
                result_json = JsonConvert.SerializeObject(item),
                err_msg = item.err_msg
            }).ToList());
            var logMsg = string.Format(
                "任务类型:{0} 总数:{1} 成功:{2} 失败:{3} 跳过:{4}",
                ScheduleTaskHelper.GetTaskTypeName(ScheduleTaskHelper.TaskTypeBatchModifyMattressInterfaceConfig),
                items.Count,
                successCount,
                failCount,
                skipCount);
            ScheduleTaskHelper.FinishTaskLog(cmd, taskid, items.Count, successCount, failCount, skipCount, logMsg);
        }

        private List<u_mattress_interface> GetTargetConfigRows(SqlCommand cmd, BatchModifyMattressInterfaceConfigRequest request, List<int> mattressIds)
        {
            var list = new List<u_mattress_interface>();
            var selectStr = @"SELECT u_mattress_interface.mattressid
	                                ,u_mattress_interface.printid
	                                ,u_mattress_interface.itemname
	                                ,u_mattress_interface.bj_pzname
	                                ,u_mattress_interface.bj_namemx
	                                ,u_mattress_interface.actual_size
	                                ,u_mattress_interface.sb_craft
	                                ,u_mattress_interface.actual_size_sb
	                                ,u_mattress_interface.erp_pzid
	                                ,u_mattress_interface.ss_rate
	                                ,u_mattress_interface.ls_rate
	                                ,u_mattress_interface.bj_inputtype
                                FROM u_mattress_interface
                                INNER JOIN u_mattress ON u_mattress.mattressid = u_mattress_interface.mattressid";
            var where = @"u_mattress_interface.mattressid IN " + ListEx.getString(mattressIds) + @"
                            AND u_mattress.erp_configcodetype = @configcodetype
                            AND u_mattress_interface.erp_pzid = @erp_pzid
                            AND u_mattress_interface.bj_pzname = @bj_pzname";

            DbSqlHelper.SelectJoin(cmd, selectStr, where, new Dictionary<string, object>()
            {
                { "@configcodetype", request.configcodetype },
                { "@erp_pzid", request.erp_pzid },
                { "@bj_pzname", request.bj_pzname }
            }, "u_mattress_interface.mattressid,u_mattress_interface.printid", "mattressid,printid,itemname,bj_pzname,bj_namemx,actual_size,sb_craft,actual_size_sb,erp_pzid,ss_rate,ls_rate,bj_inputtype", 0, 0, list);
            return list;
        }

        private void UpdateConfigName(SqlCommand cmd, BatchModifyMattressInterfaceConfigRequest request, int mattressid, int printid)
        {
            cmd.CommandText = @"UPDATE u_mattress_interface
                                SET bj_namemx = @new_bj_namemx
                                WHERE mattressid = @mattressid
                                    AND printid = @printid
                                    AND erp_pzid = @erp_pzid
                                    AND bj_pzname = @bj_pzname
                                    AND bj_inputtype = 1
                                    AND EXISTS (
                                        SELECT 1
                                        FROM u_mattress
                                        WHERE u_mattress.mattressid = u_mattress_interface.mattressid
                                            AND u_mattress.erp_configcodetype = @configcodetype
                                    )";
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.Clear();
            cmd.Parameters.AddWithValue("@new_bj_namemx", request.new_bj_namemx);
            cmd.Parameters.AddWithValue("@mattressid", mattressid);
            cmd.Parameters.AddWithValue("@printid", printid);
            cmd.Parameters.AddWithValue("@erp_pzid", request.erp_pzid);
            cmd.Parameters.AddWithValue("@bj_pzname", request.bj_pzname);
            cmd.Parameters.AddWithValue("@configcodetype", request.configcodetype);
            var count = cmd.ExecuteNonQuery();
            if (count != 1)
            {
                throw new Exception("Failed to update config row.");
            }
        }

        private List<u_mattress_interface> GetL1InterfaceRows(SqlCommand cmd, List<int> mattressIds)
        {
            var interfaceList = new List<u_mattress_interface>();
            var selectStr = @"SELECT u_mattress_interface.mattressid
	                                ,printid
	                                ,itemname
	                                ,bj_pzname
	                                ,bj_namemx
	                                ,actual_size
	                                ,sb_craft
	                                ,actual_size_sb
	                                ,erp_pzid
	                                ,ss_rate
	                                ,ls_rate
	                                ,bj_inputtype
                                    ,u_configure_code.pzcode
                                    ,u_configure_code.name AS pzname
                                FROM u_mattress_interface
                                INNER JOIN u_mattress on u_mattress.mattressid = u_mattress_interface.mattressid
                                INNER JOIN u_configure_code on u_configure_code.typeid = u_mattress.erp_configcodetype 
		                                AND u_mattress_interface.erp_pzid = u_configure_code.pzid";
            var where = "u_mattress_interface.mattressid IN " + ListEx.getString(mattressIds) + " AND u_mattress_interface.erp_pzid > 0 AND u_mattress_interface.bj_pzname <> '' ";
            DbSqlHelper.SelectJoin(cmd, selectStr, where, new Dictionary<string, object>(), "u_mattress_interface.mattressid,printid", "mattressid,printid,itemname,bj_pzname,bj_namemx,actual_size,sb_craft,actual_size_sb,erp_pzid,ss_rate,ls_rate,bj_inputtype,pzcode,pzname", 0, 0, interfaceList);
            return interfaceList;
        }

        private void UpdatePrefetchedInterfaceName(List<u_mattress_interface> interfaceRows, int printid, string newName)
        {
            var row = interfaceRows.FirstOrDefault(t => t.printid == printid);
            if (row != null)
            {
                row.bj_namemx = newName;
            }
        }

        private sealed class BatchModifyMattressInterfaceConfigWorkItem
        {
            public int printid { get; set; }
            public int mattressid { get; set; }
            public string mattressname { get; set; }
            public u_task_log_mx result { get; set; }
        }
    }
}
