using System;
using System.Collections.Generic;
using System.Text;
using MySql.Data.MySqlClient;
using Dapper;
using solarApp.Model;
using System.Configuration;

namespace solarApp.Service
{
    public class procSyncError
    {
        string Connection1 = string.Empty;

        public procSyncError(string Connection_parame = null)
        {
            if (!string.IsNullOrEmpty(Connection_parame))
            {
                Connection1 = Connection_parame;
            }
            else
            {
                Connection1 = ConfigurationManager.ConnectionStrings["mySql"].ConnectionString;
            }
        }

        public bool syncErrData()
        {
            bool result = false;
            procArchiveLog arclog = new procArchiveLog();
            try
            {
                using (MySqlConnection conn = new MySqlConnection(Connection1))
                {
                    DateTime dt_start = DateTime.Now;
                    conn.Open();
                    #region 更新 Normal time
                    dt_start = DateTime.Now;
                    //string sql = $@" update`err_main` a join alarmorion_orionalarmrecord b on a.id = b.id  set 
                    //              a.`sourcestate` = b.`sourcestate`, 
                    //              a.`ackstate` = b.`ackstate`,  
                    //              a.`priority` = b.`priority`, 
                    //              a.`normaltime` = b.`normaltime`, 
                    //              a.`acktime` = b.`acktime`,  
                    //              a.`lastupdate` = b.`lastupdate` 
                    //              where   b.datestamp >= '{ System.DateTime.Now.AddDays(-60).ToString("yyyy-MM-dd")}'";// and  a.site_id is not null "; //  ;";
                    string ss = $@" update`err_main` a join alarmorion_orionalarmrecord b on a.id = b.id  set 
                                          a.`sourcestate` = b.`sourcestate`, 
                                          a.`ackstate` = b.`ackstate`,  
                                          a.`priority` = b.`priority`, 
                                          a.`normaltime` = b.`normaltime`, 
                                          a.`acktime` = b.`acktime`,  
                                          a.`lastupdate` = b.`lastupdate` 
                                     where   FROM_UNIXTIME(b.normaltime/1000, '%Y-%m-%d') >=  '{ System.DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd")}'";
                    int rowCount = conn.Execute(ss, commandTimeout: 600); 
                    TimeSpan durationSec = DateTime.Now - dt_start;
                    arclog.insert_log("0", "syncError s0 normaltime", durationSec.TotalSeconds, "orionAlarmRecord", "err_main", "0", "", rowCount.ToString(), conn, null);

                    #endregion

                    #region 取得尚未同步的異常資料               
                    ss = $@" select max(id) new_id,  (select max(id) old_id from err_main ) old_id
	                          from alarmorion_orionalarmrecord ";
                    var ds_max = conn.Query<max_id>(ss, commandTimeout: 600).AsList<max_id>();

                    if (ds_max.Count == 0 ) return false; // 查無資料
                    if (ds_max[0].new_id == ds_max[0].old_id) return true; // 無新資料

                    ss = $@" select * from alarmorion_orionalarmrecord 
                                    where id > {ds_max[0].old_id}";
                                    // and datestamp >= '{System.DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd")}'";
                    //sql = $@"select * from err_main 
		                  //   where site_id is null and datestamp >= '{System.DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd")}'";
                    var ds = conn.Query<errMain_model>(ss, commandTimeout: 600).AsList<errMain_model>();
                    StringBuilder sb = new StringBuilder();
                    bool isfirst = true;
                    foreach (var item in ds)
                    {
                        if (isfirst)
                        {
                            isfirst = false;
                            sb.Append(item.id);
                        }
                        else {
                            sb.Append($", {item.id}");
                        }
                    }
                    #endregion
                    if (ds.Count > 0)
                    {
                        #region 新增異常值 err_main
                        string sql = "";
                        string sql_header = "INSERT INTO `err_main`(`id`, `timestamp`, `datestamp`, `uuidHash`, `uuid`, `isOpen`, `sourceState`, `ackState`, `ackRequired`, `alarmClass`, `priority`, `normalTime`, `ackTime`, `userAccount`, `alarmTransition`, `lastUpdate`) ";
                        foreach (var item in ds)
                        { // //{item.uuidHash}, '{Convert.ToBase64String(item.uuid)}'
                            sql += sql_header + $@" VALUES ({item.id}, {item.timestamp}, '{DateTime.Parse(item.datestamp).ToString("yyyy-MM-dd")}', 0, 0 
                                                , {item.isOpen}, {item.sourceState}, {item.ackState}, {item.ackRequired}, {item.alarmClass}, {item.priority}, {item.normalTime}, {item.ackTime}  
                                                , '{item.userAccount}', {item.alarmTransition}, {item.lastUpdate}); ";
                        }
                        int rowCT = conn.Execute(sql, commandTimeout: 600);
                        TimeSpan duration = DateTime.Now - dt_start;
                        arclog.insert_log("0", "syncError s1", duration.TotalSeconds, "orionAlarmRecord", "err_main", "0", "", rowCT.ToString(), conn, null);
                        #endregion 

                        #region update site_id, inverterID 異常值 不用改
                        dt_start = DateTime.Now;
                        sql = $@"update err_main a join alarmorion_orionalarmfacetvalue b on a.id = b.alarm 
				                set		err_valuekind = left(`value`, 1), 
 							                   errValue = SUBSTRING_INDEX(  
 											                  SUBSTRING_INDEX(`value`, '@', 1) # @前面所有string --> e:7
 											                  , ':', -1)
                                where facetName =   4    and alarm in ({sb.ToString()});";
                        rowCT = conn.Execute(sql, commandTimeout: 600);
                        duration = DateTime.Now - dt_start;
                        arclog.insert_log("0", "syncError s2 errValue", duration.TotalSeconds, "facetvalue4", "err_main", "0", "", rowCT.ToString(), conn, null);
                        #endregion


                        #region update site_id, device_id ； 電站編號、設備編號 不用改
                        dt_start = DateTime.Now;
                        sql = $@"update err_main a join alarmorion_orionalarmfacetvalue b on a.id = b.alarm 
						            set err_valuekind = left(`value`, 1), 
						                errDevice = SUBSTRING_INDEX(SUBSTRING_INDEX(`value`, ':', -1) # : 後面所有string
																		     ,'S', -1), 
                                        a.site_id = substring(
										                    SUBSTRING_INDEX(SUBSTRING_INDEX(`value`, ':', -1) # : 後面所有string
																		                         ,'S', -1)
										                     , 1, 9) 
		                            where facetName =   8    and a.site_id is null and  a.datestamp >= '{System.DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd")}';";
                        rowCT = conn.Execute(sql, commandTimeout: 600);
                        duration = DateTime.Now - dt_start;
                        arclog.insert_log("0", "syncError s3 errDevice", duration.TotalSeconds, "facetValue8", "err_main", "0", "", rowCT.ToString(), conn, null);

                        #endregion

                        //          #region update 設備廠牌
                        //          dt_start = DateTime.Now;
                        //          sql = $@"update err_main a join v_company_inv b on a.errDevice = b.INVERTERID  set  
                        //errDeviceBrand = b.brand, 
                        //errDeviceModel = b.Model
                        //             where errDevice is not null and  datestamp >= '{System.DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd")}';";
                        //          rowCT = conn.Execute(sql, commandTimeout: 600);
                        //          duration = DateTime.Now - dt_start;
                        //          arclog.insert_log("0", "syncError s4 site_id", duration.TotalSeconds, "v_company_inv", "err_main", "0", "", rowCT.ToString(), conn, null);
                        //          #endregion

                        #region update 異常訊息
                            sql = $@" update err_main a join alarmorion_orionalarmfacetvalue b on a.id = b.alarm 
                                            set a.errMsg = b.errMsg
                                    where facetName =   6    and   alarm in ({sb.ToString()});";
                            rowCT = conn.Execute(sql, commandTimeout: 600);
                            duration = DateTime.Now - dt_start;
                            arclog.insert_log("0", "syncError s4 errMsg", duration.TotalSeconds, "facetvalue", "err_main", "0", "", rowCT.ToString(), conn, null);
                        #endregion

                        #region 更新全部的燈號
                        dt_start = DateTime.Now;
                        sql = $@"DROP TABLE IF EXISTS `temp_healthStatus`;
                                create table temp_healthStatus 
                                select v.siteName, z.* from (
				                                select ROW_NUMBER() OVER (PARTITION BY site_id ORDER BY HealthStatus desc) row_num, 
							                                 site_id, alarmID, datestamp, HealthStatus
				                                from (
								                                select site_id, datestamp, sourceState, id alarmID,
												                                case when alarmClass  = 14 then 3 # Network 控制盒斷線 - 紅燈
														                             when alarmClass != 14 then 2 end HealthStatus # inv, sensor 異常 黃燈 
								                                from err_main 
								                                where sourceState = 1 and left(site_id , 1) = '0'
                                                                      and datestamp > '{ System.DateTime.Now.AddDays(-60).ToString("yyyy-MM-dd")}' 
								                                order by HealthStatus desc
								                                limit 100
							                                ) x 
			                                )z join v_station v on z.site_id = v.siteid
                                where row_num = 1;";
                        conn.Execute(sql, commandTimeout: 600);
                   

                        sql = $@"update power_station set healthstatus = 1;
                                 update power_station a join temp_healthstatus b on a.code = b.site_id 
                                 set a.healthstatus = b.healthstatus;";
                        rowCT = conn.Execute(sql, commandTimeout: 600);
                        duration = DateTime.Now - dt_start;
                        arclog.insert_log("0", "syncError s5 site health", duration.TotalSeconds, "temp_healthstatus", "err_main", "0", "", rowCT.ToString(), conn, null);

                        #endregion

                        #region 更新 Inverter 燈號
                        dt_start = DateTime.Now;
                        sql = $@"update inv_status set status = 1;
                                 update inv_status a join 
                                 (
	                                 select errDevice, 2 errStatus 
	                                 from err_main -- 有資料 = 異常
	                                 where sourceState = 1 and left(errDevice, 1) = '0'
	                                 group by errDevice
                                 )b on a.inverterid = b.errDevice
                                 set status = errStatus;";
                        rowCT = conn.Execute(sql, commandTimeout: 600);
                        duration = DateTime.Now - dt_start;
                        arclog.insert_log("0", "syncError s6 inv health", duration.TotalSeconds, "", "err_main", "0", "", rowCT.ToString(), conn, null);

                        #endregion
                    }
                    conn.Close();
                }
                result = true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }

