using Sugar.Enties;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using NLog;
using Newtonsoft.Json;
/// <summary>
/// 入库单业务逻辑
/// </summary>
public class MaterialInManager : DbContext<MaterialIn>
{

    /// <summary>
    /// 日志操作
    /// </summary>
    private static Logger logger = NLog.LogManager.GetCurrentClassLogger();

    //这里面写的代码不会给覆盖,如果要重新生成请删除 MaterialInManager.cs
    /// <summary>
    /// 获取入库单列表
    /// </summary>
    /// <param name="ProjectCode"></param>
    /// <param name="permission"></param>
    /// <returns></returns>
    public List<MaterialInDTO> GetMaterialIns(string ProjectCode, string permission, string search)
    {
        string sql = $@"SELECT top 20 a.MaterialInCode,sg.GroupName,a.ProjectCode,a.InPerson,caigou.UserName PurUserName, a.InDate,zd.UserName ZhiDanRen, a.InputDate,chk.UserName CheckRen, a.CheckDate,ct.ContractName,a.status FROM MaterialIn a 
          INNER JOIN SystemGroup sg ON a.GroupCode = sg.GroupCode
          INNER JOIN dbo.Contract ct ON a.ContractCode = ct.ContractCode
          INNER JOIN dbo.SystemUser caigou ON a.InPerson = caigou.UserCode
          INNER JOIN dbo.SystemUser chk ON a.InPerson = chk.UserCode
          INNER JOIN dbo.SystemUser zd ON a.InputPerson = zd.UserCode
          WHERE a.ProjectCode = '{ProjectCode}' AND sg.FullID LIKE '{permission}%' ORDER BY MaterialInCode DESC ";
        if (!string.IsNullOrEmpty(search))
        {
            sql += $" and {search}";
        }
        var list = Db.Ado.SqlQuery<MaterialInDTO>(sql);
        return list;
    }

    /// <summary>
    /// 根据入库单主键获取入库单实体
    /// </summary>
    /// <param name="materialInCode"></param>
    /// <returns></returns>
    public MaterialInDTO GetMaterialIn(string materialInCode)
    {
        string sql = $@"SELECT  a.MaterialInCode,sg.GroupName,a.ProjectCode,a.InPerson,caigou.UserName PurUserName, a.InDate,zd.UserName ZhiDanRen, a.InputDate,chk.UserName CheckRen, a.CheckDate,ct.ContractName,a.status,a.SupplierCode,a.SupplierTypeCode,a.ThreeSupplierCode,a.ThreeSupplierTypeCode FROM MaterialIn a 
          INNER JOIN SystemGroup sg ON a.GroupCode = sg.GroupCode
          INNER JOIN dbo.Contract ct ON a.ContractCode = ct.ContractCode
          INNER JOIN dbo.SystemUser caigou ON a.InPerson = caigou.UserCode
          INNER JOIN dbo.SystemUser chk ON a.InPerson = chk.UserCode
          INNER JOIN dbo.SystemUser zd ON a.InputPerson = zd.UserCode
          WHERE a.MaterialInCode = '{materialInCode}'  ";

        var entity = Db.Ado.SqlQuerySingle<MaterialInDTO>(sql);
        return entity;
    }
    /// <summary>
    /// 获取供应商名称和类型
    /// </summary>
    /// <param name="supplierCode"></param>
    /// <param name="SupplierTypeCode"></param>
    /// <returns></returns>
    public string GetSupplierNameAndType(string supplierCode, string SupplierTypeCode)
    {
        if (string.IsNullOrEmpty(supplierCode))
        {
            return "";
        }
        var sql = $"SELECT  SupplierName FROM dbo.Supplier WHERE SupplierCode='{supplierCode}'";
        var supplierNameAndType = Db.Ado.GetString(sql);
        if (!string.IsNullOrEmpty(SupplierTypeCode))
        {
            if (string.IsNullOrEmpty(supplierCode))
            {
                return supplierNameAndType;
            }
            sql = $"SELECT GroupName FROM dbo.SystemGroup WHERE GroupCode='{SupplierTypeCode}'";
            var name = Db.Ado.GetString(sql);
            if (!string.IsNullOrEmpty(name))
            {
                supplierNameAndType += "类型：" + name;
            }
        }
        return supplierNameAndType;
    }
    /// <summary>
    /// 获取入库单明细
    /// </summary>
    /// <param name="materialInCode"></param>
    /// <returns></returns>
    public List<V_MaterialInDtl> GetV_MaterialInDtlList(string materialInCode)
    {
        var sql = $"SELECT * FROM dbo.V_MaterialInDtl  WHERE MaterialInCode='{materialInCode}'";
        var list = Db.Ado.SqlQuery<V_MaterialInDtl>(sql);
        return list;
    }
    /// <summary>
    /// 根据lamda表达式获取入库单明细
    /// </summary>
    /// <param name="lamda"></param>
    /// <returns></returns>
    public List<V_MaterialInDtl> GetV_MaterialInDtlList(Expression<Func<V_MaterialInDtl, bool>> lamda)
    {
        var list = Db.Queryable<V_MaterialInDtl>().Where(lamda).ToList();
        return list;
    }

