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

namespace solarApp.Service
{
    /// <summary>
    /// 電站原始資料 rawData
    /// </summary>
    public class getStationSvc
    {
        string Connection1 = "";
        public getStationSvc(string Connection_parame = null)
        {
            if (!string.IsNullOrEmpty(Connection_parame))
            {
                Connection1 = Connection_parame;
            }
            else
            {
                Connection1 = ConfigurationManager.ConnectionStrings["mySql"].ConnectionString;
            }

        }
        //string Connection1 = ConfigurationManager.ConnectionStrings["mySql"].ConnectionString;
        protected string tableName = "power_station";
        /// <summary>
        /// 電站 Raw Data
        /// </summary>
        /// <param name="reportDate"></param>
        /// <param name="siteDB"></param>
        /// <param name="siteID"></param>
        /// <returns></returns>
        public List<raw_statino> get_station_raw(string reportDate, string siteDB, string siteID)
        {
            List<raw_statino> ds;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open();
                string sql = @"select id , FROM_UNIXTIME(`TIMESTAMP`/1000,'%Y-%m-%d %H:%i') reportdate,  siteid, round(KWH, 3) KWH, round(TODAYKWH, 3) TODAYKWH,  
					round(TOTALKWH, 3)TOTALKWH,   round(PR, 3) PR, round(SOLARHOUR, 3) SOLARHOUR  ,  round(kwhkwp, 3) kwhkwp , insertTime
	                    from " + siteDB + ".s" + siteID + @"_station  
	                    where  FROM_UNIXTIME(`TIMESTAMP`/1000,'%Y-%m-%d') =  @reportDate";
                try
                {
                    ds = conn.Query<raw_statino>(sql, new { reportDate = reportDate }).AsList<raw_statino>();
                    conn.Close();
                }
                catch (Exception ex)
                {
                    throw ex;
                } 
                return ds;
            }
        }
        #region 全區使用的 view
        public List<raw_station_day> create_v_station_inv(string date1, string date2)
        {
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open();
                string sql = @"	select siteid, left(reportdate, 10) reportdate, round((sum(KWH)), 2) KWH, round((max(TODAYKWH)), 2) TODAYKWH, round((max(TOTALKWH)), 2) TOTALKWH,
				                          round((max(PR)), 2) PR,  round((max(SOLARHOUR)), 2) SOLARHOUR, round((max(KWHKWP)), 2) KWHKWP, count(*) count
		                        from v_station_temp  
		                        where left(reportdate, 10) between @date1 and @date2
                                group by  siteid, left(reportdate, 10)";
                List<raw_station_day> ds = conn.Query<raw_station_day>(sql, new { date1 = date1, date2 = date2 }).AsList<raw_station_day>();
                conn.Close();
                return ds;
            }
        }

        #endregion
        /// <summary>
        /// 電站每天平均 from RawData
        /// </summary>
        /// <param name="date1"></param>
        /// <param name="date2"></param>
        /// <returns></returns>
        public List<raw_station_day> get_station_rawAvg(string date1, string date2, string siteDB, string siteID)
        {
            List<raw_station_day> ds;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open();
                //string sql = @"	select siteid, left(reportdate, 10) reportdate, round((sum(KWH)), 2) KWH, round((max(TODAYKWH)), 2) TODAYKWH, round((max(TOTALKWH)), 2) TOTALKWH,
				            //              round((max(PR)), 2) PR,  round((max(SOLARHOUR)), 2) SOLARHOUR, round((max(KWHKWP)), 2) KWHKWP, count(*) count
		              //          from v_station_temp  
		              //          where left(reportdate, 10) between @date1 and @date2
                //                group by  siteid, left(reportdate, 10)";
                string sql = @"	select siteid,  FROM_UNIXTIME(`TIMESTAMP`/1000,'%Y-%m-%d') reportdate, round((sum(KWH)), 2) KWH, round((max(TODAYKWH)), 2) TODAYKWH, round((max(TOTALKWH)), 2) TOTALKWH,
				                          round((max(PR)), 2) PR,  round((max(SOLARHOUR)), 2) SOLARHOUR, round((max(KWHKWP)), 2) KWHKWP, count(*) count
		                        from " + siteDB+ ".s"+ siteID + @"_station  
		                        where  FROM_UNIXTIME(`TIMESTAMP`/1000,'%Y-%m-%d') between @date1 and @date2
                                group by  siteid,  FROM_UNIXTIME(`TIMESTAMP`/1000,'%Y-%m-%d')";
                try
                {
                    ds = conn.Query<raw_station_day>(sql, new { date1 = date1, date2 = date2 }).AsList<raw_station_day>();
                    conn.Close();
                }
                catch (Exception ex)
                {
                    throw ex;
                } 
                
                return ds;
            }
        }

        

        /// <summary>
        /// web 呈現值 station - hour
        /// </summary>
        /// <param name="reportDate"></param>
        /// <returns></returns>
        public List<web_station_hour> get_web_station_hour(string reportDate, string siteID)
        {
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open();
                string sql = @" select DATE_FORMAT(`TIMESTAMP`,'%Y-%m-%d %H') reportdate, siteid, round(KWH, 2) KWH, 
                                    round(TODAYKWH, 2) TODAYKWH, round(TOTALKWH, 2) TOTALKWH, round(solarHour, 2) SOLARHOUR,
				                    round(PR, 3) PR, round(KWHKWP, 3) KWHKWP, 
                                    round(money, 3) money,   round(todaymoney, 3) todaymoney,   round(totalmoney, 3) totalmoney,
                                    round(carbon, 3) carbon, round(todayCarbon, 3) todayCarbon, round(totalCarbon, 3) totalCarbon
                                from power_station_history_hour 
                                where siteID = @siteID and left(`TIMESTAMP`, 10) = '" + reportDate + "' ";
                List<web_station_hour> ds = conn.Query<web_station_hour>(sql, new { siteID = siteID.Substring(0, 9) }).AsList<web_station_hour>();
                conn.Close();
                return ds;
            }
        }

        /// <summary>
        /// web 呈現值 station - day
        /// </summary>
        /// <param name="reportDate"></param>
        /// <param name="invID"></param>
        /// <returns></returns>
        public List<web_station_day> get_web_station_day(string date1, string date2, string siteID)
        {
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open();
                //string sql = @" 
                //                select DATE_FORMAT(`TIMESTAMP`,'%Y-%m-%d') reportdate, siteid, round(TODAYKWH, 2) TODAYKWH, round(TOTALKWH, 2) TOTALKWH,
                //            round(PR, 3) PR, round(KWHKWP, 3) KWHKWP, money
                //               from power_station_history_day where left(`TIMESTAMP`, 10) between @date1 and @date2 and siteid = @siteID";
                string sql = @"
		 select DATE_FORMAT(`TIMESTAMP`,'%Y-%m-%d') reportdate, a.siteid, round(TODAYKWH, 2) TODAYKWH, round(TOTALKWH, 2) TOTALKWH, round(solarHour, 2) SOLARHOUR,
						round(PR, 3) PR, round(KWHKWP, 3) KWHKWP, money, count
		 from power_station_history_day a left join (
						select DATE_FORMAT(`TIMESTAMP`,'%Y-%m-%d') reportdate, SITEID, count(*) count
						from power_station_history_hour
						where  siteid =  @siteID and  left(`TIMESTAMP`, 10) between  @date1 and @date2
						group by DATE_FORMAT(`TIMESTAMP`,'%Y-%m-%d'), SITEID
			) b on a.SITEID = b.SITEID and DATE_FORMAT(a.`TIMESTAMP`,'%Y-%m-%d')  = b.reportdate
		 where left(`TIMESTAMP`, 10) between  @date1 and @date2  and a.siteid = @siteID
         order by DATE_FORMAT(`TIMESTAMP`,'%Y-%m-%d')
 ";
                List<web_station_day> ds = conn.Query<web_station_day>(sql, new { date1 = date1, date2 = date2 , siteID = siteID}).AsList<web_station_day>();
                conn.Close();
                return ds;
            }
        }

        public List<web_station_day> get_web_station_month(string date1, string date2, string siteID)
        {
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open();
                string sql = @" select DATE_FORMAT(`TIMESTAMP`,'%Y-%m-%d') reportdate, siteid, round(TOTALKWH, 2) TOTALKWH,	round(solarHour, 2) SOLARHOUR, round(PR, 3) PR, round(KWHKWP, 3) KWHKWP, money
                               from power_station_history_month where left(`TIMESTAMP`, 7) between @date1 and @date2 and siteid = @siteID";
                List<web_station_day> ds = conn.Query<web_station_day>(sql, new { date1 = date1, date2 = date2, siteID = siteID }).AsList<web_station_day>();
                conn.Close();
                return ds;
            }
        }

        /// <summary>
        /// 取得電站資訊
        /// </summary>
        /// <returns></returns>
        public List<station_list> get_station_list()
        {
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open(); //                                                              01 控制器編號
                string sql = @" select id, CompanyId, `code` , SerialNumber, CONCAT(`code` ,'01') SiteID, SiteDB, `name` SiteName 
                                from power_station 
                                where deleted = 0 and `status`= 1";
// id <> 14";and id > 24
                List<station_list> ds = conn.Query<station_list>(sql).AsList<station_list>();
                conn.Close();
                return ds;
            }
        }
        public List<PowerStation> get_powerStation()
        {
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open();  
                string sql = @" select *
                                from power_station 
                                where deleted = 0 and `status`= 1";
                List<PowerStation> ds = conn.Query<PowerStation>(sql, commandTimeout: 600).AsList<PowerStation>();
                conn.Close();
                return ds;
            }
        }
        public List<lackData> get_lack_stationData(string reportDate)
        {
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open(); //   a.powerstationid, p.`code` SITEID, a.`TIMESTAMP` , TODAYKWH, TOTALKWH , b.Irradiance, b.EnvTemperature, b.irrDay 
                string sql = @"select  a.powerstationid, p.`code` SITEID, left(a.`TIMESTAMP`, 10) `TIMESTAMP`, b.TODAYKWH, b.TOTALKWH 
	                         from sensor_history_hour a 
	                        left join (
							                select powerstationid, left(`TIMESTAMP`, 10) `TIMESTAMP` , TODAYKWH, TOTALKWH from power_station_history_hour  
							                where   left(`TIMESTAMP`, 7) = @reportDate and hour(`TIMESTAMP`) = 12
						              ) b on a.powerstationid = b.powerstationid and left(a.`TIMESTAMP`, 10) = b.`TIMESTAMP`
                            join power_station p on a.powerstationid = p.id		
	                        where  left(a.`TIMESTAMP`, 7) = @reportDate and hour(a.`TIMESTAMP`) = 12 and b.TODAYKWH is null
	                        order by 1, 2 ";
                List<lackData> ds = conn.Query<lackData>(sql, new { reportDate = reportDate.Substring(0, 7) }, commandTimeout: 300).AsList<lackData>();
                  
                conn.Close(); 
                return ds;
            }
        }

        public string ExistTable(string db_name, string table_name)
        {
            string result;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                try
                {
                    var sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = @DBName AND TABLE_NAME = @TableName;";

                    result = conn.QueryFirstOrDefault<string>(sql, new { DBName = db_name, TableName = table_name }, commandTimeout: 600);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return result;
            }
        }

        public PowerStationHistory GetPowerStationHistoryPerHour(string dateTime, string table_name)
        {
            PowerStationHistory result;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                try
                {
                    var sql = $@"
                    SELECT 
                    DATE_FORMAT(FROM_UNIXTIME(timestamp / 1000), '%Y-%m-%d %H') AS TIMESTAMP,
                    SITEID,
                    SiteType,
                    KWH,
                    TodayKWh,
                    TotalKWH,
                    KWHKWP,
                    PR,
                    MP,
                    SolarHour
                    FROM {table_name} WHERE DATE_FORMAT(FROM_UNIXTIME(timestamp / 1000), '%Y-%m-%d %H') = @DateTime
                    ";

                    result =  conn.QueryFirstOrDefault<PowerStationHistory>(sql, new { DateTime = dateTime }, commandTimeout: 600);//加上時間
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public PowerStationHistory GetPowerStationHistoryPerHourForPowerStation(string dateTime, string table_name)
        {
            PowerStationHistory result;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                try
                {
                    var sql = $@"
                    SELECT  
                    DATE_FORMAT(FROM_UNIXTIME(timestamp / 1000), '%Y-%m-%d %H') AS TIMESTAMP,
                    SITEID, SiteType,  KWH,  TodayKWh, TotalKWH,
                    KWHKWP,  PR,   MP, SolarHour
                    FROM {table_name}
                    WHERE DATE_FORMAT(FROM_UNIXTIME(timestamp / 1000), '%Y-%m-%d') = @DateTime
                    AND kwh > 0
                    order by timestamp desc";

                    result = conn.QueryFirstOrDefault<PowerStationHistory>(sql, new { DateTime = dateTime }, commandTimeout: 600);//加上時間
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 透過電站編號，取得所有土地房屋資訊
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public List<LandBuilding> GetAllLandBuildingInfoByPowerStationId(int id, string db_name)
        {
            List<LandBuilding> result;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                try
                {
                    var sql = @$"SELECT lb.*, u.Name AS CreatorName FROM {db_name}.land_building lb
                                LEFT JOIN user u ON lb.CreatedBy = u.Id
                                WHERE lb.Deleted = 0 AND PowerStationId = @PowerStationId";

                    result = (conn.Query<LandBuilding>(sql, new { PowerStationId = id }, commandTimeout: 600)).AsList<LandBuilding>();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 透過name，取得單一設定變數
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public string GetOneVariableByName(string name)
        {
            string result;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                try
                {
                    var sql = $"SELECT Value FROM variable WHERE Name = @Name";

                    result = conn.QueryFirstOrDefault<string>(sql, new { Name = name }, commandTimeout: 600);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public int UpdateList(List<PowerStation> entity, List<string> properties)
        {
            int count;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateUpdateQuery(properties);

                        count = conn.Execute(sql, entity, trans, commandTimeout: 600);

                        trans.Commit();
                    }
                    catch (Exception exception)
                    {
                        trans.Rollback();
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }

                return count;
            }
        }

        /// <summary>
        /// 產生Update語句
        /// </summary>
        /// <param name="properties"></param>
        /// <returns></returns>
        protected string GenerateUpdateQuery(List<string> properties)
        {
            var updateQuery = new StringBuilder($"UPDATE {tableName} SET ");

            properties.ForEach(property =>
            {
                if (!property.Equals("Id"))
                {
                    updateQuery.Append($"{property}=@{property},");
                }
            });

            updateQuery.Remove(updateQuery.Length - 1, 1); //remove last comma
            updateQuery.Append(" WHERE id = @Id");

            return updateQuery.ToString();
        }

        public List<DeviceInfo> GetListPyrheliometerByPowerStationId(int powerStationId, string db_name)
        {
            List<DeviceInfo> result;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                try
                {
                    var sql = $@"SELECT temp.*
                                FROM(
                                SELECT d.* 
                                    FROM {db_name}.device d 
                                    WHERE d.PowerStationId = @PowerStationId AND d.`Type` = 'TPY' AND d.Deleted = 0 AND d.Enabled = 1 AND d.Status != 0
                                 UNION
                                 SELECT d.* 
                                    FROM {db_name}.sharedevice sd 
                                    LEFT JOIN {db_name}.device d ON sd.DeviceId = d.Id
                                    WHERE sd.PowerStationId = @PowerStationId AND d.`Type` = 'TPY' AND d.Deleted = 0 AND d.Enabled = 1 AND d.Status != 0
                                ) temp
                                ORDER BY temp.ColName
                    ";

                    result = (conn.Query<DeviceInfo>(sql, new { PowerStationId = powerStationId }, commandTimeout: 600)).AsList<DeviceInfo>();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public PyrheliometerHistory CalcSensorHistoryPerHour(string dateTime, List<DeviceInfo> deviceInfos, int type)
        {
            SensorTypeEnum SensorTypeEnum = (SensorTypeEnum)type;
            var typename = "";
            var calc = "";
            switch (SensorTypeEnum)
            {
                case SensorTypeEnum.PYR: //日照計
                    calc = "AVG";
                    typename = "Irradiance";
                    break;
                case SensorTypeEnum.MTR: //模組溫度計
                    calc = "AVG";
                    typename = "Temperature";
                    break;
                case SensorTypeEnum.ETR: //環境溫度計
                    calc = "AVG";
                    typename = "EnvTemperature";
                    break;
                case SensorTypeEnum.EMM: //環境濕度計
                    calc = "AVG";
                    typename = "Humidity";
                    break;
                case SensorTypeEnum.VAN: //風速計
                    calc = "AVG";
                    typename = "Vane";
                    break;
                case SensorTypeEnum.FOM: //落塵計
                    calc = "AVG";
                    typename = "Dust";
                    break;
                case SensorTypeEnum.WIN: //風向計
                    calc = "AVG";
                    typename = "WingDirection";
                    break;
                case SensorTypeEnum.TPY: //累計日照量
                    calc = "MAX";
                    typename = "IrrDay";
                    break;
            }

            PyrheliometerHistory result;
            using (MySqlConnection conn = new MySqlConnection(Connection1))
            {
                try
                {
                    List<string> sql_per_device = new List<string>();

                    foreach (var device in deviceInfos)
                    {
                        var str = @$"SELECT DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/ 1000), '%Y-%m-%d %H') AS TIMESTAMP, s.SITEID, CASE WHEN AVG(CASE WHEN s.{device.ColName} != 0 THEN s.{device.ColName} END) IS NOT NULL THEN AVG(CASE WHEN s.{device.ColName} != 0 THEN s.{device.ColName} END)
                                                                                                                                      ELSE 0 END AS SENSOR
                                    FROM {device.DBName}.{device.TableName} s 
                                    WHERE DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/ 1000), '%Y-%m-%d %H') = @DateTime
                                    GROUP BY DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/ 1000), '%Y-%m-%d %H')";

                        sql_per_device.Add(str);
                    }

                    var sql = @$"SELECT a.TIMESTAMP, {calc}(a.SENSOR) AS {typename} FROM(" + string.Join(" UNION ", sql_per_device) + @") a GROUP BY `TIMESTAMP`";

                    result = conn.QueryFirstOrDefault<PyrheliometerHistory>(sql, new { DateTime = dateTime }, commandTimeout: 600);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return result;
            }
        }

    }
}
