using Dapper;
using Repository.BackendRepository.Interface;
using Repository.Helper;
using System;
using System.Text;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Transactions;
using Repository.Models;
using System.Data.SqlTypes;
using Microsoft.Extensions.Primitives;

namespace Repository.BackendRepository.Implement
{
    public class NiagaraDataSynchronizeRepository : BackendRepository, INiagaraDataSynchronizeRepository
    {
        public NiagaraDataSynchronizeRepository(IDatabaseHelper databaseHelper) : base(databaseHelper)
        {
        }

        /// <summary>
        /// 更新import_niagara_tag資料表
        /// </summary>
        /// <param name="ds"></param>
        /// <param name="building"></param>
        /// <returns></returns>
        public async Task InsertNiagaraTagList(List<Device_value> ds, string building)
        {
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_tag` (
                                 `id` int(11) NOT NULL AUTO_INCREMENT,
                                 `db_tags` varchar(50) DEFAULT NULL,
                                 `niagara_tags` varchar(50) DEFAULT NULL,
                                 `device_area_tag` varchar(50) DEFAULT NULL,
                                 `device_building_tag` varchar(50) DEFAULT NULL,
                                 `device_system_tag` varchar(50) DEFAULT NULL,
                                 `device_name_tag` varchar(50) DEFAULT NULL,
                                 `device_floor_tag` varchar(50) DEFAULT NULL,
                                 `device_master_tag` varchar(50) DEFAULT NULL,
                                 `device_last_name_tag` varchar(50) DEFAULT NULL,
                                 `device_serial_tag` varchar(50) DEFAULT NULL,
                                 `atDateTime` datetime(1) DEFAULT NULL,
                                 `is_used` smallint(1) DEFAULT 0,
                                 PRIMARY KEY (`id`)
                               ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
                        await conn.ExecuteAsync(sql);
                        sql = "delete from import_niagara_tag where device_building_tag = '" + building + "'";
                        await conn.ExecuteAsync(sql);

                        //N4資料groupBy後放入import_niagara_tag資料表
                        var ds2 = ds.GroupBy(x => new
                        {
                            tag_name2 = x.tag_name,
                            displayName2 = x.displayName
                        }).Select(x => new Device_value
                        {
                            tag_name = x.Key.tag_name2,
                            displayName = x.Key.displayName2
                        });

                        StringBuilder sb = new StringBuilder();

                        foreach (var row in ds2)
                        {
                            if (string.IsNullOrEmpty(row.tag_name)) continue;
                            string[] arrTag = row.tag_name.Split('_');
                            
                            if (arrTag.Length == 8)
                            {
                                sb.Append($@" insert into import_niagara_tag(niagara_tags, device_area_tag, device_building_tag, device_system_tag,
                                    device_name_tag, device_floor_tag, device_master_tag, device_last_name_tag, device_serial_tag, device_full_name, atDateTime) values('" +
                                    row.tag_name + "', '" +
                                    arrTag[0] + "', '" +
                                    arrTag[1] + "', '" +
                                    arrTag[2] + "', '" +
                                    arrTag[3] + "', '" +
                                    arrTag[4] + "', '" +
                                    arrTag[5] + "', '" +
                                    arrTag[6] + "', '" +
                                    arrTag[7] + "', '" +
                                    row.displayName + "', " +
                                    "now());");
                            }
                        }
                        if (sb.Length > 0)
                        {
                            await conn.ExecuteAsync(sb.ToString());
                            sb.Clear();
                        }
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 更新import_niagara_tag資料表
        /// </summary>
        /// <param name="ds"></param>
        /// <param name="building"></param>
        /// <returns></returns>
        public async Task InsertItemFromNiagara(List<ImpNiaItem> ds, string building)
        {
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        #region 刪除 import_niagara_item資料表中選取的棟別
                        string sql = @"CREATE TABLE IF NOT EXISTS `import_niagara_item` (
                              `id` int(11) NOT NULL AUTO_INCREMENT,
                              `device_area_tag` varchar(50) DEFAULT NULL,
                              `device_building_tag` varchar(50) DEFAULT NULL,
                              `device_system_tag` varchar(50) DEFAULT NULL,
                              `device_name_tag` varchar(50) DEFAULT NULL,
                              `device_point_name` varchar(50) DEFAULT NULL,
                              `check_status` varchar(50) DEFAULT NULL,
                              `parent_path` varchar(50) DEFAULT NULL,
                              `full_name` varchar(50) DEFAULT NULL,
                              PRIMARY KEY (`id`)
                            ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
                        await conn.ExecuteAsync(sql);
                        sql = "delete from import_niagara_item where device_building_tag = '" + building + "'";
                        await conn.ExecuteAsync(sql);
                        #endregion

                        StringBuilder sb = new StringBuilder();
                        #region 放入import_niagara_item資料表
                        foreach (var row in ds)
                        {
                            sb.Append($@" insert import_niagara_item(device_area_tag, device_building_tag, device_system_tag, device_name_tag, device_point_name, parent_path, full_name)
                                        values('"+
                                            row.device_area_tag + "', '" +
                                            row.device_building_tag + "', '" +
                                            row.device_system_tag + "', '" +
                                            row.device_name_tag + "', '" +
                                            row.device_point_name + "', '" +
                                            row.parent_path + "', '" +
                                            row.full_name + "'" +
                                            ");");
                        }
                        
                        if (sb.Length > 0)
                        {
                            await conn.ExecuteAsync(sb.ToString());
                            sb.Clear();
                        }
                        #endregion
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }
        /// <summary>
        /// 比對 device
        /// </summary>
        /// <returns></returns>
        public async Task DeviceComparison()
        {
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        List<NiagaraTags> result;
                        StringBuilder sb = new StringBuilder();
                        StringBuilder sb2 = new StringBuilder();
                        sb.Append($@" SELECT m.*
                               FROM import_niagara_tag m
                               LEFT JOIN device d
                               ON m.niagara_tags = d.device_number
                               WHERE d.device_number IS NULL");
                        result = (await conn.QueryAsync<NiagaraTags>(sb.ToString())).ToList<NiagaraTags>();

                        sb.Clear();
                        //新增至device, is_link = 1
                        if (result.Count > 0)
                        {
                            var result2 = result.GroupBy(x => new
                            {
                                device_building_tag2 = x.device_building_tag,
                                device_system_tag2 = x.device_system_tag,
                                device_name_tag2 = x.device_name_tag
                            }).Select(x => new Device_item8
                            {
                                device_building_tag = x.Key.device_building_tag2,
                                device_system_tag = x.Key.device_system_tag2,
                                device_name_tag = x.Key.device_name_tag2
                            });

                            foreach (var data in result)
                            {
                                sb.Append($@" insert device(device_guid, deleted, status, priority, is_link, device_area_tag, 
                                    device_building_tag, device_system_tag, device_name_tag, full_name, device_floor_tag, device_master, 
                                    device_last_name, device_serial_tag, device_number, device_system_category_layer3, created_at, updated_at)
                                values(uuid(), 0, 1, 0, 1, '" +
                                        data.device_area_tag + "', '" +
                                        data.device_building_tag + "', '" +
                                        data.device_system_tag + "', '" +
                                        data.device_name_tag + "', '" +
                                        data.device_full_name + "', '" + 
                                        data.device_floor_tag + "', '" +
                                        data.device_master_tag + "', '" +
                                        data.device_last_name_tag + "', '" +
                                        data.device_serial_tag + "', '" +
                                        data.niagara_tags + "', '" +
                                        data.device_system_tag + "', now(), now() );");
                            }

                            foreach (var data in result2)
                            {
                                var sqlString = new StringBuilder();
                                sqlString.Append("select * from device_kind where device_building_tag = '" + data.device_building_tag + "' and device_system_tag = '" + data.device_system_tag + "' and device_name_tag = '" + data.device_name_tag + "'");
                                var dk = (await conn.QueryAsync<device_kind>(sqlString.ToString())).ToList<device_kind>();

                                if (dk.Count == 0)
                                {
                                    sb2.Append($@"INSERT device_kind (device_kind_guid, device_building_tag, device_system_tag, device_name_tag, 
                                        device_normal_flashing, device_close_flashing, device_error_flashing, device_error_independent, 
                                        created_by, created_at)
                                        VALUES (uuid(), '" + data.device_building_tag + "', '" + data.device_system_tag + "', '" + data.device_name_tag +
                                                "', 0, 0, 1, 0, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now());");
                                }
                            }

                            if (sb.Length > 0)
                            {
                                await conn.ExecuteAsync(sb.ToString());
                                await conn.ExecuteAsync(sb2.ToString());
                                sb.Clear();
                                sb2.Clear();
                            }
                        }

                        //device有,niagara沒有,is_link 更新成 0
                        sb.Append($@" SET SQL_SAFE_UPDATES = 0;
                              UPDATE device d LEFT JOIN import_niagara_tag m ON d.device_number = m.niagara_tags
                              SET d.is_link = 0
                              WHERE m.niagara_tags IS NULL");
                        await conn.ExecuteAsync(sb.ToString());

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

        /// <summary>
        /// 比對 device_item
        /// </summary>
        /// <returns></returns>
        public async Task DeviceItemComparison()
        {
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        List<NiagaraTagsForItem> result;
                        StringBuilder sb = new StringBuilder();
                        sb.Append($@" SELECT m.*
                              FROM import_niagara_item m
                              LEFT JOIN device_item d
                              ON m.device_system_tag = d.device_system_tag and m.device_name_tag = d.device_name_tag and m.device_point_name = d.points
                              WHERE d.points IS NULL");
                        result = (await conn.QueryAsync<NiagaraTagsForItem>(sb.ToString())).ToList<NiagaraTagsForItem>();

                        sb.Clear();
                        //新增至device, is_link = 1
                        if (result.Count > 0)
                        {
                            foreach (var data in result)
                            {
                                var isControll = 0;
                                var isBool = 0;
                                if (data.device_point_name == "ER" || data.device_point_name == "AL" || data.device_point_name == "ST")
                                {
                                    isControll = 1;
                                }
                                if (data.device_point_name == "ER" || data.device_point_name == "ST")
                                {
                                    isBool = 1;
                                }
                                sb.Append($@"insert device_item(deleted, points, is_show, is_show_riserDiagram, is_controll, is_bool, is_link, is_show_history, 
                                    device_system_tag, device_name_tag, full_name, parent_path, created_at, updated_at)
                                    VALUES (0, '" +
                                            data.device_point_name + "', 1, 0, " +
                                            isControll + "," +
                                            isBool + ", 1, 1, '" +
                                            data.device_system_tag + "', '" +
                                            data.device_name_tag + "', " +
                                            data.full_name + "', " +
                                            data.parent_path + "', " +
                                            "now(), now());");
                            }
                            if (sb.Length > 0)
                            {
                                await conn.ExecuteAsync(sb.ToString());
                                sb.Clear();
                            }
                        }
                        //device有,niagara沒有,is_link 更新成 0
                        sb.Append($@" SET SQL_SAFE_UPDATES = 0;
                              UPDATE device_item d LEFT JOIN import_niagara_item m 
                              ON d.device_system_tag = m.device_system_tag and d.device_name_tag = m.device_name_tag and d.points = m.device_point_name
                              SET d.is_link = 0, d.is_show_history = 0
                              WHERE m.device_point_name IS NULL");
                        await conn.ExecuteAsync(sb.ToString());
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 新增資料至 buildingMenu
        /// </summary>
        /// <returns></returns>
        public async Task InsertBuildingMenu()
        {
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        List<NiagaraTags> result;
                        StringBuilder sb = new StringBuilder();
                        #region comparison building_menu and import_niagara_tag
                        sb.Append($@" select a.* from (
                              	select  device_building_tag, device_system_tag, device_name_tag
                              	from import_niagara_tag
                              	group by device_building_tag, device_system_tag, device_name_tag 
                              ) AS a
                              LEFT JOIN building_menu b
                              ON a.device_building_tag = b.device_building_tag and a.device_system_tag = b.device_system_tag and a.device_name_tag = b.sub_system_tag
                              WHERE b.device_building_tag IS NULL");
                        result = (await conn.QueryAsync<NiagaraTags>(sb.ToString())).ToList<NiagaraTags>();
                        #endregion
                        sb.Clear();

                        if (result.Count > 0)
                        {
                            foreach (var data in result)
                            {
                                StringBuilder sqlString = new StringBuilder();
                                sqlString.Append(@"select * from building_menu where building_tag = '" + data.device_building_tag + "' and main_system_tag = '" + data.device_system_tag + "' and sub_system_tag = '" + data.device_name_tag + "'");
                                var bm = (await conn.QueryAsync<building_menu>(sqlString.ToString())).ToList<building_menu>();

                                #region insert building_menu
                                if (bm.Count == 0)
                                {
                                    sb.Append(@"insert building_menu(building_tag, main_system_tag, sub_system_tag, device_building_tag, device_system_tag,
                                  is_link, created_by, created_at, updated_by, updated_at)
                                  VALUES ('" + data.device_building_tag + "', '" +
                                          data.device_system_tag + "', '" +
                                          data.device_name_tag + "', '" +
                                          data.device_building_tag + "', '" +
                                          data.device_system_tag + "', " +
                                          "1, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now() );");
                                }
                                #endregion
                            }
                            if (sb.Length > 0)
                            {
                                await conn.ExecuteAsync(sb.ToString());
                                sb.Clear();
                            }
                        }
                        //building_menu有,import_niagara_tag沒有,is_link 更新成 0
                        sb.Append($@" SET SQL_SAFE_UPDATES = 0;
                              UPDATE building_menu b LEFT JOIN (
                              	select  device_building_tag, device_system_tag, device_name_tag
                              	from import_niagara_tag
                              	group by device_building_tag, device_system_tag, device_name_tag
                              ) AS a ON b.device_building_tag = a.device_building_tag 
                              and a.device_system_tag = b.device_system_tag and a.device_name_tag = b.sub_system_tag
                              SET b.is_link = 0
                              WHERE b.device_building_tag IS NULL");
                        await conn.ExecuteAsync(sb.ToString());
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 新增資料至 subSystemFloor
        /// </summary>
        /// <returns></returns>
        public async Task InsertSubSystemFloor()
        {
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        List<NiagaraTags> result;
                        StringBuilder sb = new StringBuilder();
                        #region comparison sub_system_floor and import_niagara_tag
                        sb.Append($@" select a.* from (
                              	select  device_building_tag, device_system_tag, device_name_tag, device_floor_tag
                              	from import_niagara_tag
                              	group by device_building_tag, device_system_tag, device_name_tag, device_floor_tag
                              ) AS a
                              LEFT JOIN sub_system_floor b
                              ON a.device_building_tag = b.building_tag and a.device_system_tag = b.main_system_tag and a.device_name_tag = b.sub_system_tag and a.device_floor_tag = b.floor_tag
                              WHERE b.building_tag IS NULL");
                        result = (await conn.QueryAsync<NiagaraTags>(sb.ToString())).ToList<NiagaraTags>();
                        #endregion

                        sb.Clear();
                        if (result.Count > 0)
                        {
                            foreach (var data in result)
                            {
                                #region insert building_menu
                                sb.Append(@"insert sub_system_floor(building_tag, main_system_tag, sub_system_tag, floor_tag,  
                                    is_link, created_by, created_at, updated_by, updated_at)
                                    VALUES ('" +
                                            data.device_building_tag + "', '" +
                                            data.device_system_tag + "', '" +
                                            data.device_name_tag + "', '" +
                                            data.device_floor_tag + "', " +
                                            "1, 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now(), 'B43E3CA7-96DD-4FC7-B6E6-974ACC3B0878', now());");
                                #endregion
                            }
                            if (sb.Length > 0)
                            {
                                await conn.ExecuteAsync(sb.ToString());
                                sb.Clear();
                            }
                        }
                        //building_menu有,import_niagara_tag沒有,is_link 更新成 0
                        sb.Append($@" SET SQL_SAFE_UPDATES = 0;
                              UPDATE sub_system_floor b LEFT JOIN (
                              	select  device_building_tag, device_system_tag, device_name_tag, device_floor_tag
                              	from import_niagara_tag
                              	group by device_building_tag, device_system_tag, device_name_tag, device_floor_tag
                              ) AS a ON b.building_tag = a.device_building_tag 
                              and b.main_system_tag = a.device_system_tag and b.sub_system_tag = a.device_name_tag and b.floor_tag = a.device_floor_tag
                              SET b.is_link = 0
                              WHERE b.building_tag IS NULL");
                        await conn.ExecuteAsync(sb.ToString());
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {  
                        conn.Close();
                    }
                }
            }
        }
        /// <summary>
        /// 檢查device內FullName為空的值,以device_Name取代
        /// </summary>
        /// <returns></returns>
        public async Task CheckFullNameEmptyReplaceByDeviceName()
        {
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.Append("update device set full_name=device_number where full_Name='';");
                        await conn.ExecuteAsync(sb.ToString());
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 檢查device_item內FullName為空的值,以points取代
        /// </summary>
        /// <returns></returns>
        public async Task ItemCheckFullNameEmptyReplaceByDeviceName()
        {

            //檢查是否有空值
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.Append("update device_item set full_name = points where full_Name = '''''';");
                        await conn.ExecuteAsync(sb.ToString());
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }

            }
        }

        /// <summary>
        /// 檢查device的full_name與niagara device_full_name不同者 覆蓋
        /// </summary>
        /// <returns></returns>
        public async Task CheckDiffFullNameAndCover()
        {
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.Append("update device d inner JOIN import_niagara_tag m ON m.niagara_tags = d.device_number " +
                            "set d.full_name=m.device_full_name " +
                            "where m.device_full_name<>d.full_name;");
                        await conn.ExecuteAsync(sb.ToString());
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }

            }
        }


        /// <summary>
        /// 比對 device_item full_name 與 import_niagara_item full_name是否相同
        /// 不同則覆蓋
        /// </summary>
        /// <returns></returns>
        public async Task CheckItemDiffFullNameAndCover()
        {
            //檢查
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.Append("update device_item d " +
                            "inner JOIN import_niagara_item m ON " +
                            "m.device_system_tag = d.device_system_tag and " +
                            "m.device_name_tag = d.device_name_tag and " +
                            "m.device_point_name = d.points " +
                            "set d.full_name=m.full_name " +
                            "where d.full_name<>m.full_name;");
                        await conn.ExecuteAsync(sb.ToString());
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 先將device_ite的is_show_history全部關掉
        /// 根據niagara輸入資料來決定要開哪些點
        /// </summary>
        /// <returns></returns>
        public async Task CheckItemIsShowHistory()
        {
            //先將所有is_show_history關閉,niagara有的才開啟
            using (IDbConnection conn = GetDbConnection())
            {
                conn.Open();
                using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        StringBuilder sb = new StringBuilder();
                        //先全部關閉
                        sb.Append("update device_item set is_show_history=0;");
                        sb.Append("update device_item set is_show_history = 1 " +
                            "WHERE(device_system_tag, device_name_tag, points) IN " +
                            "(select  distinct  device_system_tag, device_name_tag, device_point_name From import_niagara_item);");
                        await conn.ExecuteAsync(sb.ToString());
                    }
                    catch (Exception exception)
                    {
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }
    }
}