using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Globalization;
using System.Threading;

namespace Aitex.Core.RT.DBCore
{
    public class DataBaseCleanerManager
    {
        private List<string> tableNames = new List<string>();

        private int _daysOfRetainData = 90;

        private DateTime _dateDataKeepTo;

        private PeriodicJob _monitorJob;

        public void Initialize()
        {
            _monitorJob = new PeriodicJob(3600 * 1000 * 10, OnTimer, "CleanDataBase", true);
            
        }

        private bool OnTimer()
        {
            if (SC.GetValue<bool>("System.EnableDataBaseClean"))
            {
                _daysOfRetainData = SC.GetValue<int>("System.DataKeepDays");

                _dateDataKeepTo = DateTime.Now.AddDays(-_daysOfRetainData);

                CleanData();
            }
            return true;
        }

        public bool CleanData()
        {
            try
            {
                DeviceTimer deviceTimer = new DeviceTimer();

                string[,] array = new string[5, 2]
                {
                    { "carrier_data", "load_time" },
                    { "event_data", "occur_time" },
                    { "process_data", "process_begin_time" },
                    { "wafer_data", "create_time" },
                    { "wafer_move_history", "arrive_time" }
                };

                for (int i = 0; i < array.GetLength(0); i++)
                {
                    string sql = $"select count(*) from information_schema.columns where table_schema='public' and table_name ='{array[i, 0]}' and  column_name='{array[i, 1]}'";
                    int num = Convert.ToInt32(DB.ExecuteScalar(sql));
                    if (num == 1)
                    {
                        deviceTimer.Start(300000.0);
                        sql = string.Format($"delete from \"{array[i, 0]}\" where \"{array[i, 1]}\" <= '{_dateDataKeepTo.ToString("yyyy/MM/dd HH:mm:ss.fff")}'");
                        if (DB.ExecuteNonQuery(sql) > 0)
                        {
                            LOG.Info($"当前日期为{DateTime.Now.ToString("D")},删除{_daysOfRetainData}天前的数据表{array[i, 0]}," +
                            $"用时{deviceTimer.GetElapseTime() / 1000.0}秒");
                        }

                        Thread.Sleep(50);
                    }
                }

                tableNames.Clear();
                GetTableNames();
                if (tableNames.Count == 0)
                {
                    return true;
                }
                foreach (string tableName in tableNames)
                {
                    deviceTimer.Start(300000.0);
                    DB.ExecuteNonQuery($"drop table \"{tableName}\"");
                    LOG.Info($"当前日期为{DateTime.Now.ToString("D")},删除{_daysOfRetainData}天前的数据表{tableName}," +
                        $"用时{deviceTimer.GetElapseTime() / 1000.0}秒");
                    Thread.Sleep(50);
                }
            }
            catch (Exception ex)
            {
                LOG.Error(ex.Message);
            }
            return true;
        }

        public void GetTableNames()
        {
            try
            {
                string cmdText = "select tablename from pg_tables where schemaname='public' and tablename like '20%' order by tablename asc";
                DbDataReader dataReader = DB.ExecuteReader(cmdText);
                while (dataReader.Read())
                {
                    for (int i = 0; i < dataReader.FieldCount; i++)
                    {
                        string text = dataReader[i].ToString();
                        text = text.Substring(0, 8);
                        if (DateTime.ParseExact(text, "yyyyMMdd", CultureInfo.InvariantCulture) <= _dateDataKeepTo)
                        {
                            tableNames.Add(dataReader[i].ToString());
                        }
                    }
                }
                dataReader.Close();
                dataReader.Dispose();
            }
            catch (Exception ex)
            {
                LOG.Error(ex.Message);
            }
        }

        public void Terminate()
        {

        }
    }
}
