using Dapper;
using SolarPower.Helper;
using SolarPower.Models;
using SolarPower.Models.PowerStation;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace SolarPower.Repository.Implement
{
    public class OverviewRepository : RepositoryBase<Overview>, IOverviewRepository
    {
        public OverviewRepository(IDatabaseHelper databaseHelper) : base(databaseHelper)
        {
            tableName = "power_station";
        }

        public async Task<List<int>> GetAllCityIdAsync()
        {
            List<int> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT Id FROM city";

                    result = (await conn.QueryAsync<int>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<Overview> GetOverviewByPowerStationIds(List<int> powerStationIds)
        {
            Overview result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT
                                    SUM(ps.Today_kwh) AS Today_kwh,
                                    SUM(ps.Total_kwh) AS Total_kwh,
                                    AVG(ps.Today_irradiance) AS today_irradiance,
                                    AVG(ps.avg_irradiance) AS avg_irradiance,
                                    AVG(ps.today_PR) AS today_PR,
                                    AVG(ps.avg_PR) AS avg_PR,
                                    AVG(ps.today_kwhkwp) AS today_kwhkwp,
                                    AVG(ps.avg_kwhkwp) AS avg_kwhkwp,
                                    SUM(ps.today_money) AS today_money,
                                    SUM(ps.total_money) AS total_money,
                                    SUM(ps.today_carbon) AS today_carbon,
                                    SUM(ps.total_carbon) AS total_carbon
                                    FROM power_station ps
                                    WHERE ps.Id IN @PowerStationIds
                                ";

                    result = await conn.QueryFirstOrDefaultAsync<Overview>(sql, new { PowerStationIds = powerStationIds });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }

        }

        public async Task<List<CapacityDataTable>> GetCapacityDataTableByPowerStationIds(List<int> powerStationIds)
        {
            List<CapacityDataTable> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT 
                                    ps.CityId,
                                    c.Name AS CityName,
                                    COUNT(*) AS SubPowerStationCount,
                                    SUM(ps.GeneratingCapacity) AS SubTotalCapacity
                                    FROM power_station ps
                                    LEFT JOIN city c ON ps.CityId = c.Id
                                    WHERE ps.Id IN @PowerStationIds
                                    GROUP BY ps.CityId
                                    ORDER BY c.Priority
                                ";

                    result = (await conn.QueryAsync<CapacityDataTable>(sql, new { PowerStationIds = powerStationIds })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<PowerStation>> GetListPowerStationByPowerStationIds(List<int> powerStationIds)
        {
            List<PowerStation> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var dateNow = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                    var sql = @$"SELECT 
                                wf.Wx,
                                ps.*
                                FROM power_station ps
                                LEFT JOIN city c ON ps.CityId = c.Id
                                LEFT JOIN (SELECT * FROM (
                                            SELECT MAX(w.Id) AS aa FROM weather_forecast w 
                                            WHERE w.StartTime < @DateNow AND w.EndTime > @DateNow 
                                            GROUP BY w.LocationName
                                            ) A
                                            LEFT JOIN weather_forecast B ON A.aa = B.Id) wf ON c.Name = wf.LocationName
                                WHERE ps.Id IN @PowerStationIds
                                ";

                    result = (await conn.QueryAsync<PowerStation>(sql, new { PowerStationIds = powerStationIds, DateNow = dateNow })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<PowerStation>> GetSolarByCity(MyUser User, UseStatusCityGetPowerStation post)
        {

            using IDbConnection conn = _databaseHelper.GetConnection();
            List<PowerStation> powerstation = new List<PowerStation>();
            conn.Open();
            var trans = conn.BeginTransaction();
            try
            {
                var ids = "";
                var KWH = "";
                var PR = "";
                if (post.KwhOrder == 0)
                {
                    KWH = " ORDER BY Today_kwh DESC";
                }
                else
                {
                    KWH = " ORDER BY Today_kwh";
                }

                if (post.PrOrder == 0)
                {
                    PR = ",today_PR DESC";
                }
                else
                {
                    PR = ",today_PR";
                }



                foreach (var id in post.Cityid)
                {
                    ids = ids + id + ",";
                }
                if (ids.Length != 0)
                {
                    ids = ids.Substring(0, ids.Length - 1);
                }
                if (User.Role.Layer == 0 || User.Role.Layer == 1)
                {
                    var sql = "SELECT * FROM power_station WHERE CityId IN @IDs AND HealthStatus IN @Status" + KWH + PR;
                    powerstation = (await conn.QueryAsync<PowerStation>(sql, new { IDs = post.Cityid, Status = post.Status })).ToList();
                    trans.Commit();
                }
                else if (User.Role.Layer == 2)
                {
                    var sql = "SELECT * FROM power_station WHERE CityId IN @IDs AND CompanyId=@CompanyId AND HealthStatus IN @Status" + KWH + PR;
                    powerstation = (await conn.QueryAsync<PowerStation>(sql, new { IDs = post.Cityid, CompanyId = User.CompanyId, Status = post.Status })).ToList();
                    trans.Commit();
                }
                else
                {
                    var sql = "SELECT power_station.* FROM power_station LEFT JOIN power_station_operation_personnel ON power_station.Id = power_station_operation_personnel.PowerStationId WHERE CityId IN @IDs AND Userid = @UserId AND HealthStatus IN @Status" + KWH + PR;
                    powerstation = (await conn.QueryAsync<PowerStation>(sql, new { IDs = post.Cityid, UserId = User.Id, Status = post.Status })).ToList();
                    trans.Commit();
                }
            }
            catch (Exception exception)
            {
                trans.Rollback();
                throw exception;
            }
            finally
            {
                conn.Close();
            }
            return powerstation;
        }

        public async Task<List<PowerIrradiance>> GetListPowerIrradianceTodayByPowerStationId(int powerStationId, string nowDay)
        {
            List<PowerIrradiance> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql_power = @$"SELECT DATE_FORMAT(ps.timestamp,'%H %p') AS Label, ps.KWH AS PowerData, pyr.IrrDayHour AS IrrDayHourData, pyr.Temperature AS TemperatureData
                            FROM power_station_history_hour ps 
                            LEFT JOIN sensor_history_hour pyr ON ps.PowerStationId = pyr.PowerStationId AND DATE_FORMAT(ps.timestamp, '%Y-%m-%d %H') = DATE_FORMAT(pyr.timestamp, '%Y-%m-%d %H')
                            WHERE ps.PowerStationId = @PowerStationId
                            AND DATE_FORMAT(ps.timestamp, '%Y-%m-%d') = @NowDay 
                            ORDER BY ps.timestamp";

                    result = (await conn.QueryAsync<PowerIrradiance>(sql_power, new { PowerStationId = powerStationId, NowDay = nowDay })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
        public async Task<List<PowerIrradiance>> GetListPowerIrradiance7dayByPowerStationId(int powerStationId, string nowDay)
        {
            List<PowerIrradiance> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var startDay = Convert.ToDateTime(nowDay).AddDays(-7).ToString("yyyy-MM-dd");

                    var sql_power = @$"SELECT DATE_FORMAT(ps.timestamp, '%Y-%m-%d') AS Label, ps.TODAYKWH AS PowerData, pyr.Irradiance AS IrradianceData, pyr.Temperature AS TemperatureData
                            FROM power_station_history_day ps 
                            LEFT JOIN sensor_history_day pyr ON ps.PowerStationId = pyr.PowerStationId AND DATE_FORMAT(ps.timestamp, '%Y-%m-%d') =  DATE_FORMAT(pyr.timestamp, '%Y-%m-%d')
                            WHERE ps.PowerStationId = @PowerStationId
                            AND DATE_FORMAT(ps.timestamp, '%Y-%m-%d') BETWEEN @StartDay AND @NowDay
                            ORDER BY ps.timestamp";

                    result = (await conn.QueryAsync<PowerIrradiance>(sql_power, new { PowerStationId = powerStationId, StartDay = startDay, NowDay = nowDay })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
        public async Task<List<PowerIrradiance>> GetListPowerIrradianceMonthByPowerStationId(int powerStationId, string nowDay)
        {
            List<PowerIrradiance> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var startDay = Convert.ToDateTime(nowDay).ToString("yyyy-MM-01");

                    var sql_power = @$"SELECT DATE_FORMAT(ps.timestamp, '%Y-%m-%d') AS Label, ps.TODAYKWH AS PowerData, pyr.Irradiance AS IrradianceData, pyr.Temperature AS TemperatureData
                            FROM power_station_history_day ps 
                            LEFT JOIN sensor_history_day pyr ON ps.PowerStationId = pyr.PowerStationId AND DATE_FORMAT(ps.timestamp, '%Y-%m-%d') = DATE_FORMAT(pyr.timestamp, '%Y-%m-%d')
                            WHERE ps.PowerStationId = @PowerStationId
                            AND DATE_FORMAT(ps.timestamp, '%Y-%m-%d') BETWEEN @StartDay AND @NowDay
                            ORDER BY ps.timestamp";

                    result = (await conn.QueryAsync<PowerIrradiance>(sql_power, new { PowerStationId = powerStationId, StartDay = startDay, NowDay = nowDay })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<PowerIrradiance>> GetListPowerIrradianceYearByPowerStationId(int powerStationId, string nowDay)
        {
            List<PowerIrradiance> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var startyear = Convert.ToDateTime(nowDay).ToString("yyyy");

                    var sql_power = @$"SELECT DATE_FORMAT(ps.timestamp, '%Y-%m') AS Label, ps.MONTHKWH AS PowerData, pyr.Irradiance AS IrradianceData, pyr.Temperature AS TemperatureData
                            FROM power_station_history_month ps 
                            LEFT JOIN sensor_history_month pyr ON ps.PowerStationId = pyr.PowerStationId AND DATE_FORMAT(ps.timestamp, '%Y-%m') = DATE_FORMAT(pyr.timestamp, '%Y-%m')
                            WHERE ps.PowerStationId = @PowerStationId
                            AND DATE_FORMAT(ps.timestamp, '%Y') = @Year
                            ORDER BY ps.timestamp";

                    result = (await conn.QueryAsync<PowerIrradiance>(sql_power, new { PowerStationId = powerStationId, Year = startyear })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<CheckBox>> GetInvertCheckBoxByPowerStationId(int powerStationId, string db_name)
        {
            List<CheckBox> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT i.Id AS Value, i.InverterName AS Name FROM {db_name}.inverter i
                                LEFT JOIN {db_name}.controller c ON i.ControllerId = c.Id AND c.Deleted = 0
                                WHERE i.Deleted = 0 AND c.PowerStationId = @PowerStationId order by i.Id ";

                    result = (await conn.QueryAsync<CheckBox>(sql, new { PowerStationId = powerStationId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<InverterHistory>> GetListInverterByPowerStationIdAndDate(int powerStationId, string dateTime)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    //var startDateTime = dateTime + " 05:00";
                    //var endDataTime = dateTime + " 19:00";

                    //var sql = @$"SELECT * FROM inverter_history_15min WHERE PowerStationId = @PowerStationId AND DATE_FORMAT(TIMESTAMP, '%Y-%m-%d %H:%i') BETWEEN @StartDateTime AND @EndDateTime";
                    var sql = @$"SELECT * FROM inverter_history_15min WHERE PowerStationId = @PowerStationId AND DATE_FORMAT(TIMESTAMP, '%Y-%m-%d') = @DateTime ORDER BY TIMESTAMP";

                    result = (await conn.QueryAsync<InverterHistory>(sql, new { PowerStationId = powerStationId, DateTime = dateTime })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<ExceptionDataTable>> GetExceptionTable(ExceptionSent post)
        { 
            List<ExceptionDataTable> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    DateTime start;
                    DateTime end;
                    var sql = @$"select pr.FormId as FormId, pr.Id as ErrorID, a.id, site_id, `timestamp`, 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, errDevice,  err_valueKind,  errValue, 
			                             FROM_UNIXTIME( (a.lastUpdate / 1000), '%Y-%m-%d %H:%i:%s')  lastUpdate,  
                                    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 a.sourceState = @Status AND ps.Id = @PowerStationId ";
                    //var sql = @$"select pr.FormId as FormId, pr.Id as ErrorID, a.id, site_id, `timestamp`, 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, 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
                    //                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 case when lower(b.alarmClass) = 'inverter' and err_valuekind = 'e' then errvalue else '' end = d.errCode
                    //                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 a.sourceState = @Status AND ps.Id = @PowerStationId ";

                    if (!string.IsNullOrEmpty(post.Range))
                    {
                        post.StartTime = post.Range.Split('-')[0] + " 00:00:00";
                        post.EndTime = post.Range.Split('-')[1] + " 23:59:59";
                        start = Convert.ToDateTime(post.StartTime).AddHours(-8);
                        end = Convert.ToDateTime(post.EndTime).AddHours(-8);
                        var startime = (Int64)(start.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
                        var endtime = (Int64)(end.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
                        sql += @$" AND `timestamp` BETWEEN {startime*1000} AND {endtime*1000}";
                    }


                    sql += " order by pr.Id ";

                    result = (await conn.QueryAsync<ExceptionDataTable>(sql,
                            new
                            {
                                PowerStationId = post.Id,
                                Status = post.Status,
                            }, commandTimeout: 600)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<ExceptionDataTable>> GetExceptionTable2(ExceptionSent2 post)
        {


            List<ExceptionDataTable> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    DateTime start;
                    DateTime end;
                    string sql = $@"
select pr.FormId as FormId, pr.Id as ErrorID, a.id, site_id, ps.Id PowerStationId, `timestamp`, 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, errDevice,  err_valueKind,  errValue, FROM_UNIXTIME( (a.lastUpdate / 1000), '%Y-%m-%d %H:%i:%s')  lastUpdate, a.errMsg
    from err_main a 
    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 a.sourceState = @Status AND ps.Id IN @PowerStationId";
                    //var sql = @$"select pr.FormId as FormId, pr.Id as ErrorID, a.id, site_id, ps.Id PowerStationId, `timestamp`, 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, 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
                    //                from err_main a 
                    //                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 case when lower(b.alarmClass) = 'inverter' and err_valuekind = 'e' then errvalue else '' end = d.errCode
                    //                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 a.sourceState = @Status AND ps.Id IN @PowerStationId";


                    if (!string.IsNullOrEmpty(post.Range))
                    {
                        post.StartTime = post.Range.Split('-')[0] + " 00:00:00";
                        post.EndTime = post.Range.Split('-')[1] + " 23:59:59";
                        start = Convert.ToDateTime(post.StartTime);
                        end = Convert.ToDateTime(post.EndTime);
                        var startime = (Int64)(start.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
                        var endtime = (Int64)(end.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
                        sql += @$" AND `timestamp` BETWEEN {startime * 1000} AND {endtime * 1000}";
                    }

                    sql += " order by pr.Id ";

                    result = (await conn.QueryAsync<ExceptionDataTable>(sql,
                            new
                            {
                                PowerStationId = post.Id,
                                Status = post.Status,
                            })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }


        public async Task<List<InverterHistory>> GetListInverterDayByPowerStationId(int powerStationId, string day)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql_power = @$"SELECT DATE_FORMAT(inv.TIMESTAMP, '%H %p') AS TIMESTAMP,
                                        inv.INVERTERID,
                                        inv.KWH
                                        FROM inverter_history_hour inv
                                        WHERE inv.PowerStationId = @PowerStationId
                                        AND DATE_FORMAT(inv.timestamp, '%Y-%m-%d') = @Day
                                        ORDER BY inv.INVERTERID, inv.TIMESTAMP";

                    result = (await conn.QueryAsync<InverterHistory>(sql_power, new { PowerStationId = powerStationId, Day = day })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<InverterHistory>> GetListInverterMonthByPowerStationId(int powerStationId, string month)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql_power = @$"SELECT DATE_FORMAT(inv.TIMESTAMP, '%Y-%m-%d') AS TIMESTAMP,
                                        inv.INVERTERID,
                                        inv.KWH
                                        FROM inverter_history_day inv
                                        WHERE inv.PowerStationId = @PowerStationId
                                        AND DATE_FORMAT(inv.timestamp, '%Y-%m') = @Month
                                        ORDER BY inv.INVERTERID, inv.TIMESTAMP";

                    result = (await conn.QueryAsync<InverterHistory>(sql_power, new { PowerStationId = powerStationId, Month = month })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<InverterHistory>> GetListInverterQuaryerlyByPowerStationId(int powerStationId, string startMonth, string endMonth)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql_power = @$"SELECT DATE_FORMAT(inv.TIMESTAMP, '%Y-%m') AS TIMESTAMP,
                                        inv.INVERTERID,
                                        inv.KWH
                                        FROM inverter_history_month inv
                                        WHERE inv.PowerStationId = @PowerStationId
                                        AND DATE_FORMAT(inv.timestamp, '%Y-%m') BETWEEN @StartMonth AND @EndMonth
                                        ORDER BY inv.INVERTERID, inv.TIMESTAMP";

                    result = (await conn.QueryAsync<InverterHistory>(sql_power, new { PowerStationId = powerStationId, StartMonth = startMonth, EndMonth = endMonth })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<InverterHistory>> GetListInverterYearByPowerStationId(int powerStationId, string year)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql_power = @$"SELECT DATE_FORMAT(inv.TIMESTAMP, '%Y-%m') AS TIMESTAMP,
                                        inv.INVERTERID,
                                        inv.KWH
                                        FROM inverter_history_month inv
                                        WHERE inv.PowerStationId = @PowerStationId
                                        AND DATE_FORMAT(inv.timestamp, '%Y') = @Year
                                        ORDER BY inv.INVERTERID, inv.TIMESTAMP";

                    result = (await conn.QueryAsync<InverterHistory>(sql_power, new { PowerStationId = powerStationId, Year = year })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 電站資訊 - history - 上方圖表與總計
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        public async Task<List<HistoryTable>> GethistoryTable(HistorySent post)
        {
            List<HistoryTable> result;

            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                var select = "";
                var kwh = "";
                var usedb = "";
                var pyrdb = "";
                var timeGroup = "";
                var range = "";
                var range2 = "";
                var out_group = "";
                switch (post.GroupType)
                {
                    case 0:
                        select = "*, SOLARHOUR-PSValue AS DiffSOLARHOUR";
                        kwh = "C.KWH";
                        usedb = "power_station_history_hour";
                        pyrdb = "sensor_history_hour";
                        timeGroup = "%Y-%m-%d %H:%M:%S";
                        range = $" WHERE DATE_FORMAT(V.TIMESTAMP,'%Y-%m-%d')  = '{post.HistoryRange}'";
                        range2 = $" AND DATE_FORMAT(c.TIMESTAMP,'%Y-%m-%d')  = '{post.HistoryRange}'";
                        
                        break;
                    case 1:
                        select = "*, SOLARHOUR-PSValue AS DiffSOLARHOUR";
                        kwh = "C.TODAYKWH";
                        usedb = "power_station_history_day";
                        pyrdb = "sensor_history_day";
                        timeGroup = "%Y-%m-%d";
                        //range = $" WHERE DATE_FORMAT(V.TIMESTAMP,'%Y-%m')  = '{post.HistoryRange}'";
                        range = $" and  DATE_FORMAT(c.TIMESTAMP,'%Y-%m')  = '{post.HistoryRange}'"; // edit by jiahao @2022-05-13
                        //range2 = $" DATE_FORMAT(C.TIMESTAMP,'%Y-%m')  = '{post.HistoryRange}'";

                        break;
                    case 2:
                        select = "*, SOLARHOUR-PSValue AS DiffSOLARHOUR";
                        kwh = "C.MONTHKWH";
                        usedb = "power_station_history_month";
                        pyrdb = "sensor_history_month";
                        timeGroup = "%Y-%m";
                        //range = $" WHERE DATE_FORMAT(V.TIMESTAMP,'%Y')  = '{post.HistoryRange}'";
                        range = $" and  DATE_FORMAT(c.TIMESTAMP,'%Y')  = '{post.HistoryRange}'"; // edit by jiahao @2022-05-13
                        //range2 = $" DATE_FORMAT(C.TIMESTAMP,'%Y')  = '{post.HistoryRange}'";
                        break;
                    case 3:
                        //select = "DATE_FORMAT(V.TIMESTAMP,'%Y') AS TIMESTAMP, MAX(KWH) AS KWH, SUM(SOLARHOUR) AS SOLARHOUR, SUM(SOLARHOUR-PSValue) AS DiffSOLARHOUR, AVG(PR) AS PR, AVG(Irradiance) AS Irradiance, AVG(Temp) AS Temp ,AVG(KWHKWP) AS KWHKWP ";
                        //kwh = "C.TOTALKWH";
                        //usedb = "power_station_history_month";
                        //pyrdb = "sensor_history_month";
                        //timeGroup = "%Y-%m";
                        //range = "";
                        //out_group = " GROUP BY DATE_FORMAT(V.TIMESTAMP,'%Y')";4
                        select = "DATE_FORMAT(c.TIMESTAMP,'%Y') AS TIMESTAMP, MAX(KWH) AS KWH, SUM(SOLARHOUR) AS SOLARHOUR, 0 AS DiffSOLARHOUR, AVG(PR) AS PR, AVG(Irradiance) AS Irradiance, AVG(Temp) AS Temp ,AVG(KWHKWP) AS KWHKWP ";
                        kwh = "C.TOTALKWH";
                        usedb = "power_station_history_month";
                        pyrdb = "sensor_history_month";
                        timeGroup = "%Y-%m";
                        range = "";
                        out_group = " GROUP BY DATE_FORMAT(V.TIMESTAMP,'%Y')";
                        break;
                }

               
                string sql = string.Empty;
                try
                {
                    switch (post.GroupType)
                    {
                        case 0:  // today - hour - 選擇同一天
                        case 4:  // date-range 選擇不同天
                            if (!string.IsNullOrEmpty(post.HistoryRange))
                            { 
                                    string d1 = post.HistoryRange.Substring(0, 10).Replace("/", "-");
                                    string d2 = post.HistoryRange.Substring(13, 10).Replace("/", "-");
                                    if (d1 == d2)
                                    { // range 查詢同一天
                                        range2 = @$" AND DATE_FORMAT(C.`TIMESTAMP`,'%Y-%m-%d')  BETWEEN '{ d1 }' AND '{ d2 }'";
                                        sql = $@"  SELECT  C.TIMESTAMP,  C.KWH AS KWH,C.SOLARHOUR, C.PR, 
                                                P.Irradiance, P.IrrDayHour, P.Temperature AS Temp , C.KWHKWP, P.IrrDay, 0 AS DiffSOLARHOUR,  C.PR avgPR
				                           FROM power_station_history_hour C 
				                           LEFT JOIN sensor_history_hour P  ON P.`TIMESTAMP` =C.`TIMESTAMP` AND P.PowerStationId = C.PowerStationId
					                           WHERE C.PowerStationId = {post.PowerstationId}{range2}  ";
                                    }
                                    else
                                    { // range 查詢不同天
                                      //string endDate = DateTime.Parse(d2).AddDays(1).ToString("yyyy-MM-dd");
                                        range = @$" AND DATE_FORMAT(C.`TIMESTAMP`,'%Y-%m-%d')  BETWEEN '{ d1 }' AND '{ d2 }'";

                                    //sql = $@" SELECT left(C.`TIMESTAMP`, 10) `TIMESTAMP`, C.TODAYKWH AS KWH, C.SOLARHOUR, C.PR, P.Irradiance, P.Temperature AS Temp ,C.KWHKWP, P.IrrDay, 0 AS DiffSOLARHOUR, C.PR avgPR
                                    //            FROM power_station_history_day C 
                                    //     LEFT JOIN sensor_history_day P ON DATE_FORMAT(P.TIMESTAMP, '%Y-%m-%d') = DATE_FORMAT(C.TIMESTAMP, '%Y-%m-%d') AND P.PowerStationId = C.PowerStationId
                                    //        join power_station_history_month m on DATE_FORMAT(P.TIMESTAMP, '%Y-%m') = DATE_FORMAT(m.TIMESTAMP, '%Y-%m') AND m.PowerStationId = C.PowerStationId
                                    //        WHERE C.PowerStationId = {post.PowerstationId}{range} order by C.TIMESTAMP";
                                    sql = $@" SELECT C.TIMESTAMP,  C.TODAYKWH AS KWH, C.SOLARHOUR, C.PR, P.Irradiance, P.IrrDayHour, P.Temperature AS Temp ,C.KWHKWP, P.IrrDay, 0 AS DiffSOLARHOUR, C.PR avgPR
			                                        FROM power_station_history_day C 
	                                            LEFT JOIN sensor_history_day P ON DATE_FORMAT(P.TIMESTAMP, '%Y-%m-%d') = DATE_FORMAT(C.TIMESTAMP, '%Y-%m-%d') AND P.PowerStationId = C.PowerStationId
                                                WHERE C.PowerStationId = {post.PowerstationId}{range} order by C.TIMESTAMP"; break; 
                                    }                
                            } 
                             break;
                        case 1: // day 沒有 dateRange - 月
                                        sql = $@" SELECT C.TIMESTAMP, {kwh} AS KWH, C.SOLARHOUR, C.PR, P.Irradiance, P.IrrDayHour, P.Temperature AS Temp ,C.KWHKWP, P.IrrDay, 0 AS DiffSOLARHOUR, C.PR avgPR
			                                        FROM {usedb} C 
	                                            LEFT JOIN {pyrdb} P ON DATE_FORMAT(P.TIMESTAMP, '%Y-%m-%d') = DATE_FORMAT(C.TIMESTAMP, '%Y-%m-%d') AND P.PowerStationId = C.PowerStationId
                                                WHERE C.PowerStationId = {post.PowerstationId}{range} order by C.TIMESTAMP"; break;
                        case 2: // month 單月
                                        //sql = $@" SELECT C.TIMESTAMP, C.MONTHKWH AS KWH, C.SOLARHOUR, C.PR, P.Irradiance, P.IrrDayHour, P.Temperature AS Temp ,C.KWHKWP, P.IrrDay, 0 AS DiffSOLARHOUR
			                                     //   FROM power_station_history_month C 
	                                       //     LEFT JOIN sensor_history_month P ON DATE_FORMAT(P.TIMESTAMP, '%Y-%m') = DATE_FORMAT(C.TIMESTAMP, '%Y-%m') AND P.PowerStationId = C.PowerStationId
                                        //        WHERE C.PowerStationId = {post.PowerstationId}{range}";
                            sql = $@"	SELECT C.TIMESTAMP, C.MONTHKWH AS KWH, C.SOLARHOUR, C.PR, P.Irradiance, P.IrrDayHour, P.Temperature AS Temp ,C.KWHKWP, P.IrrDay, 0 AS DiffSOLARHOUR, C.PR avgPR
			                            FROM power_station_history_month C 
			                            LEFT JOIN sensor_history_month P ON DATE_FORMAT(P.TIMESTAMP, '%Y-%m') = DATE_FORMAT(C.TIMESTAMP, '%Y-%m') AND P.PowerStationId = C.PowerStationId
				                            WHERE C.PowerStationId = {post.PowerstationId}{range}";
                            break;
                            
                        case 3: // year
                                //sql = $@"SELECT left(c.`TIMESTAMP`, 4) AS `TIMESTAMP`, round(avg(monthKWH), 3) AS KWH, SUM(SOLARHOUR) AS SOLARHOUR, 0 AS DiffSOLARHOUR, AVG(PR) AS PR,  round(AVG(KWHKWP), 3) AS KWHKWP 	  
                                //         FROM power_station_history_month C 
                                //         LEFT JOIN sensor_history_month P ON P.`TIMESTAMP` = C.`TIMESTAMP` AND P.PowerStationId = C.PowerStationId
                                //            WHERE C.PowerStationId = C.PowerStationId = {post.PowerstationId} 
                                //        GROUP BY left(c.`TIMESTAMP`, 4)  ORDER BY C.`TIMESTAMP` "; 
                                //sql = $@" SELECT left(c.`TIMESTAMP`, 4) AS `TIMESTAMP`, sum(monthKWH) AS KWH, SUM(SOLARHOUR) AS SOLARHOUR, 0 AS DiffSOLARHOUR, AVG(PR) AS PR, 
                                //        AVG(Irradiance) AS Irradiance, AVG(Temperature) AS Temp ,AVG(KWHKWP) AS KWHKWP 	  
                                //       FROM power_station_history_month C 
                                //       LEFT JOIN sensor_history_month P ON P.`TIMESTAMP` = C.`TIMESTAMP` AND P.PowerStationId = C.PowerStationId
                                //        WHERE C.PowerStationId = {post.PowerstationId} 
                                //    GROUP BY left(c.`TIMESTAMP`, 4)  ORDER BY C.`TIMESTAMP` "; 
                                sql = $@"select * from (          
                                          select left(c.`TIMESTAMP`, 4) AS `TIMESTAMP`, sum(monthKWH) AS KWH,  round(AVG(PR), 2) AS PR , round(AVG(PR), 2) AS avgPR   , 
                                        	          ifnull(avg( P.IrrDay), 0) irrDay, avg(P.Temperature) AS Temp, ps.GeneratingCapacity AS GeneratingCapacity
                                        	 FROM power_station_history_month C  
                                                  LEFT JOIN sensor_history_month P ON DATE_FORMAT(P.TIMESTAMP, '%Y-%M') = DATE_FORMAT(C.TIMESTAMP, '%Y-%M') AND P.PowerStationId = C.PowerStationId
                                                  LEFT JOIN power_station ps ON ps.id = C.PowerStationId
                                        	     WHERE C.PowerStationId = {post.PowerstationId}  
                                        	     group by left(c.`TIMESTAMP`, 4)   
                                        )x join 
                                        (
                                        		select year(timestamp) yyyy, count(*) days from sensor_history_day where PowerStationId = {post.PowerstationId}  group by year(timestamp)
                                        )y on x.`TIMESTAMP` = y.yyyy";
                            break;
                    }


                    //if (post.GroupType == 0)
                    //{
                      
                    //}
                    //else
                    //{
                    //    sql = $@" SELECT C.TIMESTAMP, {kwh} AS KWH, C.SOLARHOUR, C.PR, P.Irradiance, P.Temperature AS Temp ,C.KWHKWP, P.IrrDay, 0 AS DiffSOLARHOUR
			                 //               FROM {usedb} C 
	                   //                 LEFT JOIN {pyrdb} P ON DATE_FORMAT(P.TIMESTAMP,'{timeGroup}') = DATE_FORMAT(C.TIMESTAMP,'{timeGroup}') AND P.PowerStationId = C.PowerStationId
                    //                    WHERE C.PowerStationId = {post.PowerstationId}{range}";
                    //    /*
                    //     sql = @$"SELECT {select}
                    //            FROM
                    //            (
	                   //             SELECT B.*, IFNULL(A.SOLARHOUR,0) AS PSValue
	                   //             FROM 
	                   //             (	
		                  //              SELECT DENSE_RANK() OVER(ORDER BY C.TIMESTAMP) AS ROWID
			                 //               , (DENSE_RANK() OVER(ORDER BY C.TIMESTAMP)) - 1 AS PreROWID,
			                 //               C.TIMESTAMP,{kwh} AS KWH,C.SOLARHOUR,C.PR,P.Irradiance,P.Temperature AS Temp 
			                 //               FROM {usedb} C 
	                   //                 LEFT JOIN {pyrdb} P ON DATE_FORMAT(P.TIMESTAMP,'{timeGroup}') = DATE_FORMAT(C.TIMESTAMP,'{timeGroup}') AND P.PowerStationId = C.PowerStationId
                    //                    WHERE C.PowerStationId = {post.PowerstationId}{range2} GROUP BY C.TIMESTAMP ORDER BY C.TIMESTAMP
	                   //             ) A
	                   //             RIGHT OUTER JOIN 
	                   //             (
		                  //              SELECT DENSE_RANK() OVER(ORDER BY C.TIMESTAMP) AS ROWID
			                 //               , (DENSE_RANK() OVER(ORDER BY C.TIMESTAMP)) - 1 AS PreROWID,
			                 //               C.TIMESTAMP,{kwh} AS KWH,C.SOLARHOUR,C.PR,P.Irradiance,P.Temperature AS Temp ,C.KWHKWP,P.IrrDay 
			                 //               FROM {usedb} C 
	                   //                 LEFT JOIN {pyrdb} P ON DATE_FORMAT(P.TIMESTAMP,'{timeGroup}') = DATE_FORMAT(C.TIMESTAMP,'{timeGroup}') AND P.PowerStationId = C.PowerStationId
                    //                    WHERE C.PowerStationId = {post.PowerstationId}{range2} GROUP BY C.TIMESTAMP ORDER BY C.TIMESTAMP
	                   //             ) B
		                  //              ON A.ROWID = B.PreROWID
                    //            ) V {range} {out_group}";
                    //    */
                    //}
                    result = (await conn.QueryAsync<HistoryTable>(sql)).ToList();
                }
                 catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<ExceptionEmailInfo>> GetEmailExceptionList()
        {
            List<ExceptionEmailInfo> exceptionEmailInfos = new List<ExceptionEmailInfo>();
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    string sql = $@"SELECT a.`*`,ns.Id 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,
						                                     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 datestamp = '{DateTime.Now.ToString("yyyy-MM-dd")}' and  ps.`Code` is not null  and priority < 20
	                                     ) a  LEFT JOIN notice_schedule ns ON ns.ExceptionId = a.id 
                                    WHERE ns.Id IS NULL ";
         //           var sql = $@"
	        //                    SELECT a.`*`,ns.Id 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  ps.`Code` is not null  and priority < 20
         //                     ) a  LEFT JOIN notice_schedule ns ON ns.ExceptionId = a.id 
         //                   WHERE ns.Id IS NULL ";
                    exceptionEmailInfos = (await conn.QueryAsync<ExceptionEmailInfo>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
            };
            return exceptionEmailInfos;
        }

        public async Task<List<UserPowerStationTo>> GetUserListWithPowerstation(int id)
        {
            List<UserPowerStationTo> result = new List<UserPowerStationTo>();
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT u.Name,u.Email,u.Id FROM power_station_operation_personnel pss
                                LEFT JOIN user u ON u.Id = pss.UserId
                                WHERE pss.Deleted = 0 AND pss.EmailException = 1 AND pss.PowerStationId = {id} AND u.Deleted = 0 and  Email is not null";
                    result = (await conn.QueryAsync<UserPowerStationTo>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
            };
            return result;
        }

        public async Task<List<SolarTypeMoneys>> GetSolarTypeMoneys()
        {
            List<SolarTypeMoneys> result = new List<SolarTypeMoneys>();
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT 
                                    solartype, 
                                    sum(today_money) Today_money
                                    FROM power_station
                                    group by solartype
                                    order by solartype
                                ";
                    result = (await conn.QueryAsync<SolarTypeMoneys>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }

        }
    }
}
