using CloudBuilder.Core.DatabaseAccessor.Entity;
using CloudBuilder.Core.DependencyInjection.EFCore;
using CloudBuilder.Core.Policy;
using CloudBuilder.Core.Service;
using DocumentFormat.OpenXml.Math;
using DocumentFormat.OpenXml.Vml.Office;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.JsonWebTokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CloudBuilder.Core.DatabaseAccessor
{
    public class MasterDbContext : DbContext
    {
        public const string MASTER_DB_CONTEXT = "MasterDbContext";

        public IEnumerable<IMasterRegistEntityType<ModelBuilder>> _entityManagers;
        private readonly IServiceProvider _serviceProvider;
        private readonly IConfiguration configuration;
        private readonly IHttpContextAccessor httpContextAccessor;

        public MasterDbContext(DbContextOptions<MasterDbContext> options,
            IEnumerable<IMasterRegistEntityType<ModelBuilder>> entityManagers,
            IServiceProvider serviceProvider,
            IConfiguration configuration,
            IHttpContextAccessor httpContextAccessor
            ) : base(options)
        {
            _entityManagers = entityManagers;
            _serviceProvider = serviceProvider;
            this.configuration = configuration;
            this.httpContextAccessor = httpContextAccessor;
        }

        public override int SaveChanges(bool acceptAllChangesOnSuccess)
        {
            try
            {
                SavingChangesEvent();
                return base.SaveChanges(acceptAllChangesOnSuccess);
            }
            catch (Exception ex)
            {
                //自动检验数据是否过时
                //ALTER TABLE table ADD row_version rowversion;
                //[Column("row_version")]
                //[Timestamp]
                //public byte[] RowVersion { get; set; }
                if (ex.Message.Contains("data may have been modified or deleted since entities were loaded."))
                {
                    throw new ValidatedException(CoreMessagePolicy.GetInstance().ComposeMessage(CoreMessagePolicy.THE_DATA_HAS_BEEN_MODIFIED));
                }
                throw new ValidatedException(ex.InnerException?.Message ?? ex.Message);
            }

        }

        public void SavingChangesEvent()
        {
            var entities = this.ChangeTracker.Entries()
                  .Where(u => (u.State == EntityState.Modified || u.State == EntityState.Deleted || u.State == EntityState.Added)).ToList();
            if (entities == null || entities.Count < 1) return;

            string uid = this.httpContextAccessor.HttpContext?.User?.Identity?.Name;

            DateTime now = DateTime.Now;
            if (string.IsNullOrEmpty(uid))
            {
                uid = GetUserIdFromToken(httpContextAccessor.HttpContext!);
            }

            foreach (var entity in entities)
            {              
                if (!(entity.State == EntityState.Added || entity.State == EntityState.Modified)) continue;

                // 获取所有实体有效属性，排除 [NotMapper] 属性
                var props = entity.OriginalValues.Properties;

                // 获取实体当前（现在）的值
                var currentValues = entity.CurrentValues;

                // 遍历所有属性
                foreach (var prop in props)
                {
                    // 获取属性名
                    var propName = prop.Name;
                    if (propName == IEntityAudited.CREATED_BY && entity.State == EntityState.Added)
                    {
                        currentValues[propName] = uid;
                        continue;
                    }

                    if (propName == IEntityAudited.CREATED_DATETIME && entity.State == EntityState.Added)
                    {
                        currentValues[propName] = DateTime.Now;
                        continue;
                    }

                    if (propName == IEntityAudited.UPDATED_BY)
                    {
                        currentValues[propName] = uid;
                        continue;
                    }

                    if (propName == IEntityAudited.UPDATED_DATETIME)
                    {
                        currentValues[propName] = DateTime.Now;
                        continue;
                    }
                }
            }

            foreach (var entity in entities)
            {
                var entityName = entity.Metadata.GetTableName() ?? entity.Entity.GetType().Name;
                var state = entity.State;

                // ======================================
                // 1. 获取所有主键（支持复合主键）
                // ======================================
                var pkProps = entity.Properties
                    .Where(p => p.Metadata.IsPrimaryKey())
                    .ToList();

                // 拼接 WHERE 条件：Id=1 AND TenantId=2
                var whereClauses = pkProps
                    .Select(p => $"{p.Metadata.GetColumnName()?? p.Metadata.Name} = '{p.CurrentValue?.ToString()?.Replace("'", "''")}'");
                string whereSql = string.Join(" AND ", whereClauses);

                string sqlLog = "";

                // ======================================
                // 修改 UPDATE
                // ======================================
                if (state == EntityState.Modified)
                {
                    var setClauses = entity.Properties
                        .Where(p => p.IsModified) // 只记录真正修改的字段
                        .Select(p => $"{p.Metadata.GetColumnName() ?? p.Metadata.Name} = '{p.CurrentValue?.ToString()?.Replace("'", "''")}'");

                    string setSql = string.Join(", ", setClauses);
                    sqlLog = $"[{uid}][{now.ToString("yyyy-MM-dd HH:mm:ss")}]UPDATE {entityName} SET {setSql} WHERE {whereSql}";
                }

                // ======================================
                // 新增 INSERT
                // ======================================
                else if (state == EntityState.Added)
                {
                    var data = entity.Properties.ToDictionary(p => p.Metadata.GetColumnName() ?? p.Metadata.Name, p => p.CurrentValue);
                    var columns = string.Join(", ", data.Keys);
                    var values = string.Join(", ", data.Values.Select(v => $"'{v?.ToString()?.Replace("'", "''")}'"));
                    sqlLog = $"[{uid}][{now.ToString("yyyy-MM-dd HH:mm:ss")}]INSERT INTO {entityName} ({columns}) VALUES ({values})";
                }

                // ======================================
                // 删除 DELETE
                // ======================================
                else if (state == EntityState.Deleted)
                {
                    sqlLog = $"[{uid}][{now.ToString("yyyy-MM-dd HH:mm:ss")}]DELETE FROM {entityName} WHERE {whereSql}";
                }

                WriteToFile(sqlLog);
            }
        }

        private void WriteToFile(string log)
        {
            try
            {
                long MaxFileSizeBytes = (long)(configuration.GetValue<int>("Logging:MaxFileSizeMB") * 1024 * 1024);

                string today = DateTime.Now.ToString("yyyyMMdd");
                string basePath = configuration["Logging:LogFileDirectory"];
                Directory.CreateDirectory(basePath);

                string baseFileName = $"log-{today}";
                string ext = ".log";
                string finalPath = Path.Combine(basePath, $"{baseFileName}{ext}");
                int index = 1;

                // 循环找没超过大小的文件
                while (File.Exists(finalPath) && new FileInfo(finalPath).Length >= MaxFileSizeBytes)
                {
                    finalPath = Path.Combine(basePath, $"{baseFileName}-{index}{ext}");
                    index++;
                }

                // 写入（线程安全）
                lock (this)
                {
                    File.AppendAllText(finalPath, log + Environment.NewLine, Encoding.UTF8);
                }
            }
            catch { }
        }


        protected override void OnModelCreating(ModelBuilder builder)
        {
            foreach (IMasterRegistEntityType<ModelBuilder> entityManager in _entityManagers)
            {
                entityManager.RegistEntity(builder);
            }

            base.OnModelCreating(builder);
        }

        public string GetJwtBearerToken(HttpContext httpContext, string headerKey = "Authorization", string tokenPrefix = "Bearer ")
        {
            if (httpContext == null) return null;
            // 判断请求报文头中是否有 "Authorization" 报文头
            var bearerToken = httpContext.Request.Headers[headerKey].ToString();
            if (string.IsNullOrWhiteSpace(bearerToken)) return default;

            var prefixLenght = tokenPrefix.Length;
            return bearerToken.StartsWith(tokenPrefix, true, null) && bearerToken.Length > prefixLenght ? bearerToken[prefixLenght..] : default;
        }

        public string GetUserIdFromToken(HttpContext httpContext)
        {
            string token = GetJwtBearerToken(httpContextAccessor.HttpContext!);
            if (!string.IsNullOrEmpty(token))
            {
                try
                {
                    JsonWebToken json = new JsonWebTokenHandler().ReadJsonWebToken(token);
                    return json.GetClaim(ClaimPolicy.CLAINM_USERID).Value;
                }
                catch (Exception)
                {
                    return string.Empty;
                }
            }

            return string.Empty;
        }
    }
}