        public List<ExceptionEmailInfo> QueryExceptionData()
        {
            try
            {
                using (MySqlConnection conn = new MySqlConnection(Connection1))
                {
                    conn.Open();
                    string sql = $@"SELECT a.`*`,
                                        case priority when 1 then dev_time
			                                 when 2 then DATE_ADD(dev_time, INTERVAL 12 HOUR)  
				                             when 3 then DATE_ADD(dev_time, INTERVAL 24 HOUR)  
                                        else dev_time end  emailTime
                                 FROM
                                  ( 
		 	                            select pr.FormId as FormId, pr.Id as ErrorID, priority, a.id, site_id, `timestamp`, a.sourceState,
		 	                            FROM_UNIXTIME((`timestamp` / 1000), '%Y-%m-%d %H:%i:%s') dev_time ,  
		 				                             a.sourceState err_status, FROM_UNIXTIME( (a.normalTime / 1000), '%Y-%m-%d %H:%i:%s') normalTime,
		 				                             a.alarmClass, b.alarmClass_zh as alarmClassName,ps.Name as PowerStationName, ps.Id as PowerStationId,errDevice,  err_valueKind,  errValue, 
		 				                             FROM_UNIXTIME( (a.lastUpdate / 1000), '%Y-%m-%d %H:%i:%s')  lastUpdate,  
		 				                            a.errMsg  
		 	                            from err_main a 
		 		                            left join alarmorion_orionalarmclass b on a.alarmclass = b.id  
		 		                            left join power_station ps on ps.`Code` = site_id 
		 		                            left join operation_record pr on pr.ErrorCode = a.id
		 	                            where sourceState = 1 and datestamp >  '{System.DateTime.Now.AddDays(-30).ToString("yyyy-MM-dd")}'  and  ps.`Code` is not null  
                                    ) a 
                             order by a.id desc limit 1000";
         //           string sql = $@"SELECT a.`*`,
         //                           case priority when 1 then DATE_ADD(dev_time, INTERVAL 24 HOUR) 
									//		  when 2 then DATE_ADD(dev_time, INTERVAL 12 HOUR)  
         //                                     else dev_time end  emailTime
         //                           FROM
         //                       ( 
									//select pr.FormId as FormId, pr.Id as ErrorID, priority, a.id, site_id, `timestamp`, a.sourceState,
									//FROM_UNIXTIME((`timestamp` / 1000), '%Y-%m-%d %H:%i:%s') dev_time ,  
									//			 a.sourceState err_status, FROM_UNIXTIME( (a.normalTime / 1000), '%Y-%m-%d %H:%i:%s') normalTime,
									//			 a.alarmClass, b.alarmClass_zh as alarmClassName,ps.Name as PowerStationName, ps.Id as PowerStationId,errDevice,  err_valueKind,  errValue, 
									//			 FROM_UNIXTIME( (a.lastUpdate / 1000), '%Y-%m-%d %H:%i:%s')  lastUpdate, c.errMsg_tw cerrMsg_tw, d.errMsg_tw derrMsg_tw,
									//			case when c.errMsg_tw is null then 
									//						case when err_valueKind = 'b' then d.errMsg_tw 
									//								 when err_valueKind = 'd'	then CONCAT(d.errMsg_tw, ': ', round(a.errValue, 2))  
									//								 when d.errMsg_tw is null then a.errValue
									//								 when a.errValue is null then d.errMsg_tw
									//								 else CONCAT(a.errValue, ', ' , ifNull(d.errMsg_tw, ''))  end 
									//				 else 
									//						case when err_valueKind = 'b' then c.errMsg_tw 
									//								 when err_valueKind = 'd'	then CONCAT(c.errMsg_tw, ': ', round(a.errValue, 2)) 
									//								 when c.errMsg_tw is null then a.errValue
									//								 when a.errValue is null then c.errMsg_tw
									//								 else CONCAT(a.errValue, ', ' , ifNull(c.errMsg_tw, '')) end   
									//				 end errMsg 
									//				 #, a.errDeviceBrand , d.brend , a.errDeviceModel, d.model , a.errValue , d.errCode
									//from err_main a 
									//	left join alarmorion_orionalarmclass b on a.alarmclass = b.id 
									//	left join ref_err_device c on trim(b.alarmClass) = c.deviceType 
									//	left join ref_err_inv d on lower(b.alarmClass) = d.deviceType 
									//			and a.errDeviceBrand = d.brend and a.errDeviceModel = d.model and a.errValue = d.errCode
									//	left join power_station ps on ps.`Code` = site_id 
									//	left join operation_record pr on pr.ErrorCode = a.id
									//where sourceState = 1 and datestamp > '{System.DateTime.Now.AddDays(-60).ToString("yyyy-MM-dd")}'  and  ps.`Code` is not null  
         //                     ) a 
         //                   order by a.id desc limit 1000";
                    List<ExceptionEmailInfo> ds = conn.Query<ExceptionEmailInfo>(sql, commandTimeout: 600).AsList<ExceptionEmailInfo>();
                    conn.Close();
                    return ds;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<NoticeInfo> QueryNoticeData()
        {
            try
            {
                using (MySqlConnection conn = new MySqlConnection(Connection1))
                {
                    conn.Open();
                    string sql = $@"select * from notice_schedule order by 1 desc limit 1000";
                    List<NoticeInfo> ds = conn.Query<NoticeInfo>(sql, commandTimeout: 600).AsList<NoticeInfo>();
                    conn.Close();
                    return ds;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public List<AlarmorionInfo> QueryAlarmorion_orionalarmrecordData()
        {
            try
            {
                using (MySqlConnection conn = new MySqlConnection(Connection1))
                {
                    conn.Open();
                    string sql = $@"select a.*, FROM_UNIXTIME((a.`timestamp` / 1000), '%Y-%m-%d %H:%i:%s') timestamp2 
                                    from alarmorion_orionalarmrecord a
                                    order by 1 desc limit 1000";
                    List<AlarmorionInfo> ds = conn.Query<AlarmorionInfo>(sql, commandTimeout: 600).AsList<AlarmorionInfo>();
                    conn.Close();
                    return ds;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

    }
}