    /// <summary>
    /// 获取领料单明细
    /// </summary>
    /// <param name="materialInCode"></param>
    /// <returns></returns>
    public List<V_MaterialOutDtl> GetV_MaterialOutDtlList(string materialInCode)
    {
        var sql = $"SELECT * FROM dbo.V_MaterialOutDtl  WHERE MaterialInCode='{materialInCode}'";
        var list = Db.Ado.SqlQuery<V_MaterialOutDtl>(sql);
        return list;
    }
    /// <summary>
    /// 根据lamda表达式获取领料明细
    /// </summary>
    /// <param name="lamda"></param>
    /// <returns></returns>
    public List<V_MaterialOutDtl> GetV_MaterialOutDtlList(Expression<Func<V_MaterialOutDtl, bool>> lamda)
    {
        var list = Db.Queryable<V_MaterialOutDtl>().Where(lamda).ToList();
        return list;
    }
    /// <summary>
    /// 根据项目代码和合同编码获取合同中包含的资料
    /// </summary>
    /// <param name="projectCode">项目编码</param>
    /// <param name="contractCode">合同编码</param>
    /// <returns></returns>
    public List<Material> GetMaterials(string projectCode, string contractCode, string searchValue)
    {
        string sql = $@"SELECT  m.* FROM dbo.Contract ct 
                    INNER JOIN MaterialContract mc ON ct.ContractCode=mc.ContractCode 
                    INNER JOIN dbo.Material m ON mc.MaterialCode=m.MaterialCode
                     WHERE ct.ProjectCode='{projectCode}' AND ct.ContractCode='{contractCode}' ";

        if (!string.IsNullOrEmpty(searchValue))
        {
            sql += $" and MaterialName like '%{searchValue}%'";
        }
        var list = Db.Ado.SqlQuery<Material>(sql);
        return list;
    }
    /// <summary>
    /// 插入入库单主表和子表
    /// </summary>
    /// <param name="materialIn">入库单主表实体</param>
    /// <param name="mDetailList">入库单子表实体集合</param>
    /// <param name="materialOut">领料单主表</param>
    /// <returns></returns>
    public string InsertMaterialIn(MaterialIn materialIn, List<MaterialInDtl> mDetailList, MaterialOut materialOut)
    {
        var success = "";


        //materialIn.CheckDate = null;
        try
        {
            Db.BeginTran();
            var sql = string.Format("declare @value varchar(50);exec sp_get_syscode 'MaterialIn', @value output;select @value;");
            var strMaterialIn = Db.Ado.GetString(sql);
            materialIn.MaterialInCode = strMaterialIn;
            materialIn.MaterialInID = strMaterialIn;
            materialIn.Status = 0;
            materialIn.InputDate = DateTime.Now;
            materialIn.Remark = "";
            Db.Insertable<MaterialIn>(materialIn).ExecuteCommand();


            //插入领料单主表
            sql = string.Format("declare @value varchar(50);exec sp_get_syscode 'MaterialOut', @value output;select @value;");
            var strMaterialOut = Db.Ado.GetString(sql);
            materialOut.MaterialOutCode = strMaterialOut;
            materialOut.MaterialOutID = strMaterialOut;
            materialOut.Status = 0;
            materialOut.InputDate = DateTime.Now;
            materialOut.Remark = "";
            materialOut.MoneyType = "人民币";
            materialOut.ExchangeRate = (decimal)1.0;
            Db.Insertable<MaterialOut>(materialOut).ExecuteCommand();




            //根据工程合同单号获取材料计划单号
            var list1 = GetMaterialBudget(materialOut.ContractCode);
            logger.Info($"【InsertMaterialIn】list1:{JsonConvert.SerializeObject(list1)}");
            //根据材料计划单号获取材料计划单明细列表
            List<MaterialBudgetDtl> list2 = null;
            if (list1.Count > 0)
            {
                list2 = Db.Queryable<MaterialBudgetDtl>().Where(m => SqlFunc.ContainsArray(list1, m.MaterialBudgetCode)).ToList();
            }
            foreach (var item in mDetailList)
            {
                //插入入库单明细
                sql = string.Format("declare @value varchar(50);exec sp_get_syscode 'MaterialInDtl', @value output;select @value;");
                item.MaterialInDtlCode = Db.Ado.GetString(sql);
                item.MaterialInCode = materialIn.MaterialInCode;
                item.InMoney = item.InPrice * item.InQty;
                Db.Insertable<MaterialInDtl>(item).ExecuteCommand();

                //插入领料单明细
                var outDtl = new MaterialOutDtl();
                sql = string.Format("declare @value varchar(50);exec sp_get_syscode 'MaterialOutDtl', @value output;select @value;");
                outDtl.MaterialOutDtlCode = Db.Ado.GetString(sql);
                outDtl.MaterialOutCode = strMaterialOut;
                outDtl.MaterialCode = item.MaterialCode;
                var entity = list2?.Where(m => m.MaterialCode == outDtl.MaterialCode).FirstOrDefault();
                outDtl.MaterialInDtlCode = item.MaterialInDtlCode;
                outDtl.OutQty = item.InQty;
                outDtl.OutPrice = item.InPrice;
                outDtl.OutMoney = item.InMoney;
                outDtl.OutPriceMoney = item.InPrice;
                outDtl.OutCash = item.InMoney;
                outDtl.MaterialBudgetCode = entity?.MaterialBudgetCode;
                outDtl.AlreadyDeductCash = (decimal)0;
                outDtl.AlreadyDeductMoney = (decimal)0;
                outDtl.AlreadyDeductNum = (decimal)0;
                outDtl.IsDeductOver = 0;
                outDtl.MaterialInDtlCode = item.MaterialInDtlCode;
                Db.Insertable<MaterialOutDtl>(outDtl).ExecuteCommand();
            }

            Db.CommitTran();
            success = materialIn.MaterialInCode;
        }
        catch (Exception ex)
        {
            Db.RollbackTran();

            throw;
        }
        return success;
    }
    /// <summary>
    /// 更新入库单主表和子表
    /// </summary>
    /// <param name="materialIn"></param>
    /// <param name="mDetailList"></param>
    /// <returns></returns>
    public string UpdateMaterialIn(MaterialIn materialIn, List<MaterialInDtl> mDetailList, MaterialOut materialOut)
    {
        var success = "";
        var model1 = MaterialInDb.GetById(materialIn.MaterialInCode);
        if (model1 == null)
        {
            return "-1";     //修改项不存在
        }
        if (model1.Status != 0)
        {
            return "-2";     //非待审核状态，不能修改
        }

        try
        {
            Db.BeginTran();
            //更新主表
            Db.Updateable(materialIn).UpdateColumns(it => new { it.GroupCode, it.ContractCode, it.SupplierCode, it.SupplierTypeCode, it.SupplierTypeId, it.InDate }).ExecuteCommand();


            logger.Info($"【UpdateMaterialIn】materialOut:{JsonConvert.SerializeObject(materialOut)}");
            //更新领料单主表
            Db.Updateable(materialOut).UpdateColumns(it => new { it.GroupCode, it.ContractCode, it.DoSupplierCode, it.SupplierTypeCode, it.SupplierTypeId, it.OutDate }).ExecuteCommand();






            //删除领料单明细所有记录
            Db.Deleteable<MaterialOutDtl>().Where(m => m.MaterialOutCode == materialOut.MaterialOutCode).ExecuteCommand();
            //删除入库单明细所有记录
            Db.Deleteable<MaterialInDtl>().Where(m => m.MaterialInCode == materialIn.MaterialInCode).ExecuteCommand();

            //根据工程合同单号获取材料计划单号
            var list1 = GetMaterialBudget(materialOut.ContractCode);
            logger.Info($"【UpdateMaterialIn】list1:{JsonConvert.SerializeObject(list1)}");
            //根据材料计划单号获取材料计划单明细列表
            List<MaterialBudgetDtl> list2 = null;
            if (list1.Count > 0)
            {
                list2 = Db.Queryable<MaterialBudgetDtl>().Where(m => SqlFunc.ContainsArray(list1, m.MaterialBudgetCode)).ToList();
            }
            //重新插入
            foreach (var item in mDetailList)
            {
                var sql1 = string.Format("declare @value varchar(50);exec sp_get_syscode 'MaterialInDtl', @value output;select @value;");
                item.MaterialInDtlCode = Db.Ado.GetString(sql1);
                logger.Info($"【UpdateMaterialIn】item.MaterialInDtlCode:{item.MaterialInDtlCode}");
                item.MaterialInCode = materialIn.MaterialInCode;
                item.InMoney = item.InPrice * item.InQty;
                Db.Insertable<MaterialInDtl>(item).ExecuteCommand();

                //插入领料单明细
                var outDtl = new MaterialOutDtl();
                var sql = string.Format("declare @value varchar(50);exec sp_get_syscode 'MaterialOutDtl', @value output;select @value;");
                outDtl.MaterialOutDtlCode = Db.Ado.GetString(sql);
                outDtl.MaterialOutCode = materialOut.MaterialOutCode;
                outDtl.MaterialCode = item.MaterialCode;
                var entity = list2?.Where(m => m.MaterialCode == outDtl.MaterialCode).FirstOrDefault();
                outDtl.MaterialInDtlCode = item.MaterialInDtlCode;
                logger.Info($"【UpdateMaterialIn】outDtl.MaterialInDtlCode:{item.MaterialInDtlCode}");
                outDtl.OutQty = item.InQty;
                outDtl.OutPrice = item.InPrice;
                outDtl.OutMoney = item.InMoney;
                outDtl.OutPriceMoney = item.InPrice;
                outDtl.OutCash = item.InMoney;
                outDtl.MaterialBudgetCode = entity?.MaterialBudgetCode;
                outDtl.AlreadyDeductCash = (decimal)0;
                outDtl.AlreadyDeductMoney = (decimal)0;
                outDtl.AlreadyDeductNum = (decimal)0;
                outDtl.IsDeductOver = 0;
                Db.Insertable<MaterialOutDtl>(outDtl).ExecuteCommand();
            }
            Db.CommitTran();
            success = materialIn.MaterialInCode;
        }
        catch (Exception ex)
        {
            Db.RollbackTran();

            throw;
        }
        return success;
    }
    /// <summary>
    /// 根据入库单号获取入库单明细表与材料表关联的数据
    /// </summary>
    /// <param name="materialInCode"></param>
    /// <returns></returns>
    public List<MaterialDTO> GetMaterialDTOs(string materialInCode)
    {
        var sql = $"SELECT a.*,b.InQty,b.NoPassQty NoQty FROM material a INNER JOIN MaterialInDtl b ON a.MaterialCode=b.MaterialCode WHERE b.MaterialInCode='{materialInCode}'";
        var list = Db.Ado.SqlQuery<MaterialDTO>(sql);
        return list;
    }
    /// <summary>
    /// 获取合同表中相关的合同及供应商信息
    /// </summary>
    /// <param name="contractCode"></param>
    /// <returns></returns>
    public dynamic GetContractAndSupplier(string contractCode)
    {
        var sql = $"SELECT contractCode,contractID,contractName,supplierCode,supplierTypeCode,supplierTypeId FROM dbo.Contract WHERE ContractCode='{contractCode}'";
        var model = Db.Ado.SqlQuery<dynamic>(sql);
        return model;
    }
    /// <summary>
    /// 根据数据权限编码获取数据权限的名字
    /// </summary>
    /// <param name="groupCode"></param>
    /// <returns></returns>
    public string GetGroupName(string groupCode)
    {
        var sql = $"SELECT groupName FROM systemgroup WHERE groupcode='{groupCode}'";
        return Db.Ado.GetString(sql);
    }
    /// <summary>
    /// 根据工程合同单号获取相应的材料计划单号列表
    /// </summary>
    /// <param name="RelationCode">工程合同单号</param>
    /// <returns></returns>
    public List<string> GetMaterialBudget(string RelationCode)
    {
        var sql = $"select mb.MaterialBudgetCode from MaterialBudgetRelation mbr join MaterialBudget mb on mbr.BudgetCode=mb.MaterialBudgetCode where mbr.BudgetType='JG' and mbr.RelationType='Contract' and mbr.RelationCode='{RelationCode}'";
        logger.Info($"【GetMaterialBudget】 sql:{sql}");
        var list = Db.Ado.SqlQuery<string>(sql);
        return list;
    }

