using OpenAuth.App.Base;
using OpenAuth.App.DataCodeRule.Response;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Infrastructure.Extensions;
using Infrastructure.Cache;
using OpenAuth.App.BaseApp.Base;

namespace OpenAuth.App.DataCodeRule
{
    /// <summary>
    /// 日期：2024-03-06
    /// 描述：编号规则
    /// </summary>
    public class CodeRuleApp : SqlSugarBaseApp<Repository.Domain.SysCodeRule, SugarDbContext>
    {
        private ICacheContext _iCache;
        public CodeRuleApp(ISugarUnitOfWork<SugarDbContext> unitWork, ICacheContext cacheContext,
           ISimpleClient<Repository.Domain.SysCodeRule> repository)
           : base(unitWork, repository, null)
        {
            _iCache = cacheContext;
        }
        #region 单据编码处理
        /// <summary>
        /// 获得指定模块或者编号的单据号
        /// </summary>
        /// <param name="enCode">编码</param>
        /// <returns>单据号</returns>
        public async Task<string> GetBillCode(string enCode)
        {
            string billCode = "";    //单据号
            string nextBillCode = "";//单据号

            SysCodeRule coderuleentity = await GetEntityByCode(enCode);
            if (coderuleentity != null)
            {
                List<CodeRuleFormatModel> codeRuleFormatList = coderuleentity.RuleFormatJson.ToList<CodeRuleFormatModel>();
                string dateFormatStr = "";
                foreach (CodeRuleFormatModel codeRuleFormatEntity in codeRuleFormatList)
                {
                    switch (codeRuleFormatEntity.itemType.ToString())
                    {
                        //自定义项
                        case "0":
                            billCode += codeRuleFormatEntity.formatStr;
                            nextBillCode += codeRuleFormatEntity.formatStr;
                            break;
                        //日期
                        case "1":
                            //日期字符串类型
                            dateFormatStr += codeRuleFormatEntity.formatStr.Replace("m", "M");
                            billCode += DateTime.Now.ToString(dateFormatStr);
                            nextBillCode += DateTime.Now.ToString(dateFormatStr);
                            break;
                        //流水号
                        case "2":
                            int seedStep = codeRuleFormatEntity.stepValue == null ? 1 : int.Parse(codeRuleFormatEntity.stepValue.ToString());//如果步长为空默认1
                            int initValue = codeRuleFormatEntity.initValue == null ? 1 : int.Parse(codeRuleFormatEntity.initValue.ToString());//如果初始值为空默认1

                            int nowSerious = await _iCache.Lock<int>(coderuleentity.RuleId, id => { return GetSeedValue(coderuleentity.RuleId, initValue, seedStep, dateFormatStr); });
                            //int nowSerious =await codeRuleService.GetSeedValue(coderuleentity.F_RuleId, initValue, seedStep, dateFormatStr);


                            int nextSerious = nowSerious + seedStep;
                            // 最大种子已经过期
                            string seriousStr = new string('0', (int)(codeRuleFormatEntity.formatStr.Length - nowSerious.ToString().Length)) + nowSerious.ToString();
                            string NextSeriousStr = new string('0', (int)(codeRuleFormatEntity.formatStr.Length - nextSerious.ToString().Length)) + nextSerious.ToString();
                            billCode += seriousStr;
                            nextBillCode += NextSeriousStr;
                            break;
                        //部门
                        case "3":
                            //var userInfo = await CurrentUser();
                            //DepartmentEntity departmentEntity = await _departmentIBLL.GetEntity(userInfo.F_DepartmentId);
                            //if (departmentEntity != null)
                            //{
                            //    if (codeRuleFormatEntity.formatStr == "code")
                            //    {
                            //        billCode += departmentEntity.F_EnCode;
                            //        nextBillCode = nextBillCode + departmentEntity.F_EnCode;
                            //    }
                            //    else
                            //    {
                            //        billCode = billCode + departmentEntity.F_FullName;
                            //        nextBillCode = nextBillCode + departmentEntity.F_FullName;

                            //    }
                            //}
                            break;
                        //公司
                        case "4":
                            //var userInfo2 = await CurrentUser();
                            //CompanyEntity companyEntity = await _companyIBLL.GetEntity(userInfo2.F_CompanyId);
                            //if (companyEntity != null)
                            //{
                            //    if (codeRuleFormatEntity.formatStr == "code")
                            //    {
                            //        billCode += companyEntity.F_EnCode;
                            //        nextBillCode += companyEntity.F_EnCode;
                            //    }
                            //    else
                            //    {
                            //        billCode += companyEntity.F_FullName;
                            //        nextBillCode += companyEntity.F_FullName;
                            //    }
                            //}
                            break;
                        //用户
                        case "5":
                            //var userInfo3 = await CurrentUser();
                            //if (codeRuleFormatEntity.formatStr == "code")
                            //{
                            //    billCode += userInfo3.F_Account;
                            //    nextBillCode += userInfo3.F_Account;
                            //}
                            //else
                            //{
                            //    billCode += userInfo3.F_RealName;
                            //    nextBillCode += userInfo3.F_RealName;
                            //}
                            break;
                        default:
                            break;
                    }
                }
                coderuleentity.CurrentNumber = nextBillCode;
                await SaveEntity(coderuleentity.RuleId, coderuleentity);
            }
            return billCode;

        }

