using Backend.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Repository.BackendRepository.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;

namespace Backend.Controllers
{
    public class DeviceImportController : MybaseController<DeviceImportController>
    {
        private readonly IBackendRepository backendRepository;
        private readonly IDeviceImportRepository deviceImportRepository;

        public DeviceImportController(IBackendRepository backendRepository, IDeviceImportRepository deviceImportRepository)
        {
            this.backendRepository = backendRepository;
            this.deviceImportRepository = deviceImportRepository;
        }


        public IActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 設備匯入列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<DeviceImport>>> RawDataList()
        {
            ApiResult<List<DeviceImport>> apiResult = new ApiResult<List<DeviceImport>>();
            List<DeviceImport> deviceImports = new List<DeviceImport>();

            try
            {
                deviceImports = await backendRepository.GetAllAsync<DeviceImport>("device_import_temp", null, null, "device_result DESC,created_at DESC");

                apiResult.Code = "0000";
                apiResult.Data = deviceImports;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }


        [HttpPost]
        public async Task<ApiResult<string>> ImportRawDataFile(IFormFile[] import_files)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                Dictionary<string, IWorkbook> workbooks = new Dictionary<string, IWorkbook>();

                //List<IWorkbook> workbooks = new List<IWorkbook>();

                #region 檢驗各檔案是否正確
                foreach (var import_file in import_files)
                {
                    IWorkbook workbook;

                    var filename_ext = Path.GetExtension(import_file.FileName).ToLower();

                    if (filename_ext == ".xls")
                    {
                        workbook = new HSSFWorkbook(import_file.OpenReadStream());
                        workbooks.Add($"{import_file.FileName}", workbook);
                    }
                    else if (filename_ext == ".xlsx")
                    {
                        workbook = new XSSFWorkbook(import_file.OpenReadStream());
                        workbooks.Add($"{import_file.FileName}", workbook);
                    }
                    else
                    {
                        workbook = null;
                    }

                    if (workbook == null)
                    {
                        apiResult.Code = "9998";
                        apiResult.Msg = $"{import_file.FileName}該檔案失效,請重新操作。";

                        return apiResult;
                    }
                }
                #endregion

                List<Dictionary<string, object>> deviceImports = new List<Dictionary<string, object>>();

                //抓取系統類別(以供驗證判斷)
                var sWhere = @$"deleted = 0 AND system_type = @system_type";
                var system_category_param = new { system_type = "device_system_category_layer3" };
                var system_categories_layer3 = await backendRepository.GetAllAsync<Variable>("variable", sWhere, system_category_param);

                var disaster_param = new { system_type = "disaster" };
                var disasters = await backendRepository.GetAllAsync<Variable>("variable", sWhere, disaster_param);
                var temp_building = ""; //預設的棟別(檢查用,整份excel需相同),目前只針對單一檔案情況,如後續有需再改成多檔情況。

                #region 抓取每個檔案的資料
                foreach (var keyValuePair in workbooks)
                {
                    IWorkbook workbook = keyValuePair.Value;

                    var total_sheet = workbook.NumberOfSheets;
                    for (var sheet_num = 2; sheet_num < total_sheet - 1; sheet_num++)
                    {
                        var tags_name_index = -1;
                        var system_category_index = -1; //系統類別
                        var disaster_index = -1; //緊急應變程序(等同災害類別)
                        var sheet = workbook.GetSheetAt(sheet_num);

                        //表頭
                        IRow header = sheet.GetRow(sheet.FirstRowNum);
                        List<int> columns = new List<int>();
                        if (header != null)
                        {
                            for (int i = 0; i < header.LastCellNum; i++)
                            {
                                ICell cell = header.GetCell(i);
                                if (cell != null)
                                {
                                    var header_str = cell.ToString().ToLower();
                                    if (!string.IsNullOrEmpty(header_str) && header_str == "tags name")
                                    {
                                        tags_name_index = i;
                                    }
                                    if (!string.IsNullOrEmpty(header_str) && header_str == "系統類別")
                                    {
                                        system_category_index = i;
                                    }
                                    if (!string.IsNullOrEmpty(header_str) && header_str == "系統程式軟體")
                                    {
                                        IRow sub_header = sheet.GetRow(1);

                                        for (int j = 0; j < sub_header.LastCellNum; j++)
                                        {
                                            ICell sub_cell = sub_header.GetCell(j);
                                            var sub_header_str = sub_cell.ToString().ToLower();
                                            if (!string.IsNullOrEmpty(sub_header_str) && sub_header_str == "緊急應變程序")
                                            {
                                                disaster_index = j;
                                            }
                                        }
                                    }

                                    if (tags_name_index > 0 && system_category_index > 0 && disaster_index > 0)
                                    {
                                        break;
                                    }
                                }
                            }
                        }

                        //資料
                        if (tags_name_index < 0 || system_category_index < 0 || disaster_index < 0)
                        {
                            List<string> errMsg = new List<string>();
                            var result = $@"查無[{keyValuePair.Key}]在[{workbook.GetSheetName(sheet_num)}]分頁的";

                            if (tags_name_index < 0)
                            {
                                errMsg.Add($@"[tags name]");
                            }

                            if (system_category_index < 0)
                            {
                                errMsg.Add($@"[系統類別]");
                            }

                            if (disaster_index < 0)
                            {
                                errMsg.Add($@"[緊急應變程序]");
                            }

                            Dictionary<string, object> deviceImport = new Dictionary<string, object>()
                            {
                                { "@device_number", null},
                                { "@device_system_category_layer3", null},
                                { "@device_disaster", null},
                                { "@device_result", result + String.Join("、", errMsg)}
                            };

                            deviceImports.Add(deviceImport);
                        }
                        else
                        {
                            for (var i = sheet.FirstRowNum + 2; i < sheet.LastRowNum; i++)
                            {

                                IRow row = sheet.GetRow(i);
                                if (row != null)
                                {
                                    List<string> errMsg = new List<string>();
                                    Dictionary<string, object> deviceImport = new Dictionary<string, object>();

                                    ICell tags_name_cell = row.GetCell(tags_name_index);
                                    if (tags_name_cell != null)
                                    {
                                        var tempData = tags_name_cell.ToString().Trim();
                                        var system_category = string.Empty;
                                        var disaster = string.Empty;
                                        if (!string.IsNullOrEmpty(tempData))
                                        {
                                            var arr_tempData = tempData.Split('_');

                                            #region tags name驗證條件
                                            if (string.IsNullOrEmpty(temp_building)) //抓第一筆當作該excel 比對棟別的依據
                                            {
                                                temp_building = arr_tempData[0];
                                            }
                                            else
                                            {
                                                if (temp_building != arr_tempData[0])
                                                {
                                                    errMsg.Add("資料棟別錯誤");
                                                }
                                            }

                                            if (arr_tempData.Length != 5)
                                            {
                                                errMsg.Add("資料格式錯誤");
                                            }

                                            if (arr_tempData[arr_tempData.Length - 1].Contains('~'))
                                            {
                                                errMsg.Add("設備流水號格式錯誤");
                                            }

                                            if (arr_tempData[arr_tempData.Length - 1].Split('~').Length > 2)
                                            {
                                                errMsg.Add("設備流水號格式錯誤");
                                            }
                                            #endregion

                                            #region 系統類別驗證條件
                                            ICell system_category_cell = row.GetCell(system_category_index);
                                            if (system_category_cell == null)
                                            {
                                                errMsg.Add(@"該設備的[系統類別]未填值");
                                            }
                                            else
                                            {
                                                system_category = system_category_cell.ToString().Trim();
                                                if (!string.IsNullOrEmpty(system_category))
                                                {
                                                    var exist = system_categories_layer3.Exists(x => x.system_value == system_category);
                                                    if (!exist)
                                                    {
                                                        errMsg.Add(@"該設備的[系統類別]不存在");
                                                    }
                                                }
                                                else
                                                {
                                                    errMsg.Add(@"該設備的[系統類別]未填值");
                                                }
                                            }
                                            #endregion

                                            #region 緊急應變程序驗證條件
                                            ICell disaster_cell = row.GetCell(disaster_index);
                                            if (disaster_cell == null)
                                            {
                                                errMsg.Add(@"該設備的[緊急應變程序]未填值");
                                            }
                                            else
                                            {
                                                disaster = disaster_cell.ToString().Trim();
                                                if (!string.IsNullOrEmpty(disaster))
                                                {
                                                    if (disaster != "0")
                                                    {
                                                        var exist = disasters.Exists(x => x.system_value == disaster);
                                                        if (!exist)
                                                        {
                                                            errMsg.Add(@"該設備的[緊急應變程序]不存在");
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    errMsg.Add(@"該設備的[緊急應變程序]未填值");
                                                }
                                            }
                                            #endregion

                                            if (errMsg.Count > 0)
                                            {
                                                deviceImport.Add("@device_number", tempData);
                                                deviceImport.Add("@device_system_category_layer3", system_category);
                                                deviceImport.Add("@device_disaster", disaster);
                                                deviceImport.Add("@device_result", String.Join(", ", errMsg));
                                            }
                                            else
                                            {
                                                deviceImport.Add("@device_number", tempData);
                                                deviceImport.Add("@device_system_category_layer3", system_category);
                                                deviceImport.Add("@device_disaster", disaster);
                                                deviceImport.Add("@device_result", null);
                                            }

                                            deviceImports.Add(deviceImport);
                                        }
                                    }
                                }
                            }
                        }

                    }
                }

                deviceImports = deviceImports.Distinct().ToList();

                //先刪除整份資料表
                var sql = @"IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[device_import_temp]') AND type in (N'U'))
                            BEGIN
                                DROP TABLE [dbo].[device_import_temp];
                            END
                            CREATE TABLE [dbo].[device_import_temp](
	                            [id] [int] IDENTITY(1,1) NOT NULL,
	                            [device_number] [nvarchar](255) NULL,
	                            [device_system_category_layer3] [varchar](50) NULL,
	                            [device_disaster] [varchar](50) NULL,
	                            [device_result] [nvarchar](255) NULL,
	                            [created_at] [datetime] NULL,
                             CONSTRAINT [PK_device_import_temp] PRIMARY KEY CLUSTERED 
                            (
	                            [id] ASC
                            ))
                            ALTER TABLE [dbo].[device_import_temp] ADD  CONSTRAINT [DF_device_import_temp_device_disaster]  DEFAULT ((0)) FOR [device_disaster]
                            ALTER TABLE [dbo].[device_import_temp] ADD  CONSTRAINT [DF_device_import_temp_created_at]  DEFAULT (getdate()) FOR [created_at]
                            ";
                await backendRepository.ExecuteSql(sql);

                //如有發現錯誤,直接insert 至 device_import_temp,不做後續處理
                await backendRepository.AddMutiByCustomTable(deviceImports, "device_import_temp");

                //var err = deviceImports.Where(x => x.ContainsKey("@device_result")).Select(x => x.Values).ToList();
                var err = deviceImports.SelectMany(x => x).Where(x => x.Key == "@device_result" && x.Value != null).ToList();
                if (err.Count > 0)
                {
                    apiResult.Code = "9997";
                    apiResult.Msg = "資料內容有誤,請重新匯入。";

                    return apiResult;
                }
                else
                {
                    //拆分每一份資料
                    List<Dictionary<string, object>> deviceImportChecks = new List<Dictionary<string, object>>(); //檢查OK的列表

                    
                    foreach (var deviceImport in deviceImports)
                    {

                        object device_number = null;
                        object device_system_category_layer3 = null;
                        object device_disaster = null;
                        deviceImport.TryGetValue("@device_number", out device_number);
                        deviceImport.TryGetValue("@device_system_category_layer3", out device_system_category_layer3);
                        deviceImport.TryGetValue("@device_disaster", out device_disaster);

                        var arr_device_number = device_number.ToString().Split('_');

                        //抓出是否為組數的設備
                        var arr_device_number_final_col = arr_device_number[arr_device_number.Length - 1].Contains('~') ? arr_device_number[arr_device_number.Length - 1].Split('~') : null;
                        if (arr_device_number_final_col != null && arr_device_number_final_col.Length > 0)
                        {
                            var start_num = Convert.ToInt32(arr_device_number_final_col[0].Trim());
                            var end_num = Convert.ToInt32(arr_device_number_final_col[1].Trim());
                            for (var i = start_num; i <= end_num; i++)
                            {
                                Dictionary<string, object> deviceImportCheck = new Dictionary<string, object>();
                                var pre_device_number = String.Join('_', arr_device_number, 0, 4);
                                deviceImportCheck.Add("@device_building_tag", arr_device_number[0]); //設備區域
                                deviceImportCheck.Add("@device_system_tag", arr_device_number[1]); //設備系統別
                                deviceImportCheck.Add("@device_floor_tag", arr_device_number[2]); //設備樓層
                                deviceImportCheck.Add("@device_name_tag", arr_device_number[3]); //設備名稱

                                var pad = string.Empty;
                                if(i < 10)
                                {
                                    pad = i.ToString().PadLeft(2, '0');
                                }
                                else
                                {
                                    pad = i.ToString();
                                }
                                deviceImportCheck.Add("@device_serial_tag", pad); //設備流水號

                                deviceImportCheck.Add("@device_number", pre_device_number + "_" + pad); //設備完整編號
                                deviceImportCheck.Add("@device_system_category_layer3", device_system_category_layer3.ToString()); //系統類別(第3層)
                                deviceImportCheck.Add("@device_disaster", device_disaster.ToString()); //緊急應變程序
                                deviceImportCheck.Add("@is_correct", 0); //驗證是否正確

                                deviceImportChecks.Add(deviceImportCheck);
                            }
                        }
                        else
                        {
                            Dictionary<string, object> deviceImportCheck = new Dictionary<string, object>();
                            var pre_device_number = String.Join('_', arr_device_number, 0, 3);
                            deviceImportCheck.Add("@device_building_tag", arr_device_number[0]); //設備區域
                            deviceImportCheck.Add("@device_system_tag", arr_device_number[1]); //設備系統別
                            deviceImportCheck.Add("@device_floor_tag", arr_device_number[2]); //設備樓層
                            deviceImportCheck.Add("@device_name_tag", arr_device_number[3]); //設備名稱
                            deviceImportCheck.Add("@device_serial_tag", arr_device_number[4]); //設備流水號
                            deviceImportCheck.Add("@device_number", device_number); //設備完整編號
                            deviceImportCheck.Add("@device_system_category_layer3", device_system_category_layer3.ToString()); //系統類別(第3層)
                            deviceImportCheck.Add("@device_disaster", device_disaster.ToString()); //緊急應變程序
                            deviceImportCheck.Add("@is_correct", 0); //驗證是否正確

                            deviceImportChecks.Add(deviceImportCheck);
                        }

                    }

                    //針對棟別刪除檢查OK的設備查詢表
                    var sDeleteWhere = $@"device_building_tag = '{temp_building}'";
                    await backendRepository.PurgeOneByGuidWithCustomDBNameAndTable("device_import_ckeck_temp", sDeleteWhere);

                    //var sql_check = @"IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[device_import_ckeck_temp]') AND type in (N'U'))
                    //                BEGIN
                    //                    DROP TABLE [dbo].[device_import_ckeck_temp]
                    //                END
                    //                CREATE TABLE [dbo].[device_import_ckeck_temp](
                    //                 [id] [int] IDENTITY(1,1) NOT NULL,
                    //                 [device_building_tag] [nvarchar](50) NULL,
                    //                 [device_system_tag] [nvarchar](50) NULL,
                    //                 [device_floor_tag] [nvarchar](50) NULL,
                    //                 [device_kind] [nvarchar](50) NULL,
                    //                 [device_name_tag] [nvarchar](50) NULL,
                    //                 [device_serial_tag] [nvarchar](50) NULL,
                    //                 [device_number] [nvarchar](255) NULL,
                    //                 [device_system_category_layer3] [varchar](50) NULL,
                    //                 [device_disaster] [varchar](50) NULL,
                    //                 [created_at] [datetime] NULL,
                    //                    CONSTRAINT [PK_device_import_ckeck_temp] PRIMARY KEY CLUSTERED
                    //                (
                    //                 [id] ASC
                    //                ))

                    //                ALTER TABLE [dbo].[device_import_ckeck_temp] ADD  CONSTRAINT [DF_device_import_ckeck_temp_device_disaster]  DEFAULT ((0)) FOR [device_disaster]
                    //                ALTER TABLE [dbo].[device_import_ckeck_temp] ADD  CONSTRAINT [DF_device_import_ckeck_temp_created_at]  DEFAULT (getdate()) FOR [created_at]
                    //                ";
                    //await backendRepository.ExecuteSql(sql_check);

                    //檢查正確才寫入至check_temp資料表
                    await backendRepository.AddMutiByCustomTable(deviceImportChecks, "device_import_ckeck_temp");
                }

                apiResult.Code = "0000";
                apiResult.Msg = "匯入成功";
                #endregion
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 取得設備檢核上方過濾選單
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<DeviceCheckFilter>>> GetRawDataCheckFilter()
        {
            ApiResult<List<DeviceCheckFilter>> apiResult = new ApiResult<List<DeviceCheckFilter>>();

            try
            {
                string sql = $@"
                                SELECT 
	                                ct.device_building_tag,
	                                ct.device_system_tag,
	                                ct.device_system_category_layer3
	                                FROM device_import_ckeck_temp ct
                                GROUP BY ct.device_building_tag, ct.device_system_tag, ct.device_system_category_layer3
                                ";

                var deviceCheckFilterRawDatas = await backendRepository.GetAllAsync<DeviceCheckFilterRawData>(sql);

                List<DeviceCheckFilter> deviceCheckFilters = new List<DeviceCheckFilter>();

                var deviceCheckFilterRawData_Group_Building_tag = deviceCheckFilterRawDatas.GroupBy(x => x.Device_building_tag).ToList();
                foreach (var deviceCheckFilterRawData_Building_tag in deviceCheckFilterRawData_Group_Building_tag)
                {
                    DeviceCheckFilter deviceCheckFilter = new DeviceCheckFilter();
                    deviceCheckFilter.Building_tag = deviceCheckFilterRawData_Building_tag.Key;

                    var sql_amount = @"SELECT COUNT(*) FROM device_import_ckeck_temp WHERE device_building_tag = @Device_building_tag";
                    deviceCheckFilter.Building_amount = await backendRepository.GetOneAsync<int>(sql_amount, new { Device_building_tag = deviceCheckFilterRawData_Building_tag.Key });

                    deviceCheckFilter.System_tags = new List<DeviceCheckSystemTag>();

                    var deviceCheckFilterRawData_Group_System_tag = deviceCheckFilterRawData_Building_tag.GroupBy(x => x.Device_system_tag).ToList();
                    foreach (var deviceCheckFilterRawData_System_tag in deviceCheckFilterRawData_Group_System_tag)
                    {
                        DeviceCheckSystemTag deviceCheckSystemTag = new DeviceCheckSystemTag();
                        deviceCheckSystemTag.System_tag = deviceCheckFilterRawData_System_tag.Key;
                        deviceCheckSystemTag.System_categories = new List<string>();

                        var deviceCheckFilterRawData_Group_System_category = deviceCheckFilterRawData_System_tag.GroupBy(x => x.Device_system_category_layer3).ToList();
                        foreach (var deviceCheckFilterRawData_System_category in deviceCheckFilterRawData_Group_System_category)
                        {
                            deviceCheckSystemTag.System_categories.Add(deviceCheckFilterRawData_System_category.Key);
                        }

                        deviceCheckFilter.System_tags.Add(deviceCheckSystemTag);
                    }

                    deviceCheckFilters.Add(deviceCheckFilter);
                }


                apiResult.Code = "0000";
                apiResult.Data = deviceCheckFilters;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 資料檢核表格
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<DeviceCheck>> DeviceCheckTableList(PostDeviceCheckFilter post)
        {
            ApiResult<DeviceCheck> apiResult = new ApiResult<DeviceCheck>();

            try
            {
                string sWhere = "";
                string sSubTableWhere = " WHERE {0}.device_building_tag = @Device_building_tag";
                if (post.Abnormal == "all")
                { //異常分類 為全選的時候,才可以指定選擇系統別、設備分類
                    if (post.System_tag != "all")
                    {
                        sSubTableWhere += " AND {0}.device_system_tag = @Device_system_tag";
                    }
                    if (post.System_category != "all")
                    {
                        sSubTableWhere += " AND {0}.device_system_category_layer3 = @Device_system_category_layer3";
                    }
                }
                else
                {
                    sWhere += @"WHERE ct.device_number IS NULL AND d.device_number IS NOT NULL
                                   -- OR ct.device_system_category_layer3 != d.device_system_category_layer3
                                   -- OR ct.disaster_system_value != d.device_disaster";
                }

                string sql_temp = $@"
                                SELECT 
	                                ct.device_number AS check_temp_device_number,
	                                ct.device_system_category_layer3 AS check_temp_device_system_category_layer3,
	                                ct.system_category_system_key AS check_temp_device_system_category_layer3_key,
	                                ct.disaster_system_value AS check_temp_disaster,
	                                ct.disaster_system_key AS check_temp_disaster_key,
	                                d.device_number,
	                                d.device_system_category_layer3 AS device_system_category_layer3,
	                                d.system_key AS device_system_category_layer3_key,
	                                d.device_disaster,
	                                d.device_disaster_type_text,
	                                d.device_coordinate,
                                    CASE 
		                                WHEN ct.device_number = d.device_number 
		                                THEN 0
		                                ELSE 1
	                                END AS compare_device_number,
	                                CASE 
		                                WHEN ct.device_system_category_layer3 = d.device_system_category_layer3 
		                                THEN 0
		                                ELSE 1
	                                END AS compare_system_category_layer3,
	                                CASE 
		                                WHEN ct.disaster_system_value = d.device_disaster 
		                                THEN 0
		                                ELSE 1
	                                END AS compare_device_disaster
	                            FROM (
	                                SELECT 
		                                ct.* ,
		                                v.system_type AS system_category_system_type,
		                                v.system_key AS system_category_system_key,
		                                v.system_value AS system_category_system_value,
		                                v2.system_type AS disaster_system_type,
		                                v2.system_key AS disaster_system_key,
		                                v2.system_value AS disaster_system_value
		                                FROM device_import_ckeck_temp ct
		                                LEFT JOIN variable v ON v.system_type = 'device_system_category_layer3' AND ct.device_system_category_layer3 = v.system_value
		                                LEFT JOIN variable v2 ON v2.system_type = 'disaster' AND v2.system_value = ct.device_disaster
		                                {{0}}
                                ) ct
                                FULL JOIN (
	                                SELECT 
		                                d.* ,
		                                v.system_type,
		                                v.system_key,
		                                v.system_value,
		                                (SELECT
                                            STRING_AGG( ISNULL(system_value, ' '), ',')
                                            FROM device_disaster dd 
                                            JOIN variable v ON v.deleted = 0 AND v.system_type = 'disaster' AND v.system_value = dd.device_system_value
                                            WHERE dd.device_guid = d.device_guid
                                        ) AS device_disaster,
		                                (SELECT
                                            STRING_AGG( ISNULL(system_key, ' '), ',')
                                            FROM device_disaster dd 
                                            JOIN variable v ON v.deleted = 0 AND v.system_type = 'disaster' AND v.system_value = dd.device_system_value
                                            WHERE dd.device_guid = d.device_guid
                                        ) AS device_disaster_type_text
	                                FROM device d 
	                                LEFT JOIN variable v ON v.system_type = 'device_system_category_layer3' AND d.device_system_category_layer3 = v.system_value
	                                {{1}}
                                    AND d.deleted = 0
	
                                )d ON ct.device_number = d.device_number
                                {{2}}
                                ORDER BY d.device_number DESC
                                ";

                var sql = string.Format(sql_temp, string.Format(sSubTableWhere, "ct"), string.Format(sSubTableWhere, "d"), sWhere);

                var param = new { Device_building_tag = post.Building_tag, Device_system_tag = post.System_tag, Device_system_category_layer3 = post.System_category };

                var deviceCheckTableList = await backendRepository.GetAllAsync<DeviceCheckTable>(sql, param);

                sSubTableWhere = " WHERE {0}.device_building_tag = @Device_building_tag";

                sWhere = @"WHERE  ct.device_number IS NULL AND d.device_number IS NOT NULL
                                   -- OR ct.device_system_category_layer3 != d.device_system_category_layer3
                                   -- OR ct.disaster_system_value != d.device_disaster";

                var sql_abnormal_amount = string.Format(sql_temp, string.Format(sSubTableWhere, "ct"), string.Format(sSubTableWhere, "d") + " AND d.deleted = 0", sWhere);

                var abnormal = await backendRepository.GetAllAsync<DeviceCheckTable>(sql_abnormal_amount, param);

                var abnormal_amount = abnormal.Count();

                DeviceCheck deviceCheck = new DeviceCheck();
                deviceCheck.DeviceCheckAmount = abnormal_amount;
                deviceCheck.DeviceCheckTableList = deviceCheckTableList;

                apiResult.Code = "0000";
                apiResult.Data = deviceCheck;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 資料檢核表格
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> DeviceCheckReplace(PostDeviceCheckFilter post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                //將該棟別的資料更換為正確
                string sql_update_correct = @"UPDATE device_import_ckeck_temp SET is_correct = 1 WHERE device_building_tag = @Device_building_tag";
                var param = new { Device_building_tag = post.Building_tag };
                await backendRepository.ExecuteSql(sql_update_correct, param);

                //找出當前在device裡面有的,以供後續取代用
                string sql = @"
                                SELECT
                                    ct.*,
                                    d.device_guid
                                FROM (
                                    SELECT 
                                        * 
                                    FROM device_import_ckeck_temp ct
                                    WHERE ct.device_number IN (
                                                SELECT d.device_number
                                                FROM device d
                                                WHERE d.deleted = 0
                                                AND d.device_building_tag = @Device_building_tag
                                    )
                                ) ct
                                LEFT JOIN device d ON d.deleted = 0 AND ct.device_number = d.device_number";

                var check_temp_replaces = await backendRepository.GetAllAsync<Device_import_ckeck_temp_replace>(sql, param);

                foreach (var check_temp_replace in check_temp_replaces)
                {
                    Dictionary<string, object> device_replace = new Dictionary<string, object>()
                    {
                        {"@device_system_category_layer3", check_temp_replace.Device_system_category_layer3},
                    };

                    List<Dictionary<string, object>> device_disaster_dicts = new List<Dictionary<string, object>>()
                    {
                        { new Dictionary<string, object>() { { "@device_guid", check_temp_replace.Device_guid }, { "@device_system_value", check_temp_replace.Device_disaster } } }
                    };

                    await deviceImportRepository.ReplaceOneDeviceInfo(check_temp_replace.Device_guid, device_replace, device_disaster_dicts);
                }

                apiResult.Code = "0000";
                apiResult.Msg = "取代成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

    }
}