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

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


        public List<MyPowerStationSummary> GetMyPowerStationSummary(MyUser myUser, string filter = "")
        {
            List<MyPowerStationSummary> results = new List<MyPowerStationSummary>();

            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @"SELECT ps.Id, ps.CityId, c.Name AS CityName, ps.Name
                                FROM power_station ps 
                                LEFT JOIN city c ON ps.CityId = c.Id";

                    if (myUser.Role.Layer == 2)
                    {   //公司管理員
                        sql += @" WHERE ps.Deleted = 0 AND ps.CompanyId = @CompanyId";
                    }
                    else if (myUser.Role.Layer == 3)
                    {
                        sql += @" LEFT JOIN power_station_operation_personnel op ON ps.Id = op.PowerStationId
                                    WHERE ps.Deleted = 0 AND op.Deleted = 0 AND op.UserId = @UserId ";
                    }
                    else
                    {
                        sql += @" WHERE ps.Deleted = 0";
                    }

                    if (!string.IsNullOrEmpty(filter))
                    {
                        sql += @" AND ps.Name LIKE CONCAT('%', @Filter, '%')";
                    }

                    var myPowerStationInfos = conn.Query<MyPowerStationInfo>(sql, new { CompanyId = myUser.CompanyId, UserId = myUser.Id, Filter = filter }).ToList();

                    var myPowerStationInfos_group = myPowerStationInfos.GroupBy(x => x.CityId);

                    foreach (var myPowerStationInfo in myPowerStationInfos_group)
                    {
                        MyPowerStationSummary myPowerStationSummary = new MyPowerStationSummary();
                        myPowerStationSummary.CityName = myPowerStationInfo.First().CityName;
                        myPowerStationSummary.Amount = myPowerStationInfo.Count();
                        myPowerStationSummary.MyPowerStations = new List<MyPowerStation>();
                        foreach (var info in myPowerStationInfo)
                        {
                            MyPowerStation myPowerStation = new MyPowerStation();
                            myPowerStation.PowerStationId = info.Id;
                            myPowerStation.PowerStationName = info.Name;

                            myPowerStationSummary.MyPowerStations.Add(myPowerStation);
                        }

                        results.Add(myPowerStationSummary);
                    }

                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return results;
            }
        }

        /// <summary>
        /// 查詢縣市列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<CitySelectItemList>> GetCitySelectOptionListAsync()
        {
            List<CitySelectItemList> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT Id AS Value, Name AS Text FROM city";

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

        /// <summary>
        /// 查詢地區列表
        /// </summary>
        /// <param name="cityId"></param>
        /// <returns></returns>
        public async Task<List<AreaSelectItemList>> GetAreaSelectOptionListAsync(int cityId)
        {
            List<AreaSelectItemList> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT Id AS Value, Name AS Text FROM area WHERE CityId = @CityId";

                    result = (await conn.QueryAsync<AreaSelectItemList>(sql, new { CityId = cityId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 透過編號取得，縣市資訊
        /// </summary>
        /// <param name="cityId"></param>
        /// <returns></returns>
        public async Task<City> GetOneCityByIdAsync(int cityId)
        {
            City result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT * FROM city WHERE Id=@Id";

                    result = await conn.QueryFirstOrDefaultAsync<City>(sql, new { Id = cityId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 透過編號取得，地區資訊
        /// </summary>
        /// <param name="areaId"></param>
        /// <returns></returns>
        public async Task<Area> GetOneAreaByIdAsync(int areaId)
        {
            Area result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT * FROM area WHERE Id=@Id";

                    result = await conn.QueryFirstOrDefaultAsync<Area>(sql, new { Id = areaId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 透過地區編號，取得縣市地區代碼
        /// </summary>
        /// <param name="areaId"></param>
        /// <returns></returns>
        public async Task<Zipcode> GetCityAreaZipcodeAsync(int areaId)
        {
            Zipcode result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT a.ZipCode AS Area, c.ZipCode AS City FROM area a
                                    LEFT JOIN city c ON a.cityId = c.Id
                                    WHERE a.Id = @AreaId";

                    result = await conn.QueryFirstOrDefaultAsync<Zipcode>(sql, new { AreaId = areaId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 透過縣市地區編號，取得該縣市地區最後的流水號
        /// </summary>
        /// <param name="cityId"></param>
        /// <param name="areaId"></param>
        /// <returns></returns>
        public async Task<string> GetLastSerialNumberByCityAreaIdAsync(int cityId, int areaId)
        {
            string result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT SerialNumber FROM {tableName}
                                    WHERE CityId = @CityId && AreaId = @AreaId ORDER BY SerialNumber DESC";

                    result = await conn.QueryFirstOrDefaultAsync<string>(sql, new { CityId = cityId, AreaId = areaId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public override async Task<List<PowerStation>> GetAllAsync()
        {
            List<PowerStation> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT * FROM {tableName} WHERE Deleted = 0";

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

        /// <summary>
        /// 透過電站編號，取得單一電站資訊(覆寫)
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public override async Task<PowerStation> GetOneAsync(int id)
        {
            //base.GetOneAsync(id);

            PowerStation result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    var sql = @$"SELECT ps.*, c.Name AS CityName, a.Name AS AreaName, u.Name AS CreatorName FROM {tableName} ps
                                LEFT JOIN user u ON ps.CreatedBy = u.Id
                                LEFT JOIN city c ON ps.CityId = c.Id
                                LEFT JOIN area a ON ps.AreaId = a.Id
                                WHERE ps.Deleted = 0 AND ps.Id = @Id";

                    result = await conn.QueryFirstOrDefaultAsync<PowerStation>(sql, new { Id = id });

                    if (result != null)
                    {

                        var db_name = result.SiteDB;

                        var sql_operation_personnel = @$"SELECT UserId FROM power_station_operation_personnel op WHERE Deleted = 0 AND op.PowerStationId = @PowerStationId";
                        result.OperationPersonnelIds = (await conn.QueryAsync<int>(sql_operation_personnel, new { PowerStationId = result.Id })).ToList();
                        var sql_land_building = @$"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.LandBuildings = (await conn.QueryAsync<LandBuilding>(sql_land_building, new { PowerStationId = result.Id })).ToList();
                    }
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return result;
            }
        }

        /// <summary>
        /// 新增電站資料至 主、子資料庫
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<int> AddOnePowerStationAsync(PowerStation entity, List<string> properties, string db_name)
        {
            int id; int sub_count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        //新增資料 至主資料庫
                        string sql = GenerateInsertQuery(properties);

                        sql += "SELECT LAST_INSERT_ID();";

                        id = (await conn.QueryAsync<int>(sql, entity, trans)).Single();

                        //新增資料 至子資料庫
                        properties.Add("Id");
                        entity.Id = id;

                        string sub_sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, tableName);
                        sub_count = await conn.ExecuteAsync(sub_sql, entity, trans);

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

                return id;
            }
        }

        /// <summary>
        /// 修改主、子資料庫電站基本資訊
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task UpdatePowerStationInfo(UpdatePowerStationInfo entity, List<string> properties, string db_name)
        {

            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        //修改主資料庫
                        var sql = GenerateUpdateQuery(properties);
                        await conn.ExecuteAsync(sql, entity, trans);

                        //修改子資料庫
                        var sub_sql = GenerateUpdateQueryWithCustomDBNameAndTable(properties, db_name, tableName);
                        await conn.ExecuteAsync(sub_sql, entity, trans);

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

        /// <summary>
        /// 修改主、子資料庫能源局與台電資訊
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task UpdateBoETPCInfo(UpdateBoETPCInfo entity, List<string> properties, string db_name)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        //修改主資料庫
                        var sql = GenerateUpdateQuery(properties);
                        await conn.ExecuteAsync(sql, entity, trans);

                        //修改子資料庫
                        var sub_sql = GenerateUpdateQueryWithCustomDBNameAndTable(properties, db_name, tableName);
                        await conn.ExecuteAsync(sub_sql, entity, trans);

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

        /// <summary>
        /// 透過電站編號，取得所有土地房屋資訊
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<List<LandBuilding>> GetAllLandBuildingInfoByPowerStationId(int id, string db_name)
        {
            List<LandBuilding> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                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 = (await conn.QueryAsync<LandBuilding>(sql, new { PowerStationId = id })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 取得 土地房屋資訊
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<LandBuilding> GetOneLandBuildingInfo(int id, string db_name)
        {
            LandBuilding result;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    var sql = @$"SELECT * FROM {db_name}.land_building WHERE Deleted = 0 AND Id = @Id";

                    result = await conn.QueryFirstOrDefaultAsync<LandBuilding>(sql, new { Id = id });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

                return result;
            }
        }

        /// <summary>
        /// 新增 土地房屋資訊
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<int> AddOneLandBuildingInfo(LandBuilding entity, List<string> properties, string db_name)
        {
            int id;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    string sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, "land_building");

                    sql += "SELECT LAST_INSERT_ID();";

                    id = (await conn.QueryAsync<int>(sql, entity)).Single();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

                return id;
            }
        }

        /// <summary>
        /// 更新 土地房屋資訊
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task UpdateLandBuildingInfo(UpdateLandBuilding entity, List<string> properties, string db_name)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = GenerateUpdateQueryWithCustomDBNameAndTable(properties, db_name, "land_building");

                        await conn.ExecuteAsync(sql, entity, trans);

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

        /// <summary>
        /// 軟刪除土地房屋資訊
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task DeleteOneLandBuildingInfo(int id, string db_name)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = $"UPDATE {db_name}.land_building SET Deleted = 1 WHERE Id = @Id";

                        await conn.ExecuteAsync(sql, new { Id = id }, trans);

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

        /// <summary>
        /// 新增運維
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<int> AddOperation(OperationInfo operation, List<string> properties, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                int count;
                conn.Open();
                try
                {
                    string sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, "operation_firm");

                    count = await conn.ExecuteAsync(sql, operation);

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

                return count;
            }
        }

        /// <summary>
        /// 運維DataTable
        /// </summary>
        /// <param name="stationId"></param>
        /// <param name="stationId"></param>
        /// <returns></returns>
        public async Task<List<OperationTable>> OperationTable(int stationId, string db_name)
        {

            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                List<OperationTable> operation = new List<OperationTable>();
                conn.Open();
                try
                {
                    string sql = @$"SELECT 
                                    operation_firm.Name,
                                    operation_firm.PowerStationId,
                                    operation_firm.Id,
                                    operation_firm.ContactPerson,
                                    operation_firm.Phone,
                                    operation_firm.Email,
                                    user.Name AS CreatedName,
                                    operation_firm.CreatedAt,operation_firm.Type
                                    FROM {db_name}.operation_firm
                                    LEFT JOIN user ON operation_firm.CreatedBy = user.id 
                                    WHERE operation_firm.Deleted = 0 AND operation_firm.PowerStationId = @StationId";
                    operation = (await conn.QueryAsync<OperationTable>(sql, new { StationId = stationId })).ToList();

                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return operation;
            }
        }
        /// <summary>
        /// 選取單一運維
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<OperationInfo> OneOperationInfo(int id, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                OperationInfo operation;
                conn.Open();
                try
                {
                    string sql = @$"SELECT * FROM {db_name}.operation_firm WHERE Id = @Id";
                    operation = await conn.QueryFirstOrDefaultAsync<OperationInfo>(sql, new { Id = id });

                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return operation;
            }
        }

        /// <summary>
        /// 更新運維
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task UpdateOperation(OperationInfo operation, List<string> properties, string db_name)
        {
            using IDbConnection conn = _databaseHelper.GetConnection();
            conn.Open();
            var trans = conn.BeginTransaction();
            try
            {
                var sql = GenerateUpdateQueryWithCustomDBNameAndTable(properties, db_name, "operation_firm");
                await conn.ExecuteAsync(sql, operation, trans);
                trans.Commit();
            }
            catch (Exception exception)
            {
                trans.Rollback();
                throw exception;
            }
            finally
            {
                conn.Close();
            }
        }
        /// <summary>
        /// 裝置類型下拉選單
        /// </summary>
        /// <returns></returns>
        public async Task<List<UserSelectItemList>> DeviceType()
        {
            List<UserSelectItemList> result = new List<UserSelectItemList>();
            using IDbConnection conn = _databaseHelper.GetConnection();
            conn.Open();
            var trans = conn.BeginTransaction();
            try
            {
                string sql = @$"SELECT * FROM variable WHERE name = @name";
                var json = await conn.QueryFirstOrDefaultAsync<SolarPower.Models.PowerStation.Variable>(sql, new { name = "Type" });
                Root jsonfor = JsonSerializer.Deserialize<Root>(json.value);
                foreach (Models.PowerStation.Type a in jsonfor.Type)
                {
                    UserSelectItemList KeyValue = new UserSelectItemList
                    {
                        Value = a.EName,
                        Text = a.Name
                    };
                    result.Add(KeyValue);
                }
                trans.Commit();
            }
            catch (Exception exception)
            {
                trans.Rollback();
                throw exception;
            }
            finally
            {
                conn.Close();
            }
            return result;
        }
        /// <summary>
        /// 新增裝置資料
        /// </summary>
        /// <param name="DeviceInfo"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task AddDevice(Device DeviceInfo, List<string> properties, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                var trans = conn.BeginTransaction();
                try
                {

                    string sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, "device");
                    await conn.ExecuteAsync(sql, DeviceInfo);
                    trans.Commit();
                }
                catch (Exception exception)
                {
                    trans.Rollback();
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
            }


        }
        /// <summary>
        /// 修改裝置資料
        /// </summary>
        /// <param name="DeviceInfo"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task UpdateDevice(Device DeviceInfo, List<string> properties, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                var trans = conn.BeginTransaction();
                try
                {
                    var updateQuery = GenerateUpdateQueryWithCustomDBNameAndTable(properties, db_name, "device");
                    await conn.ExecuteAsync(updateQuery.ToString(), DeviceInfo, trans);
                    trans.Commit();
                }
                catch (Exception exception)
                {
                    trans.Rollback();
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
            }
        }
        /// <summary>
        /// 裝置dataTable
        /// </summary>
        /// <param name="stationId"></param>
        /// <returns></returns>
        public async Task<List<DeviceTable>> DeviceTable(int stationId, string db_name)
        {
            using IDbConnection conn = _databaseHelper.GetConnection();
            conn.Open();
            List<DeviceTable> Device = new List<DeviceTable>();
            try
            {
                string sql = @$"SELECT de.*, con.ControllerId AS ControllerName,ps.Code AS PowerStationName FROM {db_name}.device de 
                                LEFT JOIN {db_name}.controller con ON de.ControllerId = con.id  
                                LEFT JOIN {db_name}.power_station ps ON de.PowerStationId = ps.id
                                WHERE de.Deleted = 0 AND de.PowerStationId = @StationId ";
                Device = (await conn.QueryAsync<DeviceTable>(sql, new { StationId = stationId })).ToList();
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                conn.Close();
            }
            return Device;
        }
        /// <summary>
        /// 取單一筆DeviceInfo
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<DeviceInfo> OneDeviceInfo(int id, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                DeviceInfo Device;
                conn.Open();
                try
                {
                    string sql = @$"SELECT * FROM {db_name}.device WHERE Id = @Id";
                    Device = await conn.QueryFirstOrDefaultAsync<DeviceInfo>(sql, new { Id = id });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return Device;
            }
        }
        /// <summary>
        /// 新增 異常設定
        /// </summary>
        /// <param name="Exception"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task AddException(ExceptionModal Exception, List<string> properties, string db_name)
        {
            using IDbConnection conn = _databaseHelper.GetConnection();
            conn.Open();
            try
            {
                string sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, "power_station_exception");

                await conn.ExecuteAsync(sql, Exception);

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

        /// <summary>
        /// 異常dataTable
        /// </summary>
        /// <param name="stationId"></param>
        /// <returns></returns>
        public async Task<List<ExceptionTable>> ExceptionTable(int stationId, string db_name)
        {
            using IDbConnection conn = _databaseHelper.GetConnection();
            conn.Open();
            List<ExceptionTable> Exception = new List<ExceptionTable>();
            try
            {
                string sql = @$"SELECT pe.Type,pe.UpperLimit,pe.LowerLimit,pe.Alarm,ps.Code AS PowerStationCode ,ps.Name AS PowerStationName,pe.CreatedAt,pe.Id
                                FROM {db_name}.power_station_exception pe 
                                LEFT JOIN {db_name}.power_station ps ON pe.PowerStationId = ps.Id 
                                WHERE pe.Deleted = 0 AND pe.PowerStationId = @StationId";
                Exception = (await conn.QueryAsync<ExceptionTable>(sql, new { StationId = stationId })).ToList();
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                conn.Close();
            }
            return Exception;
        }
        /// <summary>
        /// 取一筆異常設定
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ExceptionModal> OneException(int id, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                ExceptionModal Exception;
                conn.Open();
                try
                {
                    string sql = @$"SELECT * FROM {db_name}.power_station_exception WHERE Id = @Id";
                    Exception = await conn.QueryFirstOrDefaultAsync<ExceptionModal>(sql, new { Id = id });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return Exception;
            }
        }
        /// <summary>
        /// 更新異常設定
        /// </summary>
        /// <param name="Exception"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task UpdateException(ExceptionModal Exception, List<string> properties, string db_name)
        {
            using IDbConnection conn = _databaseHelper.GetConnection();
            conn.Open();
            var trans = conn.BeginTransaction();
            try
            {
                var updateQuery = GenerateUpdateQueryWithCustomDBNameAndTable(properties, db_name, "power_station_exception");
                await conn.ExecuteAsync(updateQuery.ToString(), Exception, trans);
                trans.Commit();
            }
            catch (Exception exception)
            {
                trans.Rollback();
                throw exception;
            }
            finally
            {
                conn.Close();
            }
        }
        public async Task<string> GetFinalSerialNumber(int PowerStationId, string Type, string db_name)
        {
            string Num;
            using IDbConnection conn = _databaseHelper.GetConnection();
            conn.Open();
            var trans = conn.BeginTransaction();
            try
            {
                var sql = $"SELECT SerialNumber FROM {db_name}.device WHERE PowerStationId = @PowerStationId AND Type = @Type ORDER BY SerialNumber DESC";
                Num = await conn.QueryFirstOrDefaultAsync<string>(sql, new { PowerStationId = PowerStationId, Type = Type });
                trans.Commit();
            }
            catch (Exception exception)
            {
                trans.Rollback();
                throw exception;
            }
            finally
            {
                conn.Close();
            }
            return Num;
        }

        /// <summary>
        /// 透過電站編號，取得該電站的運維人員編號
        /// </summary>
        /// <param name="powerStationId"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<List<int>> GetOperationPersonnelIdsByPowerStatioinId(int powerStationId)
        {
            List<int> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    var sql = @$"SELECT UserId FROM power_station_operation_personnel WHERE Deleted = 0 AND PowerStationId = @PowerStationId";

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

        /// <summary>
        /// 新增電站運維人員
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task<int> AddOperationPersonnelAsync(List<PowerStationOperationPersonnel> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    string sql = GenerateInsertQueryWithCustomTable(properties, "power_station_operation_personnel");

                    count = await conn.ExecuteAsync(sql, entity);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

                return count;
            }
        }

        /// <summary>
        /// 軟刪除電站運維人員
        /// </summary>
        /// <param name="operationPersonnels"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task DeleteOperationPersonnel(List<PowerStationOperationPersonnel> operationPersonnels)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = $"UPDATE power_station_operation_personnel SET Deleted = 1 WHERE PowerStationId = @PowerStationId AND UserId = @UserId";

                        await conn.ExecuteAsync(sql, operationPersonnels, trans);

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

        /// <summary>
        /// 電站管理 新增電站圖片
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<int> AddPowerStationImageAsync(List<PowerStationImage> entity, List<string> properties, string db_name)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, "power_station_image");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        /// <summary>
        /// 電站管理 取得所有電站圖片的資料
        /// </summary>
        /// <param name="powerStationId"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<List<PowerStationImage>> GetAllPowerStationImageAsync(int powerStationId, string db_name)
        {
            List<PowerStationImage> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT * FROM {db_name}.power_station_image WHERE Deleted = 0 AND PowerStationId = @PowerStationId";

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

        /// <summary>
        /// 電站管理 取得單一電站圖片的資料
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<PowerStationImage> GetOnePowerStationImageAsync(int id, string db_name)
        {
            PowerStationImage result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT * FROM {db_name}.power_station_image WHERE Deleted = 0 AND Id = @Id";

                    result = await conn.QueryFirstOrDefaultAsync<PowerStationImage>(sql, new { Id = id });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 軟刪除 單一電站圖片
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task DeleteOnePowerStationImage(int id, string db_name)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = $"UPDATE {db_name}.power_station_image SET Deleted = 1 WHERE id = @Id";

                        await conn.ExecuteAsync(sql, new { Id = id }, trans);

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

        /// <summary>
        /// 電站管理 取得主要卡片顯示圖
        /// </summary>
        /// <param name="powerStationId"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<PowerStationImage> GetMainDisplayAsync(int powerStationId, string db_name)
        {
            PowerStationImage result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT * FROM {db_name}.power_station_image WHERE Deleted = 0 AND IsMainDisplay = 1 AND PowerStationId = @PowerStationId";

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

        /// <summary>
        /// 電站管理 更新上傳圖片
        /// </summary>
        /// <param name="image"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task UpdatePowerStationImage(UpdataPowerStationImage image, List<string> properties, string db_name)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = GenerateUpdateQueryWithCustomDBNameAndTable(properties, db_name, "power_station_image");

                        await conn.ExecuteAsync(sql, image, trans);


                        var sql_MainDispalyImg = string.Empty;
                        List<string> powerStationMainDispalyImg = new List<string>()
                        {
                            "Id",
                            "MainDisplay"
                        };

                        if (image.IsMainDisplay == 1)
                        {
                            //修改主資料庫
                            sql_MainDispalyImg = GenerateUpdateQuery(powerStationMainDispalyImg);
                            await conn.ExecuteAsync(sql_MainDispalyImg, new { Id = image.PowerStationId, MainDisplay = image.Image }, trans);

                            //修改子資料庫
                            sql_MainDispalyImg = GenerateUpdateQueryWithCustomDBNameAndTable(powerStationMainDispalyImg, db_name, "power_station");
                            await conn.ExecuteAsync(sql_MainDispalyImg, new { Id = image.PowerStationId, MainDisplay = image.Image }, trans);
                        }

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

        /// <summary>
        /// 電站管理 新增單線圖
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<int> AddPowerStationSingleLineAsync(List<PowerStationSingleLine> entity, List<string> properties, string db_name)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    string sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, "power_station_single_line_diagram");

                    count = await conn.ExecuteAsync(sql, entity);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

                return count;
            }
        }

        /// <summary>
        /// 電站管理 取得所有單線圖的資料
        /// </summary>
        /// <param name="powerStationId"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<List<PowerStationSingleLine>> GetAllPowerStationSingleLineAsync(int powerStationId, string db_name)
        {
            List<PowerStationSingleLine> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT * FROM {db_name}.power_station_single_line_diagram WHERE Deleted = 0 AND PowerStationId = @PowerStationId";

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

        /// <summary>
        /// 電站管理 取得單一單線圖的資料
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<PowerStationSingleLine> GetOnePowerStationSingleLineAsync(int id, string db_name)
        {
            PowerStationSingleLine result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT * FROM {db_name}.power_station_single_line_diagram WHERE Deleted = 0 AND Id = @Id";

                    result = await conn.QueryFirstOrDefaultAsync<PowerStationSingleLine>(sql, new { Id = id });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 軟刪除 單一單線圖
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task DeleteOnePowerStationSingleLine(int id, string db_name)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = $"UPDATE {db_name}.power_station_single_line_diagram SET deleted = 1 WHERE id = @Id";

                        await conn.ExecuteAsync(sql, new { Id = id }, trans);

                        trans.Commit();
                    }
                    catch (Exception exception)
                    {
                        trans.Rollback();
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }
        public async Task<List<SolarCityAmount>> GetSolarCitySummary(MyUser User)
        {
            using IDbConnection conn = _databaseHelper.GetConnection();
            List<SolarCityAmount> solaramount = new List<SolarCityAmount>();
            conn.Open();
            var trans = conn.BeginTransaction();
            try
            {
                if (User.Role.Layer == 0 || User.Role.Layer == 1)
                {
                    var sql = "SELECT city.Id AS CityId, city.Name AS City,COUNT(*) AS Amount FROM power_station LEFT JOIN city ON power_station.CityId = city.Id GROUP BY power_station.CityId";
                    solaramount = (await conn.QueryAsync<SolarCityAmount>(sql)).ToList();
                    trans.Commit();
                }
                else if (User.Role.Layer == 2)
                {
                    var sql = "SELECT city.Id AS CityId, city.Name AS City,COUNT(*) AS Amount FROM power_station LEFT JOIN city ON power_station.CityId = city.Id WHERE CompanyId = @CompanyId GROUP BY power_station.CityId ORDER BY power_station.CityId ";
                    solaramount = (await conn.QueryAsync<SolarCityAmount>(sql, new { CompanyId = User.CompanyId })).ToList();
                    trans.Commit();
                }
                else
                {
                    var sql = "SELECT city.Id AS CityId, city.Name AS City,COUNT(*) AS Amount FROM power_station LEFT JOIN city ON power_station.CityId = city.Id LEFT JOIN power_station_operation_personnel ON power_station.Id = power_station_operation_personnel.PowerStationId WHERE UserId = @UserId GROUP BY power_station.CityId ORDER BY power_station.CityId";
                    solaramount = (await conn.QueryAsync<SolarCityAmount>(sql, new { UserId = User.Id })).ToList();
                    trans.Commit();
                }
            }
            catch (Exception exception)
            {
                trans.Rollback();
                throw exception;
            }
            finally
            {
                conn.Close();
            }
            return solaramount;
        }
        public async Task<List<PowerStation>> GetSolarByCity(MyUser User, List<int> CityId)
        {
            using IDbConnection conn = _databaseHelper.GetConnection();
            List<PowerStation> powerstation = new List<PowerStation>();
            conn.Open();
            var trans = conn.BeginTransaction();
            try
            {
                var ids = "";
                foreach (var id in 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 ps.* , c.Name AS CityName, a.Name AS AreaName
                                FROM power_station ps
                                LEFT JOIN city c ON ps.CityId = c.Id
                                LEFT JOIN area a ON ps.AreaId = a.Id
                                WHERE ps.CityId IN @IDs";
                    powerstation = (await conn.QueryAsync<PowerStation>(sql, new { IDs = CityId })).ToList();
                    trans.Commit();
                }
                else if (User.Role.Layer == 2)
                {
                    var sql = @"SELECT ps.* , c.Name AS CityName, a.Name AS AreaName
                                FROM power_station ps
                                LEFT JOIN city c ON ps.CityId = c.Id
                                LEFT JOIN area a ON ps.AreaId = a.Id
                                WHERE ps.CityId IN @IDs
                                AND ps.CompanyId=@CompanyId";
                    powerstation = (await conn.QueryAsync<PowerStation>(sql, new { IDs = CityId, CompanyId = User.CompanyId })).ToList();
                    trans.Commit();
                }
                else
                {
                    var sql = @"SELECT ps.* , c.Name AS CityName, a.Name AS AreaName
                                FROM power_station ps
                                LEFT JOIN city c ON ps.CityId = c.Id
                                LEFT JOIN area a ON ps.AreaId = a.Id
                                LEFT JOIN power_station_operation_personnel psop ON ps.Id = psop.PowerStationId
                                WHERE ps.CityId IN @IDs AND psop.Userid = @UserId";
                    powerstation = (await conn.QueryAsync<PowerStation>(sql, new { IDs = CityId, UserId = User.Id })).ToList();
                    trans.Commit();
                }
            }
            catch (Exception exception)
            {
                trans.Rollback();
                throw exception;
            }
            finally
            {
                conn.Close();
            }
            return powerstation;
        }

        public async Task<List<OperationPersonnelSelectItemList>> GetOperationPersonnelSelectOptionListAsync(int powerStationId)
        {
            List<OperationPersonnelSelectItemList> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT u.Id AS Value, u.Name AS Text 
                                FROM power_station_operation_personnel op
                                LEFT JOIN user u ON op.UserId = u.Id
                                WHERE op.Deleted = 0 AND op.PowerStationId = @PowerStationId";

                    result = (await conn.QueryAsync<OperationPersonnelSelectItemList>(sql, new { PowerStationId = powerStationId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
        /// <summary>
        /// 新增控制器
        /// </summary>
        /// <param name="deviceController"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task AddDeviceController(DeviceController deviceController, List<string> properties, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                int count;
                conn.Open();
                try
                {
                    string sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, "controller");

                    count = await conn.ExecuteAsync(sql, deviceController);

                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
            }
        }
        /// <summary>
        /// 控制器dataTable
        /// </summary>
        /// <param name="stationId"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<List<DeviceControllerTable>> DeviceControllerTable(int stationId, string db_name)
        {

            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                List<DeviceControllerTable> deviceControllerTable = new List<DeviceControllerTable>();
                conn.Open();
                try
                {
                    string sql = @$"SELECT 
                                    col.ControllerId,user.Name As CreatedName ,col.CreatedAt,col.Id
                                    FROM {db_name}.controller col
                                    LEFT JOIN user ON col.CreatedBy = user.id 
                                    WHERE col.Deleted = 0 AND col.PowerStationId = @StationId";
                    deviceControllerTable = (await conn.QueryAsync<DeviceControllerTable>(sql, new { StationId = stationId })).ToList();

                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return deviceControllerTable;
            }
        }
        /// <summary>
        /// 新增逆變器
        /// </summary>
        /// <param name="inverter"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task AddInverter(Inverter inverter, List<string> properties, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                int count;
                conn.Open();
                try
                {
                    string sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, "inverter");

                    count = await conn.ExecuteAsync(sql, inverter);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
            }
        }
        /// <summary>
        /// 取得控制器所有id
        /// </summary>
        /// <param name="stationId"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<List<int>> GetAllDeviceControllerId(int stationId, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                List<int> count;
                conn.Open();
                try
                {
                    string sql = $"SELECT id FROM {db_name}.controller WHERE PowerStationId = {stationId}";
                    count = (await conn.QueryAsync<int>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return count;
            }
        }

        /// <summary>
        /// 透過電站Id，取得所有控制器編碼
        /// </summary>
        /// <param name="stationId"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<List<string>> GetAllDeviceControllerByPowerStationId(int stationId, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                List<string> result;
                conn.Open();
                try
                {
                    string sql = $"SELECT ControllerId FROM {db_name}.controller WHERE PowerStationId = {stationId}";
                    result = (await conn.QueryAsync<string>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return result;
            }
        }

        /// <summary>
        /// 逆變器DataTable
        /// </summary>
        /// <param name="controllerid"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task<List<InverterTable>> InverterTable(List<int> controllerid, string db_name)
        {

            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                List<InverterTable> inverterTable = new List<InverterTable>();
                conn.Open();
                try
                {
                    string sql = @$"SELECT 
                                    inv.*, con.ControllerId AS ControllerName,user.Name As CreatedName,de.UID AS PyrheliometerName
                                    FROM {db_name}.inverter inv
                                    LEFT JOIN {db_name}.controller con ON inv.ControllerId = con.id 
                                    LEFT JOIN user ON inv.CreatedBy = user.id 
                                    LEFT JOIN {db_name}.device de ON inv.Pyrheliometer = de.id     
                                    WHERE inv.Deleted = 0 AND inv.ControllerId IN @Controllerid";
                    inverterTable = (await conn.QueryAsync<InverterTable>(sql, new { Controllerid = controllerid })).ToList();

                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return inverterTable;
            }
        }

        /// <summary>
        /// 其餘電站列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<PowerstationOption>> GetPowerstationOptionAsync(string db_name, int stationId)
        {
            List<PowerstationOption> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT Id AS Value, Code AS Text FROM {db_name}.power_station WHERE Deleted = 0 AND Id !={stationId}";

                    result = (await conn.QueryAsync<PowerstationOption>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
        /// <summary>
        /// 電站日照計列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<PowerstationOption>> GetPowerstationPyrheliometerAsync(string db_name, int stationId)
        {
            List<PowerstationOption> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT dd.Id AS Value, dd.UID AS Text FROM {db_name}.device dd WHERE dd.Deleted = 0 AND dd.PowerStationId = {stationId} AND dd.Type = 'PYR' 
                                UNION SELECT dd.Id AS Value, dd.UID AS Text FROM {db_name}.sharedevice sh LEFT JOIN {db_name}.device dd ON sh.DeviceId = dd.Id
                                WHERE dd.Deleted = 0 AND sh.PowerStationId = {stationId};";

                    result = (await conn.QueryAsync<PowerstationOption>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
        /// <summary>
        /// 設備編號下拉式選單
        /// </summary>
        /// <param name="db_name"></param>
        /// <param name="stationId"></param>
        /// <returns></returns>
        public async Task<List<PowerstationOption>> GetDeviceUIDListAsync(string db_name, int stationId)
        {
            List<PowerstationOption> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT Id AS Value, UID AS Text FROM {db_name}.device WHERE Deleted = 0 AND PowerStationId ={stationId}";

                    result = (await conn.QueryAsync<PowerstationOption>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
        /// <summary>
        /// 新增共享設備
        /// </summary>
        /// <param name="sharedevice"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task AddShareDevice(Sharedevice sharedevice, List<string> properties, string db_name)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    string sql = GenerateInsertQueryWithCustomDBNameAndTable(properties, db_name, "sharedevice");
                    await conn.ExecuteAsync(sql, sharedevice);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
            }
        }


        /// <summary>
        /// 共享裝置dataTable
        /// </summary>
        /// <param name="stationId"></param>
        /// <returns></returns>
        public async Task<List<DeviceTable>> shareDeviceTables(int stationId, string db_name)
        {
            using IDbConnection conn = _databaseHelper.GetConnection();
            conn.Open();
            List<DeviceTable> Device = new List<DeviceTable>();
            try
            {
                string sql = @$"SELECT de.*, con.ControllerId AS ControllerName,ps.Code AS PowerStationName, sh.Id FROM {db_name}.sharedevice sh
                                LEFT JOIN {db_name}.device de ON sh.DeviceId = de.Id
                                LEFT JOIN {db_name}.controller con ON de.ControllerId = con.id  
                                LEFT JOIN {db_name}.power_station ps ON de.PowerStationId = ps.id
                                WHERE de.Deleted = 0 AND sh.PowerStationId = @StationId ";
                Device = (await conn.QueryAsync<DeviceTable>(sql, new { StationId = stationId })).ToList();
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                conn.Close();
            }
            return Device;
        }

        /// <summary>
        /// 取一筆各型態資料
        /// </summary>
        /// <typeparam name="A"></typeparam>
        /// <param name="where"></param>
        /// <param name="db_name"></param>
        /// <param name="table_name"></param>
        /// <returns></returns>
        public async Task<A> GetoneData<A>(string where, string db_name, string table_name)
        {
            A result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT * FROM {db_name}.{table_name} WHERE {where}";

                    result = await conn.QueryFirstOrDefaultAsync<A>(sql);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<PowerStationHistory> GetPowerStationHistoryPerHour(string dateTime, string table_name)
        {
            PowerStationHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                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 = await conn.QueryFirstOrDefaultAsync<PowerStationHistory>(sql, new { DateTime = dateTime });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<AvgPowerStationHistory> CalcAvgPowerStationHistory30day(string nowDay, string table_name)
        {
            AvgPowerStationHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var startDay = Convert.ToDateTime(nowDay).AddDays(-30).ToString("yyyy-MM-dd");

                    var sql = $@"SELECT AVG(s.KWHKWP) AS AvgKWHKWP, AVG(s.PR) AS AvgPR
                                    FROM {table_name} s 
                                    WHERE DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H') IN (
	                                    SELECT MAX(DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H')) FROM {table_name} s 
	                                    WHERE DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d') BETWEEN @StartDay AND @EndDay
	                                    GROUP BY DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d')) 
                                ";

                    result = await conn.QueryFirstOrDefaultAsync<AvgPowerStationHistory>(sql, new { StartDay = startDay, EndDay = nowDay });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<int> AddPowerStationHistory(List<PowerStationHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "power_station_history_hour");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<int> UpdateList(List<PowerStation> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateUpdateQuery(properties);

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        /// <summary>
        /// 透過日期，取得最後一筆資料
        /// </summary>
        /// <param name="day"></param>
        /// <param name="table_name"></param>
        /// <returns></returns>
        public async Task<PowerStationHistoryDay> GetLastOnePowerStationHistoryByDay(string day, string table_name)
        {
            PowerStationHistoryDay result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT 
                                    DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H') AS TIMESTAMP,
                                    s.SITEID,
                                    s.SITETYPE,
                                    s.TodayKWh,
                                    s.TotalKWH,
                                    s.KWHKWP,
                                    s.PR,
                                    s.MP,
                                    s.SolarHour
                                 FROM {table_name} s 
                                 WHERE DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d') = @Day
                                 ORDER BY TIMESTAMP DESC
                                 LIMIT 1
                    ";

                    result = await conn.QueryFirstOrDefaultAsync<PowerStationHistoryDay>(sql, new { Day = day });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 新增資料，至每日的電站歷史記錄
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task<int> AddPowerStationHistoryDayList(List<PowerStationHistoryDay> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "power_station_history_day");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<PowerStationHistoryMonth> GetOnePowerStationHistoryByPowerStationIdAndMonth(int powerStationId, string month)
        {
            PowerStationHistoryMonth result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT *
                                 FROM power_station_history_month s 
                                 WHERE PowerStationId = @PowerStationId
                                 AND DATE_FORMAT(s.TIMESTAMP, '%Y-%m')= @Month
                    ";

                    result = await conn.QueryFirstOrDefaultAsync<PowerStationHistoryMonth>(sql, new { PowerStationId = powerStationId, Month = month });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<PowerStationHistoryMonth> ClacPowerStationHistoryMonthDataByPowerStationId(int powerStationId, string month)
        {
            PowerStationHistoryMonth result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT 
                                    PowerStationId,
                                    DATE_FORMAT(s.TIMESTAMP, '%Y-%m') AS TIMESTAMP,
                                    s.SITEID,
                                    s.SITETYPE,
                                    SUM(s.TODAYKWH) AS MONTHKWH,
                                    MAX(s.TOTALKWH) AS TOTALKWH,
                                    AVG(s.KWHKWP) AS KWHKWP,
                                    AVG(s.PR) AS PR,
                                    AVG(s.MP) AS MP,
                                    SUM(s.SOLARHOUR)  AS SOLARHOUR
                                    FROM power_station_history_day s 
                                    WHERE DATE_FORMAT(s.TIMESTAMP, '%Y-%m') = @Month
                                    AND PowerStationId = @PowerStationId
                                    GROUP BY PowerStationId,DATE_FORMAT(s.TIMESTAMP, '%Y-%m')
                    ";

                    result = await conn.QueryFirstOrDefaultAsync<PowerStationHistoryMonth>(sql, new { PowerStationId = powerStationId, Month = month });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 新增資料，至每月的電站歷史記錄
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task<int> AddPowerStationHistoryMonthList(List<PowerStationHistoryMonth> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "power_station_history_month");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<int> UpdatePowerStationHistoryMonthList(List<PowerStationHistoryMonth> entity)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = @"UPDATE power_station_history_month SET
                                        MonthKWh=@MonthKWh,
                                        TOTALKWH=@TOTALKWH,
                                        KWHKWP=@KWHKWP,
                                        PR=@PR,
                                        MP=@MP,
                                        SolarHour=@SolarHour,
                                        MONEY=@MONEY,
                                        TOTALMONEY=@TOTALMONEY,
                                        CARBON=@CARBON,
                                        TOTALCARBON=@TOTALCARBON
                                        WHERE PowerStationId = @PowerStationId
                                        AND TIMESTAMP LIKE CONCAT(@TIMESTAMP, '%')
";

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<int> UpdateInverter(Inverter entity, List<string> properties, string db_name)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateUpdateQueryWithCustomDBNameAndTable(properties, db_name, "inverter");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }
        public async Task<List<DeviceInfo>> GetListPyrheliometerByPowerStationId(int powerStationId, string db_name)
        {
            List<DeviceInfo> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT * 
                                    FROM {db_name}.device d 
                                    WHERE d.PowerStationId = @PowerStationId AND d.`Type` = 'PYR' 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` = 'PYR' AND d.Deleted = 0 AND d.Enabled = 1 AND d.Status != 0
                    ";

                    result = (await conn.QueryAsync<DeviceInfo>(sql, new { PowerStationId = powerStationId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
        //(有新增)
        public async Task<List<DeviceInfo>> GetListTempByPowerStationId(int powerStationId, string db_name)
        {
            List<DeviceInfo> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT * 
                                    FROM {db_name}.device d 
                                    WHERE d.PowerStationId = @PowerStationId AND d.`Type` = 'MTR' 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` = 'MTR' AND d.Deleted = 0 AND d.Enabled = 1 AND d.Status != 0
                    ";

                    result = (await conn.QueryAsync<DeviceInfo>(sql, new { PowerStationId = powerStationId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
        //(有修改)
        public async Task<PyrheliometerHistory> GetPyrheliometerHistoryPerHour(string dateTime, List<DeviceInfo> deviceInfos, int type)
        {
            var typename = "";
            if (type == 1)
            {
                typename = "Temperature";//1為溫度計
            }
            else if (type == 0)
            {
                typename = "Irradiance";//0為日照計
            }
            PyrheliometerHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                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, AVG(s.{device.ColName}) 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, AVG(a.SENSOR) AS {typename} FROM(" + string.Join(" UNION ", sql_per_device) + @") a GROUP BY `TIMESTAMP`";

                    result = await conn.QueryFirstOrDefaultAsync<PyrheliometerHistory>(sql, new { DateTime = dateTime });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<int> AddPyrheliometerHistory(List<PyrheliometerHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "sensor_history_hour");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }
        //(有新增)
        public async Task<int> AddTempHistory(List<PyrheliometerHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateUpdateQueryWithCustomTableAndWHERE(properties, "sensor_history_hour", "PowerStationId = @PowerStationId AND TIMESTAMP = @Timestamp");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<AvgPyrheliometerHistory> CalcAvgPyrheliometerHistory30day(string nowDay, int powerStationId)
        {
            AvgPyrheliometerHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var startDay = Convert.ToDateTime(nowDay).AddDays(-30).ToString("yyyy-MM-dd");

                    var sql = $@"SELECT AVG(p.Irradiance) AS AvgIrradiance
                                    FROM sensor_history_hour p
                                    WHERE DATE_FORMAT(p.TIMESTAMP, '%Y-%m-%d') BETWEEN @StartDay AND @EndDay
                                    AND p.Irradiance != 0
                                    AND PowerStationId = @PowerStationId
                                    GROUP BY DATE_FORMAT(p.TIMESTAMP, '%Y-%m-%d')
                                ";

                    result = await conn.QueryFirstOrDefaultAsync<AvgPyrheliometerHistory>(sql, new { StartDay = startDay, EndDay = nowDay, PowerStationId = powerStationId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<PyrheliometerHistory> CalcPyrheliometerHistoryDayDataByPowerStationId(string nowDay, int powerStationId)
        {
            PyrheliometerHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT 
                                    PowerStationId,
                                    DATE_FORMAT(p.TIMESTAMP, '%Y-%m-%d') AS TIMESTAMP,
                                    AVG(p.Irradiance) AS Irradiance,
                                    AVG(p.Temperature) AS Temperature
                                    FROM sensor_history_hour p
                                    WHERE DATE_FORMAT(p.TIMESTAMP, '%Y-%m-%d') = @NowDay
                                    AND p.Irradiance != 0
                                    AND PowerStationId = @PowerStationId
                                    GROUP BY DATE_FORMAT(p.TIMESTAMP, '%Y-%m-%d')
                                ";

                    result = await conn.QueryFirstOrDefaultAsync<PyrheliometerHistory>(sql, new { NowDay = nowDay, PowerStationId = powerStationId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<int> AddPyrheliometerHistoryDayList(List<PyrheliometerHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "sensor_history_day");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<PyrheliometerHistory> CalcPyrheliometerHistoryMonthDataByPowerStationId(string month, int powerStationId)
        {
            PyrheliometerHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT 
                                    PowerStationId,
                                    DATE_FORMAT(p.TIMESTAMP, '%Y-%m') AS TIMESTAMP,
                                    AVG(p.Irradiance) AS Irradiance,
                                    AVG(p.Temperature) AS Temperature
                                    FROM sensor_history_hour p
                                    WHERE DATE_FORMAT(p.TIMESTAMP, '%Y-%m') = @Month
                                    AND p.Irradiance != 0
                                    AND PowerStationId = @PowerStationId
                                    GROUP BY DATE_FORMAT(p.TIMESTAMP, '%Y-%m')
                                ";

                    result = await conn.QueryFirstOrDefaultAsync<PyrheliometerHistory>(sql, new { Month = month, PowerStationId = powerStationId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<PyrheliometerHistory> GetOnePyrheliometerHistoryByMonth(string month, int powerStationId)
        {
            PyrheliometerHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT * FROM sensor_history_month WHERE DATE_FORMAT(TIMESTAMP, '%Y-%m') = @Month AND PowerStationId = @PowerStationId";

                    result = await conn.QueryFirstOrDefaultAsync<PyrheliometerHistory>(sql, new { Month = month, PowerStationId = powerStationId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<int> AddPyrheliometerHistoryMonthList(List<PyrheliometerHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "sensor_history_month");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<int> UpdatePyrheliometerHistoryMonthList(List<PyrheliometerHistory> entity)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = @"UPDATE sensor_history_month SET
                                        Irradiance=@Irradiance,
                                        Temperature=@Temperature
                                        WHERE PowerStationId = @PowerStationId
                                        AND TIMESTAMP LIKE CONCAT(@TIMESTAMP, '%')
                                        ";

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<List<InverterHistory>> CalcInverterHisyort15minData(string dateTime, string db_name, string table_name, List<string> inverterIds)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var stratDateTime = Convert.ToDateTime(dateTime + ":00").AddMinutes(-15).ToString("yyyy-MM-dd HH:mm");

                    var sql = $@"SELECT 
                                    s.TIMESTAMP,
                                    s.INVERTERID,
                                    a.KWH,
                                    s.TODAYKWH,
                                    i.Capacity,
                                    (a.KWH/i.Capacity) AS KWHKWP
                                   FROM (SELECT 
                                                MAX(FROM_UNIXTIME(sub_inv.TIMESTAMP/1000, '%Y-%m-%d %H:%i')) AS TIMESTAMP,
                                                sub_inv.INVERTERID,
                                                MAX(sub_inv.TODAYKWH) AS TODAYKWH
                                                FROM {table_name} sub_inv
                                                WHERE FROM_UNIXTIME(sub_inv.TIMESTAMP/1000, '%Y-%m-%d %H:%i') BETWEEN @StartDateTime AND @EndDateTime
                                                AND sub_inv.INVERTERID IN @InverterIds
                                                GROUP BY sub_inv.INVERTERID) s
                                   LEFT JOIN (
                                                SELECT MAX(FROM_UNIXTIME(sub_inv.TIMESTAMP/1000, '%Y-%m-%d %H:%i')) AS TIMESTAMP,
                                                    sub_inv.INVERTERID,
                                                    AVG(sub_inv.WH)/1000 AS KWH
                                                    FROM {table_name} sub_inv 
                                                    WHERE FROM_UNIXTIME(sub_inv.TIMESTAMP/1000, '%Y-%m-%d %H:%i') BETWEEN @StartDateTime AND @EndDateTime
                                                    AND sub_inv.INVERTERID IN @InverterIds
                                                    GROUP BY sub_inv.INVERTERID) a
                                    ON s.TIMESTAMP = a.TIMESTAMP AND s.INVERTERID = a. INVERTERID
                                    LEFT JOIN {db_name}.inverter i ON s.INVERTERID = REPLACE(i.InverterId, 's', '');";

                    result = (await conn.QueryAsync<InverterHistory>(sql, new { StartDateTime = stratDateTime, EndDateTime = dateTime, InverterIds = inverterIds })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<int> AddInverter15minHistory(List<InverterHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "inverter_history_15min");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

        public async Task<List<InverterHistory>> CalcInverterHisyortHourData(string dateTime, string db_name, string table_name, List<string> inverterIds)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT 
                                    MAX(FROM_UNIXTIME(s.TIMESTAMP/1000, '%Y-%m-%d %H')) AS TIMESTAMP,
                                    s.INVERTERID,
                                    AVG(s.AC1V) AS AC1V,
                                    AVG(s.AC1A) AS AC1A,
                                    AVG(s.AC1W) AS AC1W,
                                    AVG(s.AC1F) AS AC1F,
                                    AVG(s.AC1WH) AS AC1WH,
                                    AVG(s.AC2V) AS AC2V,
                                    AVG(s.AC2A) AS AC2A,
                                    AVG(s.AC2W) AS AC2W,
                                    AVG(s.AC2F) AS AC2F,
                                    AVG(s.AC2WH) AS AC2WH,
                                    AVG(s.AC3V) AS AC3V,
                                    AVG(s.AC3A) AS AC3A,
                                    AVG(s.AC3W) AS AC3W,
                                    AVG(s.AC3F) AS AC3F,
                                    AVG(s.AC3WH) AS AC3WH,
                                    AVG(s.DC1V) AS DC1V,
                                    AVG(s.DC1A) AS DC1A,
                                    AVG(s.DC1W) AS DC1W,
                                    AVG(s.DC1WH) AS DC1WH,
                                    AVG(s.DC2V) AS DC2V,
                                    AVG(s.DC2A) AS DC2A,
                                    AVG(s.DC2W) AS DC2W,
                                    AVG(s.DC2WH) AS DC2WH,
                                    AVG(s.DC3V) AS DC3V,
                                    AVG(s.DC3A) AS DC3A,
                                    AVG(s.DC3W) AS DC3W,
                                    AVG(s.DC3WH) AS DC3WH,
                                    AVG(s.DC4V) AS DC4V,
                                    AVG(s.DC4A) AS DC4A,
                                    AVG(s.DC4W) AS DC4W,
                                    AVG(s.DC4WH) AS DC4WH,
                                    AVG(s.DC5V) AS DC5V,
                                    AVG(s.DC5A) AS DC5A,
                                    AVG(s.DC5W) AS DC5W,
                                    AVG(s.DC5WH) AS DC5WH,
                                    AVG(s.PR) AS PR,
                                    AVG(s.RA1) AS RA1,
                                    AVG(s.RA2) AS RA2,
                                    AVG(s.RA3) AS RA3,
                                    AVG(s.RA4) AS RA4,
                                    AVG(s.RA5) AS RA5,
                                    a.KWH,
                                    MAX(s.TODAYKWH) AS TODAYKWH,
                                    i.Capacity,
                                    (a.KWH/i.Capacity) AS KWHKWP
                                FROM {table_name} s
                                LEFT JOIN (
	                                SELECT 
                                        FROM_UNIXTIME(inv.TIMESTAMP/1000, '%Y-%m-%d %H') AS TIMESTAMP,
                                        inv.INVERTERID,
                                        AVG(inv.WH)/1000 AS KWH  
	                                FROM  {table_name} inv 
	                                WHERE DATE_FORMAT(FROM_UNIXTIME(inv.TIMESTAMP/1000), '%Y-%m-%d %H') = @DateTime 
                                    AND inv.INVERTERID IN @InverterIds
	                                GROUP BY FROM_UNIXTIME(inv.TIMESTAMP/1000, '%Y-%m-%d %H'), inv.INVERTERID) a
                                ON FROM_UNIXTIME(s.TIMESTAMP/1000, '%Y-%m-%d %H') = a.TIMESTAMP AND s.INVERTERID = a. INVERTERID
                                LEFT JOIN {db_name}.inverter i ON s.INVERTERID = i.InverterId
                                WHERE FROM_UNIXTIME(s.TIMESTAMP/1000, '%Y-%m-%d %H') = @DateTime
                                AND s.INVERTERID IN @InverterIds
                                GROUP BY DATE_FORMAT(FROM_UNIXTIME(s.TIMESTAMP/1000), '%Y-%m-%d %H'), s.INVERTERID
                                ";

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

        public async Task<DeviceInfo> GetFirstPyrheliometerInfo(int powerStationId, string db_name)
        {
            DeviceInfo result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT d.* 
                                    FROM {db_name}.device d 
                                    LEFT JOIN {db_name}.controller c ON d.ControllerId = c.Id AND c.Deleted = 0
                                    WHERE d.Enabled = 1 AND d.`Status` != 0 AND d.`Type` = 'PYR'
                                    AND d.PowerStationId = @PowerStationId
                                    ORDER BY d.ColName";

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

        public async Task<double> GetFirstPyrheliometerValue(string dateTime, string db_name, string table_name, string col_name)
        {
            double result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT CASE WHEN AVG({col_name}) IS NULL THEN 0
                                             WHEN AVG({col_name}) IS NOT NULL THEN AVG({col_name})
                                        END
                                    FROM {db_name}.{table_name}
                                    WHERE FROM_UNIXTIME(TIMESTAMP/1000, '%Y-%m-%d %H') = @DateTime";

                    result = await conn.QueryFirstOrDefaultAsync<double>(sql, new { DateTime = dateTime });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<InverterHistory>> CalcInverterHistoryDayDataByPowerStationId(string nowDay, string db_name, int powerStationId)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT 
                                inv.PowerStationId,
                                DATE_FORMAT(inv.TIMESTAMP, '%Y-%m-%d') AS TIMESTAMP,
                                inv.INVERTERID,
                                AVG(inv.Irradiance) AS Irradiance,
                                AVG(inv.AC1V) AS AC1V,
                                AVG(inv.AC1A) AS AC1A,
                                AVG(inv.AC1W) AS AC1W,
                                AVG(inv.AC1F) AS AC1F,
                                AVG(inv.AC1WH) AS AC1WH,
                                AVG(inv.AC2V) AS AC2V,
                                AVG(inv.AC2A) AS AC2A,
                                AVG(inv.AC2W) AS AC2W,
                                AVG(inv.AC2F) AS AC2F,
                                AVG(inv.AC2WH) AS AC2WH,
                                AVG(inv.AC3V) AS AC3V,
                                AVG(inv.AC3A) AS AC3A,
                                AVG(inv.AC3W) AS AC3W,
                                AVG(inv.AC3F) AS AC3F,
                                AVG(inv.AC3WH) AS AC3WH,
                                AVG(inv.DC1V) AS DC1V,
                                AVG(inv.DC1A) AS DC1A,
                                AVG(inv.DC1W) AS DC1W,
                                AVG(inv.DC1WH) AS DC1WH,
                                AVG(inv.DC2V) AS DC2V,
                                AVG(inv.DC2A) AS DC2A,
                                AVG(inv.DC2W) AS DC2W,
                                AVG(inv.DC2WH) AS DC2WH,
                                AVG(inv.DC3V) AS DC3V,
                                AVG(inv.DC3A) AS DC3A,
                                AVG(inv.DC3W) AS DC3W,
                                AVG(inv.DC3WH) AS DC3WH,
                                AVG(inv.DC4V) AS DC4V,
                                AVG(inv.DC4A) AS DC4A,
                                AVG(inv.DC4W) AS DC4W,
                                AVG(inv.DC4WH) AS DC4WH,
                                AVG(inv.DC5V) AS DC5V,
                                AVG(inv.DC5A) AS DC5A,
                                AVG(inv.DC5W) AS DC5W,
                                AVG(inv.DC5WH) AS DC5WH,
                                AVG(inv.PR) AS PR,
                                AVG(inv.RA1) AS RA1,
                                AVG(inv.RA2) AS RA2,
                                AVG(inv.RA3) AS RA3,
                                AVG(inv.RA4) AS RA4,
                                AVG(inv.RA5) AS RA5,
                                AVG(inv.KWH) AS KWH,
                                MAX(inv.TODAYKWH) AS TODAYKWH,
                                MAX(inv.TODAYKWH) / i.Capacity AS KWHKWP
                                FROM inverter_history_hour inv 
                                LEFT JOIN {db_name}.inverter i ON CONCAT('s', inv.INVERTERID) = i.InverterId
                                WHERE DATE_FORMAT(inv.TIMESTAMP, '%Y-%m-%d') = @NowDay 
                                AND PowerStationId = @PowerStationId
                                GROUP BY DATE_FORMAT(inv.TIMESTAMP, '%Y-%m-%d'), inv.INVERTERID";

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

        public async Task<int> AddInverterHistoryDayList(List<InverterHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "inverter_history_day");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<List<InverterHistory>> GetInverterHistoryByPowerStationIdAndMonth(string month, int powerStationId)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT * FROM inverter_history_month WHERE DATE_FORMAT(TIMESTAMP, '%Y-%m') = @Month AND PowerStationId = @PowerStationId";
                    result = (await conn.QueryAsync<InverterHistory>(sql, new { Month = month, PowerStationId = powerStationId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<List<InverterHistory>> CalcInverterHistoryMonthDataByPowerStationId(string month, string db_name, int powerStationId)
        {
            List<InverterHistory> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT 
                                inv.PowerStationId,
                                DATE_FORMAT(inv.TIMESTAMP, '%Y-%m') AS TIMESTAMP,
                                inv.INVERTERID,
                                AVG(inv.Irradiance) AS Irradiance,
                                AVG(inv.AC1V) AS AC1V,
                                AVG(inv.AC1A) AS AC1A,
                                AVG(inv.AC1W) AS AC1W,
                                AVG(inv.AC1F) AS AC1F,
                                AVG(inv.AC1WH) AS AC1WH,
                                AVG(inv.AC2V) AS AC2V,
                                AVG(inv.AC2A) AS AC2A,
                                AVG(inv.AC2W) AS AC2W,
                                AVG(inv.AC2F) AS AC2F,
                                AVG(inv.AC2WH) AS AC2WH,
                                AVG(inv.AC3V) AS AC3V,
                                AVG(inv.AC3A) AS AC3A,
                                AVG(inv.AC3W) AS AC3W,
                                AVG(inv.AC3F) AS AC3F,
                                AVG(inv.AC3WH) AS AC3WH,
                                AVG(inv.DC1V) AS DC1V,
                                AVG(inv.DC1A) AS DC1A,
                                AVG(inv.DC1W) AS DC1W,
                                AVG(inv.DC1WH) AS DC1WH,
                                AVG(inv.DC2V) AS DC2V,
                                AVG(inv.DC2A) AS DC2A,
                                AVG(inv.DC2W) AS DC2W,
                                AVG(inv.DC2WH) AS DC2WH,
                                AVG(inv.DC3V) AS DC3V,
                                AVG(inv.DC3A) AS DC3A,
                                AVG(inv.DC3W) AS DC3W,
                                AVG(inv.DC3WH) AS DC3WH,
                                AVG(inv.DC4V) AS DC4V,
                                AVG(inv.DC4A) AS DC4A,
                                AVG(inv.DC4W) AS DC4W,
                                AVG(inv.DC4WH) AS DC4WH,
                                AVG(inv.DC5V) AS DC5V,
                                AVG(inv.DC5A) AS DC5A,
                                AVG(inv.DC5W) AS DC5W,
                                AVG(inv.DC5WH) AS DC5WH,
                                AVG(inv.PR) AS PR,
                                AVG(inv.RA1) AS RA1,
                                AVG(inv.RA2) AS RA2,
                                AVG(inv.RA3) AS RA3,
                                AVG(inv.RA4) AS RA4,
                                AVG(inv.RA5) AS RA5,
                                AVG(inv.KWH) AS KWH,
                                SUM(inv.TODAYKWH) AS TODAYKWH,
                                SUM(inv.TODAYKWH) / i.Capacity AS KWHKWP
                                FROM inverter_history_day inv 
                                LEFT JOIN {db_name}.inverter i ON CONCAT('s', inv.INVERTERID) = i.InverterId
                                WHERE DATE_FORMAT(inv.TIMESTAMP, '%Y-%m') = @Month
                                AND inv.PowerStationId = @PowerStationId
                                GROUP BY DATE_FORMAT(inv.TIMESTAMP, '%Y-%m'), inv.INVERTERID";
                    result = (await conn.QueryAsync<InverterHistory>(sql, new { Month = month, PowerStationId = powerStationId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<A> Getonediv<A>(string where, string db_name, string table_name)
        {
            A result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $"SELECT sh.*,inv.*,con.Id,con.PowerStationId FROM {db_name}.{table_name} WHERE {where}";

                    result = await conn.QueryFirstOrDefaultAsync<A>(sql);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<int> AddInverterHistory(List<InverterHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "inverter_history_hour");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<int> AddInverterHistoryMonthList(List<InverterHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "inverter_history_month");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<int> UpdateInverterHistoryMonthList(List<InverterHistory> entity)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = @"UPDATE inverter_history_month SET
                                        KWH=@KWH,
                                        TODAYKWH=@TODAYKWH,
                                        KWHKWP=@KWHKWP
                                        WHERE PowerStationId = @PowerStationId
                                        AND TIMESTAMP LIKE CONCAT(@TIMESTAMP, '%')
                                        AND INVERTERID = @INVERTERID";

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<List<int>> GetPowerStationIdsByUserRole(MyUser myUser)
        {
            List<int> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = "";

                    if (myUser.Role.Layer == (int)RoleLayerEnum.CompanyAdmin)
                    {
                        sql += @$"SELECT ps.Id FROM power_station ps WHERE ps.Deleted = 0 AND ps.CompanyId = @CompanyId";
                    }
                    else if (myUser.Role.Layer == (int)RoleLayerEnum.CompanyUser)
                    {
                        sql += @$"SELECT op.PowerStationId FROM power_station_operation_personnel op WHERE op.Deleted = 0 AND UserId = @UserId";
                    }
                    else
                    {
                        sql += @$"SELECT ps.Id FROM power_station ps WHERE ps.Deleted = 0";
                    }

                    result = (await conn.QueryAsync<int>(sql, new { CompanyId = myUser.CompanyId, UserId = myUser.Id })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task AddWeatherObservation(List<WeatherObservation> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "weather_observation");

                        count = await conn.ExecuteAsync(sql, entity, trans);

                        trans.Commit();
                    }
                    catch (Exception exception)
                    {
                        trans.Rollback();
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }
        public async Task AddWeatherForecast(List<WeatherForecast> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "weather_forecast");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

        public async Task<NowWeather> SelectNowWeather(int CityId)
        {
            NowWeather result = new NowWeather();
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                var now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                try
                {
                    var sql = @$"SELECT wf.PoP, wd.WeatherKey
                                FROM city c 
                                LEFT JOIN weather_forecast wf ON wf.LocationName = c.`Name` 
                                LEFT JOIN weather_description wd ON wd.WeatherName = wf.Wx  
                                WHERE c.Priority = {CityId} AND '{now}' BETWEEN wf.StartTime AND wf.EndTime ORDER BY wf.CreatedAt desc";

                    result = await conn.QueryFirstOrDefaultAsync<NowWeather>(sql);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<MoneyAndCarbon> GetMoneyAndCarbonWithHistoryHour(int powerstationId, string dateTime, int type)
        {
            MoneyAndCarbon result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = "";
                    if (type == 0)
                    {
                        sql = $@"SELECT SUM(MONEY) AS MONEY, SUM(CARBON) AS CARBON FROM power_station_history_hour 
                                    WHERE PowerStationId = {powerstationId} AND DATE_FORMAT(`TIMESTAMP`,'%Y-%m') = '{dateTime}' ";
                    }
                    else
                    {
                        sql = $@"SELECT SUM(MONEY) AS MONEY, SUM(CARBON) AS CARBON FROM power_station_history_hour 
                                    WHERE PowerStationId = {powerstationId} AND DATE_FORMAT(`TIMESTAMP`,'%Y-%m-%d') = '{dateTime}' ";
                    }
                    result = await conn.QueryFirstOrDefaultAsync<MoneyAndCarbon>(sql);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<MoneyAndCarbon> GetLastMoneyAndCarbonInHour(int powerstationId, int type, string time)
        {
            MoneyAndCarbon result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                var tablename = "";
                if (type == 0)
                {
                    tablename = "power_station_history_hour";
                }
                else if (type == 1)
                {
                    tablename = "power_station_history_day";
                }
                else
                {
                    tablename = "power_station_history_month";
                }


                try
                {
                    var sql = "";
                    if (type == 0)
                    {
                        var time2 = time.Split(' ');
                        sql = $@"SELECT(SELECT TODAYMONEY FROM power_station_history_hour WHERE PowerStationId = {powerstationId} AND DATE_FORMAT(`TIMESTAMP`, '%Y-%m-%d') = '{time2[0]}' order by TIMESTAMP desc limit 1) AS TODAYMONEY,
                        TOTALMONEY,
                        (SELECT TODAYCARBON FROM power_station_history_hour WHERE PowerStationId = {powerstationId} AND DATE_FORMAT(`TIMESTAMP`, '%Y-%m-%d') = '{time2[0]}' order by TIMESTAMP desc limit 1) AS TODAYCARBON,
                         TOTALCARBON
                        FROM power_station_history_hour WHERE PowerStationId = {powerstationId} order by TIMESTAMP desc limit 1";
                    }
                    else
                    {
                        sql = $@"SELECT TOTALMONEY,TOTALCARBON FROM {tablename} 
                                    WHERE PowerStationId = {powerstationId} order by TIMESTAMP desc limit 1";
                    }

                    result = await conn.QueryFirstOrDefaultAsync<MoneyAndCarbon>(sql);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<string> ExistTable(string db_name, string table_name)
        {
            string result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = @DBName AND TABLE_NAME = @TableName;";

                    result = await conn.QueryFirstOrDefaultAsync<string>(sql, new { DBName = db_name, TableName = table_name });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<SensorAvgHistory> CalcSensorAvgHistory(string dateTime, string table_name)
        {
            SensorAvgHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sensor_str = "";
                    for (var i = 1; i <= 50; i++)
                    {
                        if (i < 10)
                        {
                            sensor_str += "AVG(SENSORAVG" + "0" + i.ToString() + ") AS SENSORAVG" + "0" + i.ToString() + ",";
                        }
                        else
                        {
                            sensor_str += "AVG(SENSORAVG" + i.ToString() + ") AS SENSORAVG" + i.ToString() + ",";
                        }
                    }

                    sensor_str = sensor_str.Substring(0, sensor_str.Length - 1);

                    var sql = @$"SELECT
                                    FROM_UNIXTIME(timestamp / 1000, '%Y-%m-%d %H') AS TIMESTAMP,
                                    {sensor_str}
                                    FROM {table_name}
                                    WHERE FROM_UNIXTIME(timestamp / 1000, '%Y-%m-%d %H') = @DateTime
                                    GROUP BY FROM_UNIXTIME(timestamp / 1000, '%Y-%m-%d %H')";


                    result = await conn.QueryFirstOrDefaultAsync<SensorAvgHistory>(sql, new { DateTime = dateTime });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<int> AddSensorAvgHistory(List<SensorAvgHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "sensoravg_history_hour");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

            return count;
        }

        public async Task<SensorAvgHistory> CalcSensorAvgDayDataByPowerStationId(string nowDay, int powerStationId)
        {
            SensorAvgHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sensor_str = "";
                    for (var i = 1; i <= 50; i++)
                    {
                        if (i < 10)
                        {
                            sensor_str += "AVG(SENSORAVG" + "0" + i.ToString() + ") AS SENSORAVG" + "0" + i.ToString() + ",";
                        }
                        else
                        {
                            sensor_str += "AVG(SENSORAVG" + i.ToString() + ") AS SENSORAVG" + i.ToString() + ",";
                        }
                    }

                    sensor_str = sensor_str.Substring(0, sensor_str.Length - 1);

                    var sql = @$"SELECT
                                    PowerStationId,
                                    DATE_FORMAT(TIMESTAMP, '%Y-%m-%d') AS TIMESTAMP,
                                    {sensor_str}
                                    FROM sensoravg_history_hour
                                    WHERE PowerStationId = @PowerStationId
                                    AND DATE_FORMAT(TIMESTAMP, '%Y-%m-%d') = @NowDay
                                    GROUP BY DATE_FORMAT(timestamp, '%Y-%m-%d')";


                    result = await conn.QueryFirstOrDefaultAsync<SensorAvgHistory>(sql, new { PowerStationId = powerStationId, NowDay = nowDay });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<int> AddSensorAvgHistoryDayList(List<SensorAvgHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "sensoravg_history_day");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<SensorAvgHistory> GetSensorAvgHistoryByPowerStationIdAndMonth(string month, int powerStationId)
        {
            SensorAvgHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = $@"SELECT * FROM sensoravg_history_month WHERE DATE_FORMAT(TIMESTAMP, '%Y-%m') = @Month AND PowerStationId = @PowerStationId";
                    result = await conn.QueryFirstOrDefaultAsync<SensorAvgHistory>(sql, new { Month = month, PowerStationId = powerStationId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<SensorAvgHistory> CalcSensorAvgHistoryMonthDataByPowerStationId(string month, int powerStationId)
        {
            SensorAvgHistory result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sensor_str = "";
                    for (var i = 1; i <= 50; i++)
                    {
                        if (i < 10)
                        {
                            sensor_str += "AVG(SENSORAVG" + "0" + i.ToString() + ") AS SENSORAVG" + "0" + i.ToString() + ",";
                        }
                        else
                        {
                            sensor_str += "AVG(SENSORAVG" + i.ToString() + ") AS SENSORAVG" + i.ToString() + ",";
                        }
                    }

                    sensor_str = sensor_str.Substring(0, sensor_str.Length - 1);

                    var sql = @$"SELECT
                                    PowerStationId,
                                    DATE_FORMAT(TIMESTAMP, '%Y-%m') AS TIMESTAMP,
                                    {sensor_str}
                                    FROM sensoravg_history_day
                                    WHERE PowerStationId = @PowerStationId
                                    AND DATE_FORMAT(TIMESTAMP, '%Y-%m')  = @Month
                                    GROUP BY DATE_FORMAT(TIMESTAMP, '%Y-%m')";

                    result = await conn.QueryFirstOrDefaultAsync<SensorAvgHistory>(sql, new { Month = month, PowerStationId = powerStationId });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task<int> AddSensorAvgHistoryMonthList(List<SensorAvgHistory> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "sensoravg_history_month");

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }

        public async Task<int> UpdateSensorAvgHistoryMonthList(List<SensorAvgHistory> entity)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sensor_str = "";
                        for (var i = 1; i <= 50; i++)
                        {
                            if (i < 10)
                            {
                                sensor_str += "SENSORAVG" + "0" + i.ToString() + " = @SENSORAVG" + "0" + i.ToString() + ",";
                            }
                            else
                            {
                                sensor_str += "SENSORAVG" + i.ToString() + " = @SENSORAVG" + i.ToString() + ",";
                            }

                        }

                        sensor_str = sensor_str.Substring(0, sensor_str.Length - 1);

                        string sql = @$"UPDATE sensoravg_history_month SET
                                        {sensor_str}
                                        WHERE PowerStationId = @PowerStationId
                                        AND TIMESTAMP LIKE CONCAT(@TIMESTAMP, '%')";

                        count = await conn.ExecuteAsync(sql, entity, trans);

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

                return count;
            }
        }
    }
}
