using System.Data;
using PowerEasy.WebFuture.DataMigrations.Foundation.Log;
using PowerEasy.WebFuture.DataMigrations.Foundation.MigrationProgramme;

namespace PowerEasy.WebFuture.DataMigrations.Foundation.Service
{
    /// <summary>
    /// 迁移项目通用基类。
    /// </summary>
    public abstract class BaseCommonDataMigrationItem : IMigrationItem
    {
        /// <summary>
        /// 构造函数。
        /// </summary>
        public BaseCommonDataMigrationItem()
        {
        }

        /// <summary>
        /// 模型名字。
        /// </summary>
        public abstract string ModelName { get; set; }

        /// <summary>
        /// 迁移项目的排序，用于执行和工具显示的顺序，从小到大排序。
        /// </summary>
        public abstract int Order { get; set; }

        /// <summary>
        /// 迁移项目名称。
        /// </summary>
        public abstract string MigrationItemName { get; set; }

        /// <summary>
        /// 目标数据库表名。
        /// </summary>
        public abstract string TargetDatabaseTableName { get; set; }

        /// <summary>
        /// 来源数据库表的主键名称。
        /// </summary>
        public abstract string SourcePrimaryKeyName { get; set; }

        /// <summary>
        /// 上传目录。
        /// </summary>
        public abstract string UploadPath { get; set; }

        /// <summary>
        /// 目标站点id。
        /// </summary>
        public abstract int SiteId { get; set; }

        /// <summary>
        /// 迁移项目是否勾选。
        /// </summary>
        public bool Enable { get; set; }

        /// <summary>
        /// 来源数据库表数据。
        /// </summary>
        public DataTable SourceDataTable { get; set; }

        /// <summary>
        /// 迁移方案标识。
        /// </summary>
        /// <remarks>
        /// 迁移项目的标识需要与迁移方案标识相同。
        /// 如果迁移项目跟迁移方案命名空间相同时，可不指定标识，系统会将命名空间作为标识。
        /// </remarks>
        public string MigrationProgrammeIdentifier
        {
            get
            {
                if (string.IsNullOrEmpty(this.MigrationProgrammeIdentifierString))
                {
                    this.MigrationProgrammeIdentifierString = this.GetType().Namespace;
                }

                return this.MigrationProgrammeIdentifierString;
            }

            set
            {
                this.MigrationProgrammeIdentifierString = value;
            }
        }

        /// <summary>
        /// 迁移方案标识。
        /// </summary>
        private string MigrationProgrammeIdentifierString { get; set; }

        /// <summary>
        /// 开始执行迁移项目。
        /// </summary>
        /// <param name="isCheckedIncremental">是否勾选增量迁移。</param>
        /// <returns>返回迁移结果。</returns>
        public virtual bool StartMigration(bool isCheckedIncremental)
        {
            LogHelper.BackgroundWorker.ReportProgress(0, $"{this.MigrationItemName}开始。");
            var status = this.StartInsert(isCheckedIncremental);
            LogHelper.BackgroundWorker.ReportProgress(100, $"{this.MigrationItemName}结束。");
            return status;
        }

        /// <summary>
        /// 获取批量插入的数据表。
        /// </summary>
        /// <returns>返回数据表。</returns>
        public virtual DataTable GetInsertDataTable()
        {
            var targetDatabaseProvider = DatabaseService.GetTargetDatabaseProvider(this.MigrationProgrammeIdentifier);

            // 获取新目标数据库对应迁移表的字段结构。
            var moldDataTable = new DataTable();
            var moldDataSql = targetDatabaseProvider.GetOneDataByTableName(this.TargetDatabaseTableName);
            moldDataTable = targetDatabaseProvider.ExecuteDataTable(moldDataSql);

            // 构建需要迁移的数据表。
            var migrationDataTable = new DataTable();
            migrationDataTable.TableName = this.TargetDatabaseTableName;
            for (int i = 0; i < moldDataTable.Columns.Count; i++)
            {
                migrationDataTable.Columns.Add(moldDataTable.Columns[i].ColumnName, moldDataTable.Columns[i].DataType);
            }

            foreach (DataRow moldRow in this.SourceDataTable.Rows)
            {
                // 下面进行数据库录入。
                DataRow newRow = migrationDataTable.NewRow();

                // 获取旧数据库和新数据库字段对应的行数据。
                var mold = this.MapFields(moldRow, newRow);
                migrationDataTable.Rows.Add(mold);
            }

            return migrationDataTable;
        }

        /// <summary>
        /// 获取来源要迁移的数据集合。
        /// </summary>
        /// <param name="newContentId">最新迁移的数据主键。</param>
        public abstract void LoadSourceDataTable(int newContentId);

        /// <summary>
        /// 字段映射。（没有赋值的属性都使用了model中的默认值，如果需要，请在本方法重新赋值。）
        /// </summary>
        /// <param name="sourceDataRow">源数据表行数据。</param>
        /// <param name="targetDataRow">目标数据表行数据。</param>
        /// <returns>返回映射后的行数据。</returns>
        public abstract DataRow MapFields(DataRow sourceDataRow, DataRow targetDataRow);

        /// <summary>
        /// 开始插入公共方法。
        /// </summary>
        /// <param name="isCheckedIncremental">是否勾选增量迁移。</param>
        /// <returns>返回执行结果。</returns>
        public virtual bool StartInsert(bool isCheckedIncremental)
        {
            return false;
        }
    }
}