        /// <summary>
        /// 保存规则表单（新增、修改）
        /// </summary>
        /// <param name="keyValue">主键值</param>
        /// <param name="codeRuleEntity">规则实体</param>
        /// <returns></returns>
        public async Task SaveEntity(string keyValue, SysCodeRule codeRuleEntity)
        {
            if (!string.IsNullOrEmpty(keyValue))
            {
                codeRuleEntity.RuleId = keyValue;
                codeRuleEntity.ModifyDate = DateTime.Now;
                codeRuleEntity.ModifyUserId = _auth.GetUserId();
                codeRuleEntity.ModifyUserName = _auth.GetUserName();
                await base.Repository.UpdateAsync(codeRuleEntity);
            }
            else
            {
                codeRuleEntity.RuleId = Guid.NewGuid().ToString();
                codeRuleEntity.CreateDate = DateTime.Now;
                codeRuleEntity.DeleteMark = 0;
                codeRuleEntity.EnabledMark = 1;
                codeRuleEntity.CreateUserId = _auth.GetUserId();
                codeRuleEntity.CreateUserName = _auth.GetUserName();
                await base.Repository.InsertAsync(codeRuleEntity);
            }
        }

        /// <summary>
        /// 规则实体
        /// </summary>
        /// <param name="enCode">规则编码</param>
        /// <returns></returns>
        public Task<SysCodeRule> GetEntityByCode(string enCode)
        {
            return base.Repository.GetFirstAsync(t => t.EnabledMark == 1 && t.DeleteMark == 0 && t.EnCode == enCode);
        }
        #endregion
        #region 单据编码处理
        /// <summary>
        /// 获取当前编码规则流程号值
        /// </summary>
        /// <param name="ruleId"></param>
        /// <param name="initValue"></param>
        /// <param name="stepNum"></param>
        /// <param name="dateFormatStr"></param>
        /// <returns></returns>
        public async Task<int> GetSeedValue(string ruleId, int initValue, int stepNum, string dateFormatStr)
        {
            int value = 0;
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                var codeRuleSeed = await base.Repository.ChangeRepository<SugarRepositiry<SysCodeRuleSeed>>().GetFirstAsync(t => t.RuleId == ruleId);
                if (codeRuleSeed == null)
                {
                    //说明没有种子，插入一条种子
                    codeRuleSeed = new SysCodeRuleSeed();
                    codeRuleSeed.RuleSeedId = Guid.NewGuid().ToString();
                    codeRuleSeed.CreateDate = DateTime.Now;
                    codeRuleSeed.ModifyDate = DateTime.Now;
                    codeRuleSeed.SeedValue = initValue;
                    codeRuleSeed.RuleId = ruleId;

                    value = (int)codeRuleSeed.SeedValue;
                    codeRuleSeed.SeedValue += stepNum;

                    await db.SysCodeRuleSeed.InsertAsync(codeRuleSeed);
                }
                else
                {
                    if (dateFormatStr.Contains("dd"))
                    {
                        if ((codeRuleSeed.ModifyDate).ToDateString() != DateTime.Now.ToString("yyyy-MM-dd"))
                        {
                            codeRuleSeed.SeedValue = initValue;
                        }
                    }
                    else if (dateFormatStr.Contains("mm"))
                    {
                        if (((DateTime)codeRuleSeed.ModifyDate).ToString("yyyy-MM") != DateTime.Now.ToString("yyyy-MM"))
                        {
                            codeRuleSeed.SeedValue = initValue;
                        }
                    }
                    else if (dateFormatStr.Contains("yy"))
                    {
                        if (((DateTime)codeRuleSeed.ModifyDate).ToString("yyyy") != DateTime.Now.ToString("yyyy"))
                        {
                            codeRuleSeed.SeedValue = initValue;
                        }
                    }
                    codeRuleSeed.ModifyDate = DateTime.Now;
                    value = (int)codeRuleSeed.SeedValue;

                    codeRuleSeed.SeedValue += stepNum;

                    await db.SysCodeRuleSeed.UpdateAsync(codeRuleSeed);
                }
                db.Commit();
                return value; 
            }

        }
        #endregion
    }
}
