using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using HealthMonitor.Util.Common;
using HealthMonitor.Util.Entities.Interfaces;

namespace HealthMonitor.Util.Entities.Base
{
	public abstract class EntityBase : IEntity
	{
		/// <summary>
		/// 获取全局(数据库内)唯一键
		/// </summary>
		/// <param name="key">需要赋予实体键的值,多个实体键赋予的值,用逗号分隔</param>
		/// <returns></returns>
		public string GetUniqueKey(string? key = null)
		{
			var type = this.GetType();

			if(EntityUtils.HasAutoGenerateKey(type))
			{
				return $"{type.Name}_{Guid.NewGuid()}";
			}

			if (!string.IsNullOrWhiteSpace(key)) AssignEntityKey(key);
			var propertyValues = type.GetProperties().Where(e => e.GetCustomAttributes(typeof(KeyAttribute), false).Length > 0)
				.Select(e => e.GetValue(this) + "");
			string str = $"{type.Name}_{string.Join("_", propertyValues)}";
			return str;
		}

		/// <summary>
		/// 获取全局(数据库内)唯一键(通过实体的主键创建,而不会创建随机键)
		/// </summary>
		/// <returns></returns>
		public string GetRequiredUniqueKey()
		{
			var type = this.GetType();

			var propertyValues = type.GetProperties().Where(e => e.GetCustomAttributes(typeof(KeyAttribute), false).Length > 0)
				.Select(e => e.GetValue(this) + "").ToList();
			if (propertyValues.Count() == 0 || (propertyValues[0] + "") == "0") throw new ArgumentException($"实体{type.Name}主键无效");

			string str = $"{type.Name}_{string.Join("_", propertyValues)}";
			return str;
		}

		/// <summary>
		/// 获取主键(数据表内唯一)
		/// </summary>
		/// <returns></returns>
		public string GetPrimaryKey()
		{
			var type = this.GetType();

			var propertyValues = type.GetProperties().Where(e => e.GetCustomAttributes(typeof(KeyAttribute), false).Length > 0)
				.Select(e => e.GetValue(this) + "");
			string str = string.Join("_", propertyValues);
			return str;
		}

		/// <summary>
		/// 为实体的键(标记了KeyAttribute)属性赋值
		/// </summary>
		/// <param name="key"></param>
		public virtual void AssignEntityKey(string key)
		{
			var type = this.GetType();

			try
			{
				var properties = type.GetProperties().Where(e => e.GetCustomAttributes(typeof(KeyAttribute), false).Length > 0);
				if (!string.IsNullOrWhiteSpace(key))
				{
					//为字段赋值
					var values = key.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
					if (properties.Count() == 1 || properties.Count() == values.Count())
					{
						int i = 0;
						foreach (var p in properties) p.SetValue(this, values[i]);
					}
				}
			}
			catch (Exception) { }
		}

		/// <summary>
		/// 断言实体各个字段值符合要求
		/// </summary>
		public void AssertValidate()
		{
			var type = this.GetType();
			var properties = type.GetProperties();

			var requiredProperties = properties.Where(e => e.GetCustomAttributes(typeof(RequiredAttribute), false).Length > 0).ToList();
			requiredProperties.ForEach(e =>
			{
				var value = e.GetValue(this);
				if (value == null)
				{
					//throw new ArgumentException($"字段{e.Name}值能为空");

					//赋默认值
					object? v = e.PropertyType.IsValueType ? Activator.CreateInstance(e.PropertyType) : string.Empty;
					e.SetValue(this, v);
				}
			});

			var limitedProperties = properties.Where(e => e.GetCustomAttributes(typeof(StringLengthAttribute), false).Length > 0).ToList();
			limitedProperties.ForEach(e =>
			{
				var attr = (e.GetCustomAttributes(typeof(StringLengthAttribute), false) as StringLengthAttribute[])![0];
				int max = attr.MaximumLength;
				int min = attr.MinimumLength;
				var strValue = e.GetValue(this) + "";
				if (strValue.Length > max || strValue.Length < min) throw new ArgumentException($"字段{e.Name}值长度大于{max},或者小于{min}");
			});
		}
	}
}