    /// <summary>
    /// 获取工程合同中包含的材料编码列表
    /// </summary>
    /// <param name="projectcode">项目编码</param>
    /// <param name="contractcode">工程合同编码</param>
    /// <param name="materialBudgetCodeList">材料计划单号列表</param>
    /// <returns></returns>
    public List<Material> GetMaterialsOfContract(string projectcode, string contractcode, List<string> materialBudgetCodeList)
    {
        var codes = "";
        foreach (var str in materialBudgetCodeList)
        {
            codes += "'" + str + "',";
        }
        if (codes.EndsWith(","))
        {
            codes = codes.Substring(0, codes.Length - 1);
        }
        logger.Info($"【GetMaterialsOfContract】 codes:{codes}");
        var sql = $"select Material.MaterialCode,Material.MaterialName from V_MaterialInDtl as Material where Status in ( 2 ) and materialincode in (select materialincode from materialin where projectcode='{projectcode}') and materialcode in (select materialcode from MaterialBudgetDtl where MaterialBudgetCode in ({codes})) and materialcode in (select materialcode from contractmaterial where contractcode='{contractcode}') and InvQty>0  ";
        logger.Info($"【GetMaterialsOfContract】 sql:{sql}");
        var list = Db.Ado.SqlQuery<Material>(sql);
        return list;
    }
    /// <summary>
    /// 根据入库单号返回关联的领料单表
    /// </summary>
    /// <param name="materialInCode"></param>
    /// <returns></returns>
    public MaterialOut GetMaterialOutRelation(string materialInCode)
    {
        var sql = $"  SELECT mo.* FROM dbo.Materialout mo INNER JOIN MaterialOutDtl mod ON mo.MaterialOutCode=mod.MaterialOutCode INNER JOIN dbo.MaterialInDtl mid ON mod.MaterialInDtlCode=mid.MaterialInDtlCode WHERE mid.MaterialInCode='{materialInCode}'";
        var model = Db.Ado.SqlQuery<MaterialOut>(sql).FirstOrDefault();
        return model;
    }
}
