using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SqlSugar
{
    public class MySqlCodeFirst : CodeFirstProvider
    {
        public override void NoExistLogic(EntityInfo entityInfo)
        {
            var tableName = GetTableName(entityInfo);
            //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1");
            List<DbColumnInfo> columns = new List<DbColumnInfo>();
            if (entityInfo.Columns.HasValue())
            {
                foreach (var item in entityInfo.Columns.OrderBy(it => it.IsPrimarykey ? 0 : 1))
                {
                    if (item.IsIgnore)
                        continue;
                    if (item.PropertyInfo!=null&&UtilMethods.GetUnderType(item.PropertyInfo.PropertyType) == UtilConstants.GuidType && item.Length == 0&&item.DataType==null)
                    {
                        item.Length = Guid.NewGuid().ToString().Length;
                    }
                    DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item);
                    columns.Add(dbColumnInfo);
                }
                if (entityInfo.IsCreateTableFiledSort)
                {
                    columns = columns.OrderBy(c => c.CreateTableFieldSort).ToList();
                    columns = columns.OrderBy(it => it.IsPrimarykey ? 0 : 1).ToList();
                }
            }
            this.Context.DbMaintenance.CreateTable(tableName, columns,true);
        }
        protected override DbColumnInfo EntityColumnToDbColumn(EntityInfo entityInfo, string tableName, EntityColumnInfo item)
        {
            var propertyType = UtilMethods.GetUnderType(item.PropertyInfo);
            var result = new DbColumnInfo()
            {
                TableId = entityInfo.Columns.IndexOf(item),
                DbColumnName = item.DbColumnName.HasValue() ? item.DbColumnName : item.PropertyName,
                IsPrimarykey = item.IsPrimarykey,
                IsIdentity = item.IsIdentity,
                TableName = tableName,
                IsNullable = item.IsNullable,
                DefaultValue = item.DefaultValue,
                ColumnDescription = item.ColumnDescription,
                Length = item.Length,
                DecimalDigits=item.DecimalDigits,
                CreateTableFieldSort = item.CreateTableFieldSort
            };
            GetDbType(item, propertyType, result);
            if (result.DataType.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.Length == 0)
            {
                result.Length = 1;
            }
            return result;
        }

        protected override void ConvertColumns(List<DbColumnInfo> dbColumns)
        {
            foreach (var item in dbColumns)
            {
                if (item.DataType == "DateTime")
                {
                    item.Length = 0;
                }
            }
        }

        protected override void ChangeKey(EntityInfo entityInfo, string tableName, EntityColumnInfo item)
        {
            this.Context.DbMaintenance.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
            if (!item.IsPrimarykey)
                this.Context.DbMaintenance.DropConstraint(tableName,null);
            if (item.IsPrimarykey)
                this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName);
        }

        internal DbColumnInfo GetEntityColumnToDbColumn(EntityInfo entity, string dbTableName, EntityColumnInfo item)
        {
            return EntityColumnToDbColumn(entity,dbTableName,item);
        }

        protected override void GetDbType(EntityColumnInfo item, Type propertyType, DbColumnInfo result)
        {
            if (!string.IsNullOrEmpty(item.DataType))
            {
                result.DataType = item.DataType;
            }
            else if (propertyType.IsEnum())
            {
                result.DataType = this.Context.Ado.DbBind.GetDbTypeName(item.Length > 9 ? UtilConstants.LongType.Name : UtilConstants.IntType.Name);
            }
            else if (item.IsJson && item.DataType == null)
            {
                result.DataType = "json";
            }
            else if (propertyType == UtilConstants.DecType&&item.Length==0&&item.DecimalDigits==0) 
            {
                result.Length = 18;
                result.DecimalDigits = 4;
                result.DataType = "decimal";
            }
            else
            {
                var name = GetType(propertyType.Name);
                if (name == "Boolean")
                {
                    result.DataType = "tinyint";
                    result.Length = 1;
                    result.Scale = 0;
                    result.DecimalDigits = 0;
                }
                else
                {
                    result.DataType = this.Context.Ado.DbBind.GetDbTypeName(name);
                    if (name == "Guid" && result.DataType == "varchar"&&result.Length<=1) 
                    {
                        result.Length = 36;
                    }
                }
            }
        }


        protected override bool IsNoSamgeType(EntityColumnInfo ec, DbColumnInfo dc)
        {
            if (ec.UnderType==UtilConstants.BoolType && dc.DataType == "tinyint" && dc.Length == 1)
            {
                return false;
            }
            else if (ec.UnderType == UtilConstants.DobType && dc.DataType== "double")
            {
                return false;
            }
            else if (ec.UnderType == UtilConstants.DateType && dc.DataType?.StartsWith("datetime")==true)
            {
                return false;
            }
            return base.IsNoSamgeType(ec, dc);
        }
    }
}
