using Backend.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
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 DeviceManageController : MybaseController<DeviceManageController>
    {
        private readonly IBackendRepository backendRepository;
        private readonly IDeviceManageRepository deviceManageRepository;
        private string deviceKindFileSaveAsPath = "";
        private string deviceKindFilePath = "upload/device_icon/";


        public DeviceManageController(IBackendRepository backendRepository, IDeviceManageRepository deviceManageRepository)
        {
            this.backendRepository = backendRepository;
            this.deviceManageRepository = deviceManageRepository;

            deviceKindFileSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "device_icon");
        }

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

        /// <summary>
        /// 取得設備管理左側選單
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<BuildingCollapse>>> GetBuildingMenuCollapse(string filter)
        {
            ApiResult<List<BuildingCollapse>> apiResult = new ApiResult<List<BuildingCollapse>>();
            try
            {

                //取得區域選單
                var sql = $@"SELECT 
	                            bm.*,
	                            b.full_name AS bFull_name,
	                            b.priority AS bPriority,
	                            mv.system_key AS mFull_name,
	                            mv.system_priority AS mPriority,
	                            sv.system_key AS sFull_name,
	                            sv.system_priority AS sPriority
                            FROM building_menu bm 
                            LEFT JOIN building b ON bm.building_tag = b.building_tag AND b.deleted = 0
                            LEFT JOIN variable mv ON bm.main_system_tag = mv.system_value AND mv.deleted = 0
                            LEFT JOIN variable sv ON bm.sub_system_tag = sv.system_value AND sv.deleted = 0";

                if (!string.IsNullOrEmpty(filter))
                {
                    sql += $@" WHERE (
                                        b.full_name LIKE CONCAT('%', @Filter, '%')
                                    OR  mv.system_key LIKE CONCAT('%', @Filter, '%')
                                    OR  sv.system_key LIKE CONCAT('%', @Filter, '%')
                                  )";
                }

                sql += $@" ORDER BY b.priority, mv.system_priority, sv.system_priority, sv.created_at DESC";

                var buildingMenuRawDatas = await backendRepository.GetAllAsync<BuildingMenuRawData>(sql, new { Filter = filter });

                //取得系統小類樓層
                var sub_sql = $@"SELECT 
	                                ssf.*,
	                                f.full_name AS fFull_name,
	                                f.InitMapName,
	                                f.floor_map_name,
	                                f.priority AS fPriority
                                FROM sub_system_floor ssf
                                LEFT JOIN floor f ON ssf.floor_tag = f.full_name AND ssf.building_tag = f.building_tag AND f.deleted = 0
                                WHERE ssf.deleted = 0
                                ORDER BY f.priority, f.created_at
";
                var subSystemFloorRawDatas = await backendRepository.GetAllAsync<SubSystemFloorRawData>(sub_sql);

                var buildingMenu_Group_Building_tag = buildingMenuRawDatas.GroupBy(x => x.building_tag).ToList();

                List<BuildingCollapse> buildingCollapses = new List<BuildingCollapse>();
                foreach (var buildingMenus_Building_tag in buildingMenu_Group_Building_tag)
                {
                    BuildingCollapse buildingCollapse = new BuildingCollapse();

                    buildingCollapse.Building_tag = buildingMenus_Building_tag.Key;
                    buildingCollapse.Full_name = buildingMenus_Building_tag.First().bFull_name;
                    buildingCollapse.Main_systems = new List<Main_system>();

                    var buildingMenus_Group_Main_system_tag = buildingMenus_Building_tag.GroupBy(x => x.main_system_tag).ToList();

                    foreach (var buildingMenus_Main_system_tag in buildingMenus_Group_Main_system_tag)
                    {
                        Main_system main_System = new Main_system();
                        main_System.Main_system_tag = buildingMenus_Main_system_tag.Key;
                        main_System.Full_name = buildingMenus_Main_system_tag.First().mFull_name;
                        main_System.Sub_systems = new List<Sub_system>();

                        var buildingMenus_Group_Sub_system_tag = buildingMenus_Main_system_tag.GroupBy(x => x.sub_system_tag).ToList();

                        foreach (var buildingMenus_Sub_system_tag in buildingMenus_Group_Sub_system_tag)
                        {
                            Sub_system sub_System = new Sub_system();
                            sub_System.Sub_system_tag = buildingMenus_Sub_system_tag.Key;
                            sub_System.Full_name = buildingMenus_Sub_system_tag.First().sFull_name;
                            sub_System.Floors = new List<Floor>();

                            var floorRawDatas = subSystemFloorRawDatas.Where(x => x.building_tag == buildingCollapse.Building_tag
                                                                        && x.main_system_tag == main_System.Main_system_tag
                                                                        && x.sub_system_tag == sub_System.Sub_system_tag).ToList();

                            foreach (var floorRawData in floorRawDatas)
                            {
                                Floor floor = new Floor();
                                floor.Floor_tag = floorRawData.Floor_tag;
                                floor.Full_name = floorRawData.fFull_name;
                                floor.InitMapName = floorRawData.InitMapName;
                                floor.Floor_map_name = floorRawData.Floor_map_name;

                                sub_System.Floors.Add(floor);
                            }

                            main_System.Sub_systems.Add(sub_System);
                        }

                        buildingCollapse.Main_systems.Add(main_System);
                    }

                    buildingCollapses.Add(buildingCollapse);
                }

                apiResult.Code = "0000";
                apiResult.Data = buildingCollapses;
            }
            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<Device>>> DeviceTableList(PostDeviceFilter post)
        {
            ApiResult<List<Device>> apiResult = new ApiResult<List<Device>>();

            try
            {

                var sql = $@"SELECT 
		                            d.*,
		                            d.full_name AS Device_full_name,
		                            b.full_name AS Building_full_name,
		                            mv.system_key AS Main_system_full_name,
		                            sv.system_key AS Sub_system_full_name,
		                            f.full_name AS Floor_full_name,
		                            dk.device_image,
		                            CONCAT('{baseURL}', '{deviceKindFilePath}', dk.device_image) AS device_image_url,
		                            dk.device_close_color,
		                            dk.device_normal_color,
		                            dk.device_error_color,
		                            dk.device_normal_flashing,
		                            dk.device_close_flashing,
		                            dk.device_error_flashing,
                            (SELECT
		                            GROUP_CONCAT( IFNULL(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 ( 
		                            SELECT * 
				                            FROM device d
				                            WHERE d.device_building_tag = @building_tag
						                            AND d.device_system_tag = @main_system_tag
						                            AND d.device_name_tag = @sub_system_tag
						                            AND d.device_floor_tag = @floor_tag
						                            AND d.deleted = 0
                            ) d
                            JOIN building b ON d.device_building_tag = b.building_tag
                            JOIN variable mv ON d.device_system_tag = mv.system_value AND mv.system_type = @main_system_type
                            JOIN variable sv ON d.device_name_tag = sv.system_value AND sv.system_type = @sub_system_type
                            JOIN floor f ON d.device_floor_tag = f.full_name  AND d.device_building_tag = f.building_tag
                            LEFT JOIN device_kind dk ON dk.device_building_tag = d.device_building_tag AND dk.device_system_tag = d.device_system_tag AND dk.device_name_tag = d.device_name_tag
                            ORDER BY d.priority ASC, d.device_number ASC";
              
                var devices = await backendRepository.GetAllAsync<Device>(sql, new { 
                    building_tag  = post.building_tag,
                    main_system_tag = post.device_system_tag,
                    sub_system_tag = post.device_name_tag,
                    floor_tag = post.device_floor_tag,
                    main_system_type = main_system_type,
                    sub_system_type = sub_system_type
                });

                var sql_node = $@"SELECT
                                    dn.device_node_guid,
                                    dn.device_guid,
                                    dn.full_name AS Device_node_full_name,
                                    dn.device_node_coordinate,
                                    dn.priority
                                FROM device_node dn 
                                WHERE dn.deleted = 0 AND dn.device_guid = @device_guid
                                ORDER BY dn.priority ASC";
                foreach (var device in devices)
                {
                    device.Device_nodes = await backendRepository.GetAllAsync<DeviceNode>(sql_node, new { device_guid = device.Device_guid });
                }

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

            return apiResult;
        }

        /// <summary>
        /// 取得單一設備基本資料
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<Device>> GetOneDevice(string guid)
        {
            ApiResult<Device> apiResult = new ApiResult<Device>();

            try
            {
                string sql = $@"SELECT 
                                        d.*,
                                        d.full_name AS Device_full_name,
                                        b.full_name AS Building_full_name,
                                        mv.system_key AS Main_system_full_name,
                                        sv.system_key AS Sub_system_full_name,
                                        f.full_name AS Floor_full_name
                                        FROM (
                                            SELECT *
                                            FROM device d
                                            WHERE 
                                                    d.device_guid = @Device_guid
                                                AND d.deleted = @Deleted
                                        ) d
                                        JOIN building b ON d.device_building_tag = b.building_tag
                                        JOIN variable mv ON d.device_system_tag = mv.system_value AND mv.system_type = @main_system_type
                                        JOIN variable sv ON d.device_name_tag = sv.system_value AND sv.system_type = @sub_system_type
                                        JOIN floor f ON d.device_floor_tag = f.full_name
                                        ";

                object param = new { Deleted = 0, Device_guid = guid ,main_system_type = main_system_type , sub_system_type = sub_system_type };

                var device = await backendRepository.GetOneAsync<Device>(sql, param);

                string sWhere = "Device_guid = @Device_guid";
                device.Device_disasters = await backendRepository.GetAllAsync<DeviceDisaster>("device_disaster", sWhere, new { Device_guid = device.Device_guid });

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

            return apiResult;
        }

        /// <summary>
        /// 取得災害類型
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<Variable>>> GetDisasterList()
        {
            ApiResult<List<Variable>> apiResult = new ApiResult<List<Variable>>();

            try
            {
                var sWhere = "system_type = @System_type";

                object param = new { System_type = "disaster" };

                var variables = await backendRepository.GetAllAsync<Variable>("variable", sWhere, param);

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

            return apiResult;
        }

        /// <summary>
        /// 新增 設備基本資料
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> SaveDeviceInfoAdd(PostDeviceInfoAdd post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                List<Dictionary<string, object>> deviceDics = new List<Dictionary<string, object>>();
                List<Dictionary<string, object>> device_disaster_dicts = new List<Dictionary<string, object>>();

                using (var reader = new StreamReader(post.SelectedDevicesFile.OpenReadStream()))
                {
                    string content = reader.ReadToEnd();
                    post.SelectedDevices = JsonSerializer.Deserialize<List<SelcectedDeviceAdd>>(content);
                }

                foreach (var device in post.SelectedDevices)
                {
                    var guid = Guid.NewGuid();
                    var split = device.Device_number.Split('_');

                    var device_building_tag = !string.IsNullOrEmpty(split[0]) ? split[0] : "";
                    var device_system_tag = !string.IsNullOrEmpty(split[1]) ? split[1] : "";
                    var device_floor_tag = !string.IsNullOrEmpty(split[2]) ? split[2] : "";
                    var device_name_tag = !string.IsNullOrEmpty(split[3]) ? split[3] : "";
                    var device_serial_tag = !string.IsNullOrEmpty(split[4]) ? split[4] : "";
                    string device_master = null;

                    //針對燈具加入master
                    if (device.Device_system_category_layer3 == "L1" || device.Device_system_category_layer3 == "L2")
                    {
                        device_master = device_building_tag + device_name_tag;
                    }

                    Dictionary<string, object> deviceDic = new Dictionary<string, object>()
                    {
                        { "@device_guid", guid},
                        { "@full_name", device_name_tag + device_serial_tag},
                        { "@device_building_tag", device_building_tag},
                        { "@device_system_tag", device_system_tag},
                        { "@device_floor_tag", device_floor_tag},
                        { "@device_name_tag", device_name_tag},
                        { "@device_serial_tag", device_serial_tag},
                        { "@device_master", device_master},
                        { "@device_number", device.Device_number},
                        { "@device_system_category_layer3", device.Device_system_category_layer3},
                        { "@created_by", myUserInfo.Userinfo_guid},
                    };

                    deviceDics.Add(deviceDic);

                    if (device.Device_disasters != null)
                    {
                        foreach (var device_disasters_str in device.Device_disasters)
                        {
                            var device_disasters = device_disasters_str.ToString().Trim().Split(',');
                            foreach (var dd in device_disasters)
                            {
                                Dictionary<string, object> device_disaster_dict = new Dictionary<string, object>()
                                {
                                    { "@device_guid", guid },
                                    { "@device_system_value", dd }
                                };
                                device_disaster_dicts.Add(device_disaster_dict);
                            }
                        }
                    }
                }

                await deviceManageRepository.AddMutiByCustomTable(deviceDics, "device");

                if (device_disaster_dicts.Count() > 0)
                {
                    await deviceManageRepository.AddMutiByCustomTable(device_disaster_dicts, "device_disaster");
                }

                await ResetDeviceGroup(); //重新寫入設備群組

                apiResult.Code = "0000";
                apiResult.Msg = "修改成功";

            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 修改 設備基本資料
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> SaveDeviceInfoEdit(PostDeviceInfoEdit post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                string sWhere = @$"deleted = @Deleted AND device_guid = @Guid";

                object param = new { Deleted = 0, Guid = post.Device_guid };

                var device = await backendRepository.GetOneAsync<Device>("device", sWhere, param);

                if (device == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = "查無該設備";
                }
                else
                {
                    string coordinate = null;
                    if (post.Device_coordinate_x != null && post.Device_coordinate_y != null)
                    {
                        coordinate = Math.Round(Convert.ToDouble(post.Device_coordinate_x), 3).ToString() + "," + Math.Round(Convert.ToDouble(post.Device_coordinate_y), 3).ToString();
                    }

                    Dictionary<string, object> deviceDic = new Dictionary<string, object>()
                    {
                        { "@full_name", post.Full_name},
                        { "@device_coordinate", coordinate},
                        { "@device_ip", post.Device_ip},
                        { "@device_port", post.Device_port},
                        { "@updated_by", myUserInfo.Userinfo_guid},
                        { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
                    };

                    List<Dictionary<string, object>> device_disaster_dicts = new List<Dictionary<string, object>>();
                    if (post.Device_disasters != null)
                    {
                        foreach (var disaster in post.Device_disasters)
                        {
                            Dictionary<string, object> device_disaster_dict = new Dictionary<string, object>()
                            {
                                { "device_guid", device.Device_guid},
                                { "@device_system_value", disaster},
                            };

                            device_disaster_dicts.Add(device_disaster_dict);
                        }
                    }

                    await deviceManageRepository.UpdateOneDeviceInfo(device.Device_guid, deviceDic, device_disaster_dicts);

                    apiResult.Code = "0000";
                    apiResult.Msg = "修改成功";
                }
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 軟刪除單一設備
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> DeleteOneDevice(string guid)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                string sWhere = @$"deleted = @Deleted AND device_guid = @Guid";

                object param = new { Deleted = 0, Guid = guid };

                var device = await backendRepository.GetOneAsync<Device>("device", sWhere, param);

                if (device == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = "查無該設備";
                }
                else
                {

                    Dictionary<string, object> deviceDic = new Dictionary<string, object>()
                    {
                        { "@deleted", 1},
                        { "@updated_by", myUserInfo.Userinfo_guid},
                        { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
                    };

                    await backendRepository.UpdateOneByCustomTable(deviceDic, "device", "device_guid='" + guid + "'");

                    await ResetDeviceGroup(); //重新寫入設備群組

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

            return apiResult;
        }

        /// <summary>
        /// 修改 設備座標
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> SaveDeviceCoordinate(PostDeviceCoordinate post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {

                if (string.IsNullOrEmpty(post.Device_node_guid))
                {
                    //修改設備本身
                    string sWhere = @$"deleted = @Deleted AND device_guid = @Guid";

                    object param = new { Deleted = 0, Guid = post.Device_guid };

                    var device = await backendRepository.GetOneAsync<Device>("device", sWhere, param);

                    if (device == null)
                    {
                        apiResult.Code = "9998";
                        apiResult.Msg = "查無該設備";
                    }
                    else
                    {

                        Dictionary<string, object> deviceDic = new Dictionary<string, object>()
                    {
                        { "@device_coordinate", post.Coordinate},
                        { "@updated_by", myUserInfo.Userinfo_guid},
                        { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
                    };

                        await backendRepository.UpdateOneByCustomTable(deviceDic, "device", "device_guid='" + post.Device_guid + "'");

                        apiResult.Code = "0000";
                        apiResult.Msg = "修改成功";
                    }
                }
                else
                {
                    //修改設備子節點本身
                    string sWhere = @$"deleted = @Deleted AND device_node_guid = @Guid";

                    object param = new { Deleted = 0, Guid = post.Device_node_guid };

                    var deviceNode = await backendRepository.GetOneAsync<DeviceNode>("device_node", sWhere, param);

                    if (deviceNode == null)
                    {
                        apiResult.Code = "9998";
                        apiResult.Msg = "查無該設備子節點";
                    }
                    else
                    {
                        Dictionary<string, object> deviceNodeDic = new Dictionary<string, object>()
                        {
                            { "@device_node_coordinate", post.Coordinate},
                            { "@updated_by", myUserInfo.Userinfo_guid},
                            { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
                        };

                        await backendRepository.UpdateOneByCustomTable(deviceNodeDic, "device_node", "device_node_guid='" + post.Device_node_guid + "'");

                        apiResult.Code = "0000";
                        apiResult.Msg = "修改成功";
                    }
                }

            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 取得單一設備子節點資料
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<DeviceNode>> GetOneDeviceNode(string guid)
        {
            ApiResult<DeviceNode> apiResult = new ApiResult<DeviceNode>();

            try
            {
                string sql = $@"SELECT 
                                    dn.*,
                                    dn.full_name AS Device_node_full_name
                                FROM device_node dn
                                WHERE dn.deleted = @Deleted
                                    AND dn.device_node_guid = @Device_node_guid
                                        ";

                object param = new { Deleted = 0, Device_node_guid = guid };

                var deviceNode = await backendRepository.GetOneAsync<DeviceNode>(sql, param);

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

            return apiResult;
        }

        /// <summary>
        /// 新增/儲存 設備子節點資料
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> SaveDeviceNode(PostDeviceNode post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                string sWhere = @$"deleted = @Deleted AND device_node_guid = @Guid";

                object param = new { Deleted = 0, Guid = post.Device_node_guid };

                var deviceNode = await backendRepository.GetOneAsync<DeviceNode>("device_node", sWhere, param);
                string coordinate = null;
                if (post.Device_node_coordinate_x != null && post.Device_node_coordinate_y != null)
                {
                    coordinate = Math.Round(Convert.ToDouble(post.Device_node_coordinate_x), 3).ToString() + "," + Math.Round(Convert.ToDouble(post.Device_node_coordinate_y), 3).ToString();
                }


                if (deviceNode == null)
                {
                    //產生一組GUID
                    var guid = Guid.NewGuid();  //大樓GUID

                    //抓取當前的Priority
                    var current_priority = await backendRepository.GetCurrentPriority("device_node");

                    Dictionary<string, object> device_node_dic = new Dictionary<string, object>();
                    device_node_dic = new Dictionary<string, object>()
                        {
                            { "@device_node_guid", guid},
                            { "@device_guid", post.Device_guid},
                            { "@full_name", post.Full_name},
                            { "@device_node_coordinate", coordinate},
                            { "@priority", current_priority + 1},
                            { "@created_by", myUserInfo.Userinfo_guid}
                        };
                    await backendRepository.AddOneByCustomTable(device_node_dic, "device_node");

                    apiResult.Code = "0000";
                    apiResult.Msg = "新增成功";
                }
                else
                {
                    Dictionary<string, object> deviceNodeDic = new Dictionary<string, object>()
                    {
                        { "@full_name", post.Full_name},
                        { "@device_node_coordinate", coordinate},
                        { "@updated_by", myUserInfo.Userinfo_guid},
                        { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
                    };

                    await backendRepository.UpdateOneByCustomTable(deviceNodeDic, "device_node", "device_node_guid='" + post.Device_node_guid + "'");

                    apiResult.Code = "0000";
                    apiResult.Msg = "修改成功";
                }
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 軟刪除單一設備子節點
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> DeleteOneDeviceNode(string guid)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                string sWhere = @$"deleted = @Deleted AND device_node_guid = @Guid";

                object param = new { Deleted = 0, Guid = guid };

                var deviceNode = await backendRepository.GetOneAsync<DeviceNode>("device_node", sWhere, param);

                if (deviceNode == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = "查無該設備子節點";
                }
                else
                {

                    Dictionary<string, object> deviceNodeDic = new Dictionary<string, object>()
                    {
                        { "@deleted", 1},
                        { "@updated_by", myUserInfo.Userinfo_guid},
                        { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},
                    };

                    await backendRepository.UpdateOneByCustomTable(deviceNodeDic, "device_node", "device_node_guid='" + guid + "'");

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

            return apiResult;
        }


        /// <summary>
        /// 取得設備基本資料清單
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<DeviceImportCheckTempFilter>>> GetDeviceImportCheckTempFilter()
        {
            ApiResult<List<DeviceImportCheckTempFilter>> apiResult = new ApiResult<List<DeviceImportCheckTempFilter>>();

            try
            {
                var rawDatas = await backendRepository.GetAllAsync<DeviceImportCheckTempRawData>("import_niagara_tag", null,null,"device_building_tag, device_system_tag, device_floor_tag, device_name_tag");

                var rawDatas_Group_Building_tag = rawDatas.GroupBy(x => x.Device_building_tag).ToList();
                List<DeviceImportCheckTempFilter> tempFilters = new List<DeviceImportCheckTempFilter>();
                foreach (var rawData_Building_tag in rawDatas_Group_Building_tag)
                {
                    DeviceImportCheckTempFilter tempFilter = new DeviceImportCheckTempFilter();
                    tempFilter.Device_building_tag = rawData_Building_tag.Key;
                    tempFilter.Device_system_tags = new List<ImportTempDeviceSystemTag>();

                    var rawDatas_Group_System_tag = rawData_Building_tag.GroupBy(x => x.Device_system_tag).ToList();

                    foreach (var rawData_System_tag in rawDatas_Group_System_tag)
                    {
                        ImportTempDeviceSystemTag systemTag = new ImportTempDeviceSystemTag();
                        systemTag.Device_system_tag = rawData_System_tag.Key;
                        systemTag.Device_floor_tags = new List<ImportTempDeviceFloorTag>();

                        var rawDatas_Group_Floor_tag = rawData_System_tag.GroupBy(x => x.Device_floor_tag).ToList();

                        foreach (var rawData_Floor_tag in rawDatas_Group_Floor_tag)
                        {
                            ImportTempDeviceFloorTag floorTag = new ImportTempDeviceFloorTag();
                            floorTag.Device_floor_tag = rawData_Floor_tag.Key;
                            floorTag.Device_name_tags = new List<string>();

                            var rawDatas_Group_Name_tag = rawData_Floor_tag.GroupBy(x => x.Device_name_tag).ToList();
                            foreach (var rawData_Name_tag in rawDatas_Group_Name_tag)
                            {
                                floorTag.Device_name_tags.Add(rawData_Name_tag.Key);
                            }

                            systemTag.Device_floor_tags.Add(floorTag);
                        }

                        tempFilter.Device_system_tags.Add(systemTag);
                    }

                    tempFilters.Add(tempFilter);
                }


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

            return apiResult;
        }

        /// <summary>
        /// 取得新增設備基本資料modal的設備清單
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<DeviceImportCheckTemp>>> DeviceImportCheckTempTableList(DeviceImportCheckTemp post)
        {
            ApiResult<List<DeviceImportCheckTemp>> apiResult = new ApiResult<List<DeviceImportCheckTemp>>();

            try
            {
                string sql = @"SELECT
	                            di.device_building_tag,
	                            di.device_system_tag,
	                            di.device_floor_tag,
	                            di.device_last_name_tag as device_name_tag,
	                            di.device_serial_tag,
                                0 as Device_disasters,
                                0 as Device_disaster_type_text,
	                            di.niagara_tags as device_number
                            FROM
	                            (
	                            SELECT
		                            * 
	                            FROM
		                            import_niagara_tag intag 
	                            WHERE
		                            device_building_tag = @Device_building_tag 
		                            AND device_system_tag = @Device_system_tag
		                            AND device_floor_tag = @Device_floor_tag
		                            AND device_name_tag = @Device_name_tag
		                            AND convert(intag.niagara_tags, nchar) NOT IN ( SELECT convert(d.device_number, nchar) FROM device d WHERE d.deleted = 0 ) 
	                            ) di 
                            GROUP BY
	                            di.device_building_tag,
	                            di.device_system_tag,
	                            di.device_floor_tag,
                                di.device_last_name_tag,
	                            di.device_serial_tag,
	                            di.niagara_tags";

                var deviceImports = await backendRepository.GetAllAsync<DeviceImportCheckTemp>(sql, post);

                apiResult.Code = "0000";
                apiResult.Data = deviceImports;
            }
            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<DeviceKind>>> DeviceKindTableList(PostDeviceFilter post)
        {
            ApiResult<List<DeviceKind>> apiResult = new ApiResult<List<DeviceKind>>();

            try
            {

                var sql = $@"SELECT 
			                    dk.device_kind_guid,
			                    dd.device_building_tag,
			                    dd.device_system_tag,
			                    -- dd.device_floor_tag,
			                    dd.device_name_tag,
			                    dk.device_image,
			                    dk.device_normal_text,
			                    dk.device_normal_point_name,
			                    dk.device_normal_point_col,
			                    dk.device_normal_point_value,
			                    dk.device_normal_color,
			                    dk.device_normal_flashing,
			                    dk.device_close_text,
			                    dk.device_close_point_name,
			                    dk.device_close_point_col,
			                    dk.device_close_point_value,
			                    dk.device_close_color,
			                    dk.device_close_flashing,
			                    dk.device_error_text,
			                    dk.device_error_point_name,
			                    dk.device_error_point_col,
			                    dk.device_error_point_value,
			                    dk.device_error_color,
			                    dk.device_error_flashing,
			                    dk.device_error_independent
                            FROM ( SELECT
		                            d.device_building_tag,
		                            d.device_system_tag,
		                            -- d.device_floor_tag,
		                            d.device_name_tag
			                            FROM ( 
				                            SELECT * 
					                            FROM device d
					                            WHERE 
							                            d.device_building_tag = @building_tag
							                            AND d.device_system_tag = @main_system_tag
							                            AND d.device_name_tag = @sub_system_tag
							                            -- AND d.floor_guid = @Floor_tag
							                            AND d.deleted = 0
			                            ) d
		                            GROUP BY d.device_building_tag,
				                             d.device_system_tag,
				                             -- d.device_floor_tag,
				                             d.device_name_tag) dd
                            LEFT JOIN device_kind dk ON dd.device_building_tag = dk.device_building_tag
				                            AND dd.device_system_tag = dk.device_system_tag
				                            -- AND dd.device_floor_tag = dk.device_floor_tag
				                            AND dd.device_name_tag = dk.device_name_tag";

                var deviceKinds = await backendRepository.GetAllAsync<DeviceKind>(sql, post);


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

            return apiResult;
        }


        /// <summary>
        /// 取得單一設備種類
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<DeviceKind>> GetOneDevicekind(string guid)
        {
            ApiResult<DeviceKind> apiResult = new ApiResult<DeviceKind>();

            try
            {
                string sWhere = "device_kind_guid = @Device_kind_guid";

                object param = new { Deleted = 0, Device_kind_guid = guid };

                var deviceKind = await backendRepository.GetOneAsync<DeviceKind>("device_kind", sWhere, param);

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

            return apiResult;
        }

        /// <summary>
        /// 修改 設備基本資料
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> SaveDeviceKind(PostDeviceKind post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                string sWhere = @$"device_kind_guid = @Guid";

                object param = new { Guid = post.Device_kind_guid };

                var deviceKind = await backendRepository.GetOneAsync<DeviceKind>("device_kind", sWhere, param);

                if (deviceKind == null)
                {
                    //新增
                    //產生一組GUID
                    var guid = Guid.NewGuid();

                    var image_name = string.Empty;

                    var split_image = new string[0];
                    if (post.Device_image_file != null)
                    {
                        split_image = post.Device_image_file.FileName.Split(".");

                        image_name = guid + "." + split_image[split_image.Length - 1];
                    }

                    //抓出點位名稱
                    var point_name = new PointName();

                    var sql_device_normal_point = @"SELECT n.points AS device_normal_point_name FROM (SELECT * FROM device_item di WHERE di.device_item_guid = @device_normal_point_guid) n";
                    point_name.Device_normal_point_name = await backendRepository.GetOneAsync<string>(sql_device_normal_point, new { device_normal_point_guid = post.Device_normal_point_guid });

                    var sql_device_close_point = @"SELECT c.points AS device_close_point_name FROM (SELECT * FROM device_item di WHERE di.device_item_guid = @device_close_point_guid) c";
                    point_name.Device_close_point_name = await backendRepository.GetOneAsync<string>(sql_device_close_point, new { device_close_point_guid = post.Device_close_point_guid });

                    var sql_device_error_point = @"SELECT e.points AS device_error_point_name FROM (SELECT * FROM device_item di WHERE di.device_item_guid = @device_error_point_guid) e";
                    point_name.Device_error_point_name = await backendRepository.GetOneAsync<string>(sql_device_error_point, new { device_error_point_guid = post.Device_error_point_guid });

                    Dictionary<string, object> deviceKindDic = new Dictionary<string, object>()
                    {
                        { "@device_kind_guid", guid},
                        { "@device_building_tag", post.Device_building_tag},
                        { "@device_system_tag", post.Device_system_tag},
                        //{ "@device_floor_tag", post.Device_floor_tag},
                        { "@device_name_tag", post.Device_name_tag},
                        { "@device_image", image_name },
                        { "@device_normal_text", post.Device_normal_text},
                        { "@device_normal_point_guid", post.Device_normal_point_guid},
                        { "@device_normal_point_name", point_name.Device_normal_point_name},
                        { "@device_normal_point_col", post.Device_normal_point_col},
                        { "@device_normal_point_value", post.Device_normal_point_value},
                        { "@device_normal_color", post.Device_normal_color},
                        { "@device_normal_flashing", post.Device_normal_flashing},
                        { "@device_close_text", post.Device_close_text},
                        { "@device_close_point_guid", post.Device_close_point_guid},
                        { "@device_close_point_name", point_name.Device_close_point_name},
                        { "@device_close_point_col", post.Device_close_point_col},
                        { "@device_close_point_value", post.Device_close_point_value},
                        { "@device_close_color", post.Device_close_color},
                        { "@device_close_flashing", post.Device_close_flashing},
                        { "@device_error_text", post.Device_error_text},
                        { "@device_error_point_guid", post.Device_error_point_guid},
                        { "@device_error_point_name", point_name.Device_error_point_name},
                        { "@device_error_point_col", post.Device_error_point_col},
                        { "@device_error_point_value", post.Device_error_point_value},
                        { "@device_error_color", post.Device_error_color},
                        { "@device_error_flashing", post.Device_error_flashing},
                        { "@device_error_independent", post.Device_error_independent},
                        { "@created_by", myUserInfo.Userinfo_guid}
                    };
                    await backendRepository.AddOneByCustomTable(deviceKindDic, "device_kind");

                    if (post.Device_image_file != null)
                    {
                        var split = post.Device_image_file.FileName.Split(".");
                        var fileName = guid + "." + split[split.Length - 1];

                        var fullPath = Path.Combine(deviceKindFileSaveAsPath, fileName);

                        using (var stream = new FileStream(fullPath, FileMode.Create))
                        {
                            post.Device_image_file.CopyTo(stream);
                        }
                    }

                    #region 新增至派送資料表
                    List<Repository.Models.FileInfo> fileInfos = new List<Repository.Models.FileInfo>();
                    if (post.Device_image_file != null)
                    {
                        var split = post.Device_image_file.FileName.Split(".");
                        var fileName = guid + "." + split[split.Length - 1];

                        var fullPath = Path.Combine(deviceKindFileSaveAsPath, fileName);

                        Repository.Models.FileInfo fileInfo = new Repository.Models.FileInfo();
                        fileInfo.Folder = "device_icon";
                        fileInfo.OriginalFileName = null;
                        fileInfo.FileName = fileName;
                        fileInfo.File = fullPath;

                        fileInfos.Add(fileInfo);
                        await backendRepository.ManualInsertFileBackgroundServiceTask("", "", "device_kind", fileInfos);
                    }
                    #endregion

                    apiResult.Code = "0000";
                    apiResult.Msg = "新增成功";
                }
                else
                {
                    var image_name = string.Empty;
                    var image_guid = Guid.NewGuid();
                    var split_image = new string[0];
                    if (post.Device_image_file != null)
                    {
                        split_image = post.Device_image_file.FileName.Split(".");

                        image_name = image_guid + "." + split_image[split_image.Length - 1];
                    }
                    else
                    {
                        image_name = deviceKind.Device_image;
                    }

                    //抓出點位名稱
                    var point_name = new PointName();

                    var sql_device_normal_point = @"SELECT n.points AS device_normal_point_name FROM (SELECT * FROM device_item di WHERE di.device_item_guid = @device_normal_point_guid) n";
                    point_name.Device_normal_point_name = await backendRepository.GetOneAsync<string>(sql_device_normal_point, new { device_normal_point_guid = post.Device_normal_point_guid });

                    var sql_device_close_point = @"SELECT c.points AS device_close_point_name FROM (SELECT * FROM device_item di WHERE di.device_item_guid = @device_close_point_guid) c";
                    point_name.Device_close_point_name = await backendRepository.GetOneAsync<string>(sql_device_close_point, new { device_close_point_guid = post.Device_close_point_guid });

                    var sql_device_error_point = @"SELECT e.points AS device_error_point_name FROM (SELECT * FROM device_item di WHERE di.device_item_guid = @device_error_point_guid) e";
                    point_name.Device_error_point_name = await backendRepository.GetOneAsync<string>(sql_device_error_point, new { device_error_point_guid = post.Device_error_point_guid });

                    Dictionary<string, object> deviceKindDic = new Dictionary<string, object>()
                    {
                        { "@device_image", image_name},
                        { "@device_normal_text", post.Device_normal_text},
                        { "@device_normal_point_guid", post.Device_normal_point_guid},
                        { "@device_normal_point_name", point_name != null? point_name.Device_normal_point_name : null},
                        { "@device_normal_point_col", post.Device_normal_point_col},
                        { "@device_normal_point_value", post.Device_normal_point_value},
                        { "@device_normal_color", post.Device_normal_color},
                        { "@device_normal_flashing", post.Device_normal_flashing},
                        { "@device_close_text", post.Device_close_text},
                        { "@device_close_point_guid", post.Device_close_point_guid},
                        { "@device_close_point_name", point_name != null? point_name.Device_close_point_name : null},
                        { "@device_close_point_col", post.Device_close_point_col},
                        { "@device_close_point_value", post.Device_close_point_value},
                        { "@device_close_color", post.Device_close_color},
                        { "@device_close_flashing", post.Device_close_flashing},
                        { "@device_error_text", post.Device_error_text},
                        { "@device_error_point_guid", post.Device_error_point_guid},
                        { "@device_error_point_name", point_name != null? point_name.Device_error_point_name : null},
                        { "@device_error_point_col", post.Device_error_point_col},
                        { "@device_error_point_value", post.Device_error_point_value},
                        { "@device_error_color", post.Device_error_color},
                        { "@device_error_flashing", post.Device_error_flashing},
                        { "@device_error_independent", post.Device_error_independent},
                        { "@updated_by", myUserInfo.Userinfo_guid},
                        { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
                    };
                    await backendRepository.UpdateOneByCustomTable(deviceKindDic, "device_kind", "device_kind_guid='" + deviceKind.Device_kind_guid + "'");

                    if (post.Device_image_file != null)
                    {
                        //刪除原本的檔案
                        FolderFunction folderFunction = new FolderFunction();
                        folderFunction.DeleteFile(Path.Combine(deviceKindFileSaveAsPath, deviceKind.Device_image));

                        var split = post.Device_image_file.FileName.Split(".");
                        var fileName = image_guid + "." + split[split.Length - 1];

                        var fullPath = Path.Combine(deviceKindFileSaveAsPath, fileName);

                        using (var stream = new FileStream(fullPath, FileMode.Create))
                        {
                            post.Device_image_file.CopyTo(stream);
                        }
                    }

                    #region 新增至派送資料表
                    List<Repository.Models.FileInfo> fileInfos = new List<Repository.Models.FileInfo>();
                    if (post.Device_image_file != null)
                    {
                        var split = post.Device_image_file.FileName.Split(".");
                        var fileName = image_guid + "." + split[split.Length - 1];

                        var fullPath = Path.Combine(deviceKindFileSaveAsPath, fileName);

                        Repository.Models.FileInfo fileInfo = new Repository.Models.FileInfo();
                        fileInfo.Folder = "device_icon";
                        fileInfo.OriginalFileName = deviceKind.Device_image;
                        fileInfo.FileName = fileName;
                        fileInfo.File = fullPath;

                        fileInfos.Add(fileInfo);
                        await backendRepository.ManualInsertFileBackgroundServiceTask("", "", "device_kind", fileInfos);
                    }
                    #endregion

                    apiResult.Code = "0000";
                    apiResult.Msg = "修改成功";
                }
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        private async Task ResetDeviceGroup()
        {
            //先刪除整個device_group
            var delete_group_sql = @"DROP  TABLE IF EXISTS `device_group` ;
                                    CREATE TABLE `device_group` (
                                      `id` int(11) NOT NULL,
                                      `device_disaster` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '災類',
                                      `device_building_tag` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '設備東別guid',
                                      `device_floor_guid` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '設備樓層guid',
                                      `device_area_tag` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '設備區域',
                                      `device_system_category_layer2` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '系統大類device_system_tag',
                                      `device_system_category_layer3` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '系統小類device_name_tag',
                                      `device_amount` int(11) NOT NULL DEFAULT '0' COMMENT '設備總計',
                                      PRIMARY KEY (`id`)
                                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='設備類別 - UI 過濾用';";

            await backendRepository.ExecuteSql(delete_group_sql);
            //更新整個device_group
            var insert_group_sql = @"
                            INSERT INTO device_group (device_disaster, device_building_tag, device_floor_guid, device_system_category_layer2, device_system_category_layer3, device_amount)
                            SELECT 
	                            dd.device_system_value AS device_disaster,
	                            d.building_tag AS device_building_tag,
	                            d.floor_guid AS device_floor_guid,
	                            vv.device_system_category_layer2 AS device_system_category_layer2,
	                            d.device_system_category_layer3 AS device_system_category_layer3,
	                            count(*) AS device_amount
	                            FROM device d
	                            JOIN device_disaster dd ON d.device_guid = dd.device_guid
	                            JOIN (SELECT 
				                            v.system_value AS device_system_category_layer3,
				                            v2.system_value AS device_system_category_layer2
				                            FROM variable v 
				                            LEFT JOIN variable v2 ON v.system_parent_id = v2.id
				                            WHERE v.system_type = 'device_system_category_layer3'
				                            ) vv ON d.device_system_category_layer3 = vv.device_system_category_layer3
	                            WHERE d.deleted = 0
	                            GROUP BY dd.device_system_value,
			                                d.building_tag, 
			                                d.floor_guid,
			                                vv.device_system_category_layer2,
			                                d.device_system_category_layer3";


            await backendRepository.ExecuteSql(insert_group_sql);


            #region 新增至派送資料表
            var deviceGroups = await backendRepository.GetAllAsync<DeviceGroup>("device_group", "");
            List<Dictionary<string, object>> deviceGroupsDics = new List<Dictionary<string, object>>();
            foreach (var deviceGroup in deviceGroups)
            {
                Dictionary<string, object> deviceGroupDic = new Dictionary<string, object>()
                {
                    { "@id", deviceGroup.id},
                    { "@device_disaster", deviceGroup.device_disaster},
                    { "@device_building_tag", deviceGroup.device_building_tag},
                    { "@device_floor_guid", deviceGroup.device_floor_tag},
                    { "@device_system_category_layer2", deviceGroup.device_system_category_layer2},
                    { "@device_system_category_layer3", deviceGroup.device_system_category_layer3},
                    { "@device_amount", deviceGroup.device_amount},
                };

                deviceGroupsDics.Add(deviceGroupDic);
            }
            await backendRepository.ManualInsertBackgroundServiceTask("", "", "device_group", "purge_all_insert", deviceGroupsDics);
            #endregion
        }

        /// <summary>
        /// 取得設備Master清單
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<DeviceMaster>>> GetDeviceMasterTableList(PostDeviceFilter post)
        {
            ApiResult<List<DeviceMaster>> apiResult = new ApiResult<List<DeviceMaster>>();

            try
            {
                var sql = $@"SELECT 
		                            dm.device_master_guid,
		                            dd.device_building_tag,
		                            dd.device_name_tag,
		                            dm.device_master_number,
		                            dm.device_master_full_name,
		                            dm.device_master_icon
                            FROM ( SELECT
		                            d.device_building_tag,
		                            d.device_name_tag
			                            FROM ( 
				                            SELECT * 
					                            FROM device d
					                            WHERE 
							                            d.device_building_tag = @building_tag
							                            AND d.device_system_tag = @main_system_tag
							                            AND d.device_name_tag = @sub_system_tag
							                            AND d.device_floor_tag = @floor_tag
							                            AND d.deleted = 0
			                            ) d
                            GROUP BY d.device_building_tag, d.device_name_tag) dd
                            LEFT JOIN device_master dm ON dd.device_building_tag = dm.device_building_tag
		                            AND dd.device_name_tag = dm.device_name_tag";

                var deviceMasters = await backendRepository.GetAllAsync<DeviceMaster>(sql, post);


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

            return apiResult;
        }

        /// <summary>
        /// 取得單一設備master
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<DeviceMaster>> GetOneDeviceMaster(string guid)
        {
            ApiResult<DeviceMaster> apiResult = new ApiResult<DeviceMaster>();

            try
            {
                string sWhere = "device_master_guid = @Device_master_guid";

                object param = new {Device_master_guid = guid };

                var deviceMaster = await backendRepository.GetOneAsync<DeviceMaster>("device_master", sWhere, param);

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

            return apiResult;
        }

        /// <summary>
        /// 修改 設備基本資料
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> SaveDeviceMaster(PostDeviceMaster post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                string sWhere = @$"device_master_guid = @Guid";

                object param = new { Guid = post.Device_master_guid };

                var deviceMaster = await backendRepository.GetOneAsync<DeviceMaster>("device_master", sWhere, param);

                if (deviceMaster == null)
                {
                    //新增
                    //產生一組GUID
                    var guid = Guid.NewGuid();

                    var image_name = string.Empty;

                    var split_image = new string[0];
                    if (post.Device_master_icon_file != null)
                    {
                        split_image = post.Device_master_icon_file.FileName.Split(".");

                        image_name = guid + "." + split_image[split_image.Length - 1];
                    }

                    string temp_device_master_number = null;
                    if (!string.IsNullOrEmpty( post.Device_building_tag) && !string.IsNullOrEmpty(post.Device_name_tag))
                    {
                        temp_device_master_number = post.Device_building_tag + "_" + post.Device_name_tag;
                    }

                    Dictionary<string, object> deviceMasterDic = new Dictionary<string, object>()
                    {
                        { "@device_master_guid", guid},
                        { "@device_building_tag", post.Device_building_tag},
                        { "@device_name_tag", post.Device_name_tag},
                        { "@device_master_number", temp_device_master_number},
                        { "@device_master_full_name", post.Device_master_full_name},
                        { "@device_master_icon", image_name },
                        { "@created_by", myUserInfo.Userinfo_guid}
                    };
                    await backendRepository.AddOneByCustomTable(deviceMasterDic, "device_master");

                    if (post.Device_master_icon_file != null)
                    {
                        var split = post.Device_master_icon_file.FileName.Split(".");
                        var fileName = guid + "." + split[split.Length - 1];

                        var fullPath = Path.Combine(deviceKindFileSaveAsPath, fileName);

                        using (var stream = new FileStream(fullPath, FileMode.Create))
                        {
                            post.Device_master_icon_file.CopyTo(stream);
                        }
                    }

                    #region 新增至派送資料表
                    List<Repository.Models.FileInfo> fileInfos = new List<Repository.Models.FileInfo>();
                    if (post.Device_master_icon_file != null)
                    {
                        var split = post.Device_master_icon_file.FileName.Split(".");
                        var fileName = guid + "." + split[split.Length - 1];

                        var fullPath = Path.Combine(deviceKindFileSaveAsPath, fileName);

                        Repository.Models.FileInfo fileInfo = new Repository.Models.FileInfo();
                        fileInfo.Folder = "device_icon";
                        fileInfo.OriginalFileName = null;
                        fileInfo.FileName = fileName;
                        fileInfo.File = fullPath;

                        fileInfos.Add(fileInfo);
                        await backendRepository.ManualInsertFileBackgroundServiceTask("", "", "device_master", fileInfos);
                    }
                    #endregion

                    apiResult.Code = "0000";
                    apiResult.Msg = "新增成功";
                }
                else
                {
                    var image_name = string.Empty;
                    var image_guid = Guid.NewGuid();
                    var split_image = new string[0];
                    if (post.Device_master_icon_file != null)
                    {
                        split_image = post.Device_master_icon_file.FileName.Split(".");

                        image_name = image_guid + "." + split_image[split_image.Length - 1];
                    }
                    else
                    {
                        image_name = deviceMaster.Device_master_icon;
                    }

                    Dictionary<string, object> deviceMasterDic = new Dictionary<string, object>()
                    {
                        { "@device_master_icon", image_name},
                        { "@device_master_full_name", post.Device_master_full_name},
                        { "@updated_by", myUserInfo.Userinfo_guid},
                        { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
                    };
                    await backendRepository.UpdateOneByCustomTable(deviceMasterDic, "device_master", "device_master_guid='" + deviceMaster.Device_master_guid + "'");

                    if (post.Device_master_icon_file != null)
                    {
                        //刪除原本的檔案
                        FolderFunction folderFunction = new FolderFunction();
                        folderFunction.DeleteFile(Path.Combine(deviceKindFileSaveAsPath, deviceMaster.Device_master_icon));

                        var split = post.Device_master_icon_file.FileName.Split(".");
                        var fileName = image_guid + "." + split[split.Length - 1];

                        var fullPath = Path.Combine(deviceKindFileSaveAsPath, fileName);

                        using (var stream = new FileStream(fullPath, FileMode.Create))
                        {
                            post.Device_master_icon_file.CopyTo(stream);
                        }
                    }

                    #region 新增至派送資料表
                    List<Repository.Models.FileInfo> fileInfos = new List<Repository.Models.FileInfo>();
                    if (post.Device_master_icon_file != null)
                    {
                        var split = post.Device_master_icon_file.FileName.Split(".");
                        var fileName = image_guid + "." + split[split.Length - 1];

                        var fullPath = Path.Combine(deviceKindFileSaveAsPath, fileName);

                        Repository.Models.FileInfo fileInfo = new Repository.Models.FileInfo();
                        fileInfo.Folder = "device_icon";
                        fileInfo.OriginalFileName = deviceMaster.Device_master_icon;
                        fileInfo.FileName = fileName;
                        fileInfo.File = fullPath;

                        fileInfos.Add(fileInfo);
                        await backendRepository.ManualInsertFileBackgroundServiceTask("", "", "device_kind", fileInfos);
                    }
                    #endregion

                    apiResult.Code = "0000";
                    apiResult.Msg = "修改成功";
                }
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 取得子系統的device item
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<Device_item>>> GetDeviceItem(string sub_system_tag)
        {
            ApiResult<List<Device_item>> apiResult = new ApiResult<List<Device_item>>();

            try
            {
                string sWhere = "deleted = 0 AND sub_system_tag = @Sub_system_tag";

                object param = new { Sub_system_tag = sub_system_tag };

                var deviceItems = await backendRepository.GetAllAsync<Device_item>("device_item", sWhere, param);

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

            return apiResult;
        }
    }
}