using FrontendWebApi.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Repository.BackendRepository.Interface;
using Repository.FrontendRepository.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.StaticFiles;
using NPOI.HPSF;

namespace FrontendWebApi.ApiControllers
{
    public class HistoryController : MyBaseApiController<EmergencyRecordController>
    {
        private readonly IBackendRepository backendRepository;
        private readonly IFrontendRepository frontendRepository;

        public HistoryController
        (
            IBackendRepository backendRepository,
            IFrontendRepository frontendRepository
        )
        {
            this.backendRepository = backendRepository;
            this.frontendRepository = frontendRepository;
        }

        /// <summary>
        /// 匯出excel
        /// </summary>
        /// <param name="lhe"></param>
        /// <returns></returns>
        public ActionResult<ApiResult<string>> OpeExportExcel([FromBody] List<HistoryExport> lhe)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            if (lhe == null)
            {
                apiResult.Code = "0001";
                apiResult.Msg = "沒有資料匯入";
                return apiResult;
            }

            try
            {
                var fileDateName = lhe.FirstOrDefault().dateType == "month" ? lhe.FirstOrDefault().starttime.ToString("yyyy-MM") : lhe.FirstOrDefault().endtime == null ? lhe.FirstOrDefault().starttime.ToString("yyyy-MM-dd") : lhe.FirstOrDefault().starttime.ToString("yyyy-MM-dd") + "_" + ((DateTime)lhe.FirstOrDefault().endtime).ToString("yyyy-MM-dd");
                var fileName = "歷史資料_"+fileDateName+".xlsx";
                var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "excel", "history");

                if (!System.IO.Directory.Exists(filePath))
                    System.IO.Directory.CreateDirectory(filePath);

                using (var fs = new FileStream(Path.Combine(filePath, fileName), FileMode.Create, FileAccess.Write))
                {
                    IWorkbook workbook = new XSSFWorkbook();
                    #region excel設定
                    IFont font12 = workbook.CreateFont();
                    font12.FontName = "新細明體";
                    font12.FontHeightInPoints = 12;
                    ICellStyle style12 = workbook.CreateCellStyle();
                    style12.SetFont(font12);
                    style12.Alignment = HorizontalAlignment.Center;
                    style12.VerticalAlignment = VerticalAlignment.Center;
                    IFont font12Times = workbook.CreateFont();
                    font12Times.FontName = "Times New Roman";
                    font12Times.FontHeightInPoints = 12;
                    IFont font18 = workbook.CreateFont();
                    font18.FontName = "新細明體";
                    font18.FontHeightInPoints = 18;
                    font18.IsBold = true;
                    ICellStyle styleTitle18 = workbook.CreateCellStyle();
                    styleTitle18.SetFont(font18);
                    styleTitle18.Alignment = HorizontalAlignment.Center;
                    styleTitle18.VerticalAlignment = VerticalAlignment.Center;
                    ICellStyle styleLeft12 = workbook.CreateCellStyle();
                    styleLeft12.SetFont(font12);
                    styleLeft12.Alignment = HorizontalAlignment.Left;
                    styleLeft12.VerticalAlignment = VerticalAlignment.Center;
                    ICellStyle styleLine12 = workbook.CreateCellStyle();
                    styleLine12.SetFont(font12);
                    styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
                    styleLine12.VerticalAlignment = VerticalAlignment.Center;
                    styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                    styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                    styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                    styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                    ICellStyle stylein12 = workbook.CreateCellStyle();
                    stylein12.SetFont(font12Times);
                    stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;
                    stylein12.VerticalAlignment = VerticalAlignment.Center;
                    stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                    stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                    stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                    stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                    stylein12.WrapText = true;
                    #endregion

                    ISheet sheet = workbook.CreateSheet("歷史資料");
                    int RowPosition = 0;
                    #region set cell
                    IRow row = sheet.CreateRow(RowPosition);
                    sheet.SetColumnWidth(0, 4 * 160 * 12);
                    sheet.SetColumnWidth(1, 4 * 160 * 12);
                    sheet.SetColumnWidth(2, 4 * 160 * 12);
                    ICell cell = row.CreateCell(0);
                    cell.SetCellValue("設備名稱");
                    cell.CellStyle = styleLine12;
                    cell = row.CreateCell(1);
                    cell.SetCellValue("數值");
                    cell.CellStyle = styleLine12;
                    cell = row.CreateCell(2);
                    cell.SetCellValue("記錄時間");
                    cell.CellStyle = styleLine12;
                    #endregion

                    if (lhe.Count > 0)
                    {
                        foreach (var he in lhe)
                        {
                            RowPosition += 1;
                            row = sheet.CreateRow(RowPosition);
                            for (var i = 0; i < 3; i++)
                            {
                                cell = row.CreateCell(i);
                                if (i == 0)
                                {
                                    cell.SetCellValue(he.type);
                                }
                                if (i == 1)
                                {
                                    cell.SetCellValue(he.deviceName);
                                }
                                if (i == 2)
                                {
                                    cell.SetCellValue(he.value);
                                }
                                if (i == 3)
                                {
                                    cell.SetCellValue(he.timestamp.ToString("yyyy-MM-dd HH:mm") + ":00");//
                                }

                                cell.CellStyle = style12;
                            }
                        }
                    }

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

        /// <summary>
        /// 即時趨勢條件過濾條件面板
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/GetMainSub")]
        public async Task<ActionResult<ApiResult<History_MainSubBuildFloor>>> GetMainSub([FromBody] HistoryFind hf)
        {
            ApiResult<History_MainSubBuildFloor> apiResult = new ApiResult<History_MainSubBuildFloor>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            else if (string.IsNullOrEmpty(hf.building_tag))
            {
                apiResult.Code = "0002";
                apiResult.Msg = "必須選擇東別";
                return apiResult;
            }

            try
            {
                var dbsub = await frontendRepository.GetAllAsync<HistoryDBMainSub>(
                    @$"select distinct v1.system_key main_name, v1.system_value main_system_tag, v2.system_key sub_name, v2.system_value sub_system_tag, v1.system_priority, v2.system_priority,
                                       d.device_number, d.full_name as device_full_name, d.device_serial_tag
                        from role_auth a
                        join auth_page b on a.AuthCode = b.AuthCode
                        join userinfo c on c.role_guid = a.role_guid
                        join variable v2 on b.ShowView = v2.id and v2.system_type = @sub_system_type
                        join variable v1 on v1.id = v2.system_parent_id and v1.system_type = @main_system_type
                        join device d on v1.system_value = d.device_system_tag and v2.system_value = d.device_name_tag and d.deleted = 0
                        where c.account = @account
                        order by v1.system_priority, v2.system_priority", new { @account = myUser.account, @sub_system_type = sub_system_type, @main_system_type = main_system_type });
                var dbbuilding = await frontendRepository.GetAllAsync<History_Build>(
                    @$"select distinct d.building_guid,d.full_name,d.priority from role_auth a
                        join auth_page b on a.AuthCode = b.AuthCode
                        join userinfo c on c.role_guid = a.role_guid
                        join building d on d.building_tag = b.building_tag
                        where c.account = @account and d.building_tag = @building_tag
                        order by d.priority 
                        ", new { @account = myUser.account, @building_tag = hf.building_tag });
                var mains = dbsub.GroupBy(a => a.main_system_tag).ToList();
                apiResult.Data = new History_MainSubBuildFloor();
                apiResult.Data.history_Main_Systems = new List<History_Main_system>();
                foreach (var main in mains)
                {
                    History_Main_system history_Main_System = new History_Main_system();
                    history_Main_System.main_system_tag = main.Select(a => a.main_system_tag).FirstOrDefault();
                    history_Main_System.full_name = main.Select(a => a.main_name).FirstOrDefault();

                    var subs = dbsub.Where(x => x.main_system_tag == main.Select(m => m.main_system_tag).FirstOrDefault()).GroupBy(x => x.sub_system_tag).ToList();
                    history_Main_System.History_Sub_systems = subs.Count > 0 ? new List<History_Sub_system>() : null;
                    foreach (var sub in subs)
                    {
                        History_Sub_system history_Sub_System = new History_Sub_system();
                        history_Sub_System.full_name = sub.Select(x => x.sub_name).FirstOrDefault();
                        history_Sub_System.sub_system_tag = sub.Select(x => x.sub_system_tag).FirstOrDefault();


                        var devices = dbsub.Where(x => x.main_system_tag == main.Select(m => m.main_system_tag).FirstOrDefault() && x.sub_system_tag == sub.Select(x => x.sub_system_tag).FirstOrDefault() && x.device_number != null).ToList();
                        history_Sub_System.device = devices.Count > 0 ? new List<Device>() : null;
                        foreach (var d in devices)
                        {
                            Device device = new Device();
                            device.device_number = d.device_number;
                            device.device_serial_tag = d.device_serial_tag;
                            device.full_name = d.device_full_name;
                            history_Sub_System.device.Add(device);
                        }

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

        /// <summary>
        /// 即時趨勢條件過濾條件面板
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/GetDevPoi")]
        public async Task<ActionResult<ApiResult<List<DeviceItem>>>> GetDevPoi([FromBody] HistoryFind hf)
        {
            ApiResult<List<DeviceItem>> apiResult = new ApiResult<List<DeviceItem>>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            else if (string.IsNullOrEmpty(hf.device_number))
            {
                apiResult.Code = "0002";
                apiResult.Msg = "必須選擇設備";
                return apiResult;
            }

            try
            {
                List<DeviceItem> deviceItems = new List<DeviceItem>();
                var main_system_value = hf.device_number.Split('_')[2];
                var sub_system_value = hf.device_number.Split('_')[3];
                var sqlString = $@"select * from device_item where deleted = 0 and device_system_tag = @main_system_value and device_name_tag = @sub_system_value and is_show_history = 1";
                deviceItems = await frontendRepository.GetAllAsync<DeviceItem>(sqlString, new { @main_system_value = main_system_value, @sub_system_value = sub_system_value });

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

        /// <summary>
        /// 依據過濾條件取得設備列表
        /// </summary>
        /// <param name="postDevice"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/GetDevice")]
        public async Task<ActionResult<ApiResult<List<History_GetDevice>>>> GetDevice(History_PostDevice postDevice)
        {
            ApiResult<List<History_GetDevice>> apiResult = new ApiResult<List<History_GetDevice>>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }

            try
            {
                List<string> wheres = new List<string>();
                wheres.Add("d.deleted = 0");
                if (postDevice.SelectBuildings != null && postDevice.SelectBuildings.Count() > 0)
                {
                    wheres.Add("d.building_guid in @builds");
                }

                if (postDevice.SelectFloors != null && postDevice.SelectFloors.Count() > 0)
                {
                    wheres.Add("d.floor_guid in @floor_guid");
                }

                if (postDevice.SelectSub != null && postDevice.SelectSub.Count() > 0)
                {
                    wheres.Add("d.sub_system_guid in @syss");
                }

                if (!string.IsNullOrEmpty(postDevice.Device_name))
                {
                    wheres.Add("d.full_name LIKE CONCAT('%', @device_name, '%')");
                }

                var wheres_str = string.Join(" AND ", wheres);

                var sql = $@"SELECT
                                a.device_guid,
                                b.full_name building_name,
                                c.full_name main_name,
                                d.full_name sub_name,
                                d.full_name sub_name,
                                a.full_name device_name,
                                a.device_number
                            from (SELECT * 
                                    FROM device d
                                    WHERE {wheres_str}) a
                            join building b on b.building_guid = a.building_guid
                            join main_system c on c.main_system_guid = a.main_system_guid
                            join sub_system d on d.sub_system_guid = a.sub_system_guid
                            order by b.priority,c.priority,d.priority,a.priority";

                var dbDevice = await backendRepository.GetAllAsync<History_GetDevice>(sql, new { builds = postDevice.SelectBuildings, floor_guid = postDevice.SelectFloors, syss = postDevice.SelectSub, device_name = postDevice.Device_name });
                apiResult.Data = dbDevice;
                apiResult.Code = "0000";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            return Ok(apiResult);
        }

        /// <summary>
        /// 依據選得的設備,查看所有設備點位
        /// </summary>
        /// <param name="postDevice"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/LookRealTime")]
        public async Task<ActionResult<ApiResult<List<History_PostItem>>>> LookRealTime(itemlist postDevice)
        {
            ApiResult<List<History_PostItem>> apiResult = new ApiResult<List<History_PostItem>>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                var dbDevice = await backendRepository.GetAllAsync<History_PostItem>(
                    @$"select c.full_name building_name,b.device_number,b.full_name device_name,a.full_name item_name,a.points,a.unit 
                        from device_item a
                        join device b on a.sub_system_guid = b.sub_system_guid
                        join building c on c.building_guid = b.building_guid
                        join sub_system d on d.sub_system_guid = b.sub_system_guid
                        join main_system e on e.main_system_guid = b.main_system_guid
                        where a.deleted = 0 and b.deleted = 0 and d.deleted = 0 and e.deleted = 0
                        and a.unit is not null and b.device_number in @Device_number
                        order by c.priority,b.priority
                        "
                        , new { Device_number = postDevice.select_data.Select(a => a.device_number).ToList() }
                    );
                apiResult.Data = dbDevice;
                apiResult.Code = "0000";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            return Ok(apiResult);
        }

        /// <summary>
        /// 取得即時趨勢常用組合
        /// </summary>
        /// <param name="postDevice"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/RealTimeCombination")]
        public async Task<ActionResult<ApiResult<List<RealTimeCombination>>>> GetRealTimeCombination(PostRealTimeCombination post)
        {
            ApiResult<List<RealTimeCombination>> apiResult = new ApiResult<List<RealTimeCombination>>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                var sql = $@"
                            SELECT
                             rc.combination_guid,
                             rc.full_name AS combination_full_name,
                             rcd.device_guid,
                             d.device_number,
                             d.full_name AS Device_full_name,
                             b.full_name AS Building_full_name,
                             ms.full_name AS Main_system_full_name,
                             ss.full_name AS Sub_system_full_name
                            FROM realtime_combination_detail rcd
                            LEFT JOIN 
                            (SELECT
                                rc.*
                             FROM realtime_combination rc
                             WHERE building_guid = @building_guid
                                AND userinfo_guid = @userinfo_guid
                            ) rc ON rcd.combination_guid = rc.combination_guid
                            JOIN device d ON d.deleted = 0 AND d.device_guid = rcd.device_guid
                            JOIN building b ON b.deleted = 0 AND b.building_guid = d.building_guid
                            JOIN main_system ms ON ms.deleted = 0 AND ms.main_system_guid = d.main_system_guid
                            JOIN sub_system ss ON ss.deleted = 0 AND ss.sub_system_guid = d.sub_system_guid
                            WHERE rc.deleted = 0";

                var rawDatas = await frontendRepository.GetAllAsync<RealTimeCombinationRawData>(sql, new { building_guid = post.building_guid, userinfo_guid = myUser.userinfo_guid });

                var rawDatas_groups = rawDatas.GroupBy(x => x.Combination_guid).ToList();

                List<RealTimeCombination> realTimeCombinations = new List<RealTimeCombination>();

                foreach (var rawDatas_group in rawDatas_groups)
                {
                    RealTimeCombination realTimeCombination = new RealTimeCombination();
                    realTimeCombination.Combination_guid = rawDatas_group.Key;
                    realTimeCombination.Combination_full_name = rawDatas_group.First().Combination_full_name;
                    realTimeCombination.Details = new List<RealTimeCombinationDetail>();

                    foreach (var rawData in rawDatas_group)
                    {
                        RealTimeCombinationDetail realTimeCombinationDetail = new RealTimeCombinationDetail();
                        realTimeCombinationDetail.Combination_guid = rawData.Combination_guid;
                        realTimeCombinationDetail.Device_guid = rawData.Device_guid;
                        realTimeCombinationDetail.Device_number = rawData.Device_number;
                        realTimeCombinationDetail.Device_full_name = rawData.Device_full_name;
                        realTimeCombinationDetail.Building_full_name = rawData.Building_full_name;
                        realTimeCombinationDetail.Main_system_full_name = rawData.Main_system_full_name;
                        realTimeCombinationDetail.Sub_system_full_name = rawData.Sub_system_full_name;

                        realTimeCombination.Details.Add(realTimeCombinationDetail);
                    }

                    realTimeCombinations.Add(realTimeCombination);
                }

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

        /// <summary>
        /// 新增常用組合(包含覆蓋、另存新檔)
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/SaveRealTimeCombination")]
        public async Task<ActionResult<ApiResult<string>>> SaveRealTimeCombination(PostSaveRealTimeCombination post)
        {
            ApiResult<string> apiResult = new ApiResult<string>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                if (post.Save_type == 1)
                {   //另存新檔

                    //產生一組GUID
                    var guid = Guid.NewGuid();  //常用組合GUID

                    Dictionary<string, object> combination = new Dictionary<string, object>();
                    combination = new Dictionary<string, object>()
                        {
                            { "@combination_guid", guid},
                            { "@building_guid", post.Building_guid},
                            { "@userinfo_guid", myUser.userinfo_guid},
                            { "@full_name", post.Full_name},
                            { "@created_by", myUser.userinfo_guid}
                        };
                    await frontendRepository.AddOneByCustomTable(combination, "realtime_combination");

                    List<Dictionary<string, object>> detailDics = new List<Dictionary<string, object>>();
                    foreach (var detail in post.Details)
                    {
                        Dictionary<string, object> detailDic = new Dictionary<string, object>()
                        {
                            { "@combination_guid", guid},
                            { "@device_guid", detail.Device_guid},
                            { "@created_by", myUser.userinfo_guid}
                        };

                        detailDics.Add(detailDic);
                    }

                    await frontendRepository.AddMutiByCustomTable(detailDics, "realtime_combination_detail");
                }
                else
                {   //覆蓋
                    var sWhere = $@"deleted = 0 AND combination_guid = @combination_guid";

                    var realTimeCombination = await frontendRepository.GetOneAsync<RealTimeCombination>("realtime_combination", sWhere, new { combination_guid = post.Combination_guid });

                    if (realTimeCombination == null)
                    {
                        apiResult.Code = "9996";
                        apiResult.Msg = "查無該常用組合";

                        return Ok(apiResult);
                    }
                    else
                    {
                        //刪除該組合的所有設備
                        await frontendRepository.PurgeOneAsync(realTimeCombination.Combination_guid, "realtime_combination_detail", "combination_guid");

                        //重新新增
                        List<Dictionary<string, object>> detailDics = new List<Dictionary<string, object>>();
                        foreach (var detail in post.Details)
                        {
                            Dictionary<string, object> detailDic = new Dictionary<string, object>()
                            {
                                { "@combination_guid", realTimeCombination.Combination_guid},
                                { "@device_guid", detail.Device_guid},
                                { "@created_by", myUser.userinfo_guid}
                            };

                            detailDics.Add(detailDic);
                        }

                        await frontendRepository.AddMutiByCustomTable(detailDics, "realtime_combination_detail");
                    }
                }

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

        /// <summary>
        /// 修改常用組合名稱
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/EditRealTimeCombination")]
        public async Task<ActionResult<ApiResult<string>>> EditRealTimeCombination(PostEditRealTimeCombination post)
        {
            ApiResult<string> apiResult = new ApiResult<string>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                var sWhere = $@"deleted = 0 AND combination_guid = @combination_guid";

                var realTimeCombination = await frontendRepository.GetOneAsync<RealTimeCombination>("realtime_combination", sWhere, new { combination_guid = post.Combination_guid });

                if (realTimeCombination == null)
                {
                    apiResult.Code = "9996";
                }
                else
                {
                    Dictionary<string, object> realTimeCombinationDic = new Dictionary<string, object>()
                    {
                        { "@full_name", post.Full_name },
                        { "@updated_by", myUser.userinfo_guid},
                        { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
                    };

                    await frontendRepository.UpdateOneByCustomTable(realTimeCombinationDic, "realtime_combination", "combination_guid = '" + post.Combination_guid + "'");
                }

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

        /// <summary>
        /// 刪除常用組合名稱
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/DeleteRealTimeCombination")]
        public async Task<ActionResult<ApiResult<string>>> DeleteRealTimeCombination(string guid)
        {
            ApiResult<string> apiResult = new ApiResult<string>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                var sWhere = $@"deleted = 0 AND combination_guid = @combination_guid";

                var realTimeCombination = await frontendRepository.GetOneAsync<RealTimeCombination>("realtime_combination", sWhere, new { combination_guid = guid });

                if (realTimeCombination == null)
                {
                    apiResult.Code = "9996";
                }
                else
                {
                    await frontendRepository.DeleteOne(guid, "realtime_combination", "combination_guid");
                }

                apiResult.Code = "0000";

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


        //[HttpPost]
        //[Route("api/History/GetHistoryMenu")]
        //public async Task<ActionResult<ApiResult<List<History_Main_system>>>> GetHistoryMenu(string account)
        //{
        //    ApiResult<List<History_Main_system>> apiResult = new ApiResult<List<History_Main_system>>(jwt_str);
        //    if (!jwtlife)
        //    {
        //        apiResult.Code = "5000";
        //        return BadRequest(apiResult);
        //    }
        //    try
        //    {
        //        var dbitems = await backendRepository.GetAllAsync<HistoryClass>(
        //            @$"select c.main_system_guid ,c.full_name main_name,b.sub_system_guid,b.full_name sub_name,e.building_guid,e.full_name building_name,a.device_item_guid,a.full_name item_name
        //            from device_item a
        //            join sub_system b on b.sub_system_guid = a.sub_system_guid
        //            join main_system c on c.main_system_guid = b.main_system_guid
        //            join auth_page d on d.ShowView = b.sub_system_guid
        //            join building e on e.building_guid = d.building_guid
        //            join role_auth f on f.AuthCode = d.AuthCode
        //            join userinfo g on g.role_guid = f.role_guid
        //            where g.account = '{account}' and a.deleted = 0");

        //        var dbdevice = await backendRepository.GetAllAsync<History_Sub_device>
        //            ("device", " deleted = 0");

        //        var main_systems = dbitems.GroupBy(a => a.main_system_guid).ToList();
        //        List<History_Main_system> History_Main_system = new List<History_Main_system>();
        //        foreach (var main_system in main_systems)
        //        {
        //            History_Main_system history_Main_System = new History_Main_system()
        //            {
        //                History_Sub_systems = new List<History_Sub_system>(),
        //                main_system_guid = main_system.Select(a => a.main_system_guid).FirstOrDefault(),
        //                full_name = main_system.Select(a => a.main_name).FirstOrDefault()
        //            };
        //            var sub_systems = main_system.GroupBy(a => a.sub_system_guid).ToList();
        //            foreach (var sub_system in sub_systems)
        //            {
        //                History_Sub_system history_Sub_System = new History_Sub_system()
        //                {
        //                    sub_system_guid = sub_system.Select(a => a.sub_system_guid).FirstOrDefault(),
        //                    full_name = sub_system.Select(a => a.sub_name).FirstOrDefault(),
        //                    History_Builds = new List<History_Build>()
        //                };
        //                var builds = sub_system.GroupBy(a => a.building_guid).ToList();
        //                foreach (var build in builds)
        //                {
        //                    History_Build history_Build = new History_Build()
        //                    {
        //                        building_guid = build.Select(a => a.building_guid).First(),
        //                        full_name = build.Select(a => a.building_name).FirstOrDefault(),
        //                        History_Devices = new List<History_Device>()
        //                    };
        //                    var devices = dbdevice.Where(a => a.building_guid == history_Build.building_guid & a.sub_system_guid == history_Sub_System.sub_system_guid).ToList();
        //                    foreach (var device in devices)
        //                    {
        //                        History_Device history_Device = new History_Device()
        //                        {
        //                            device_guid = device.device_guid,
        //                            full_name = device.full_name,
        //                            History_Deviceitems = new List<History_Deviceitem>()
        //                        };
        //                        var items = build.GroupBy(a => a.device_item_guid).ToList();
        //                        foreach (var item in items)
        //                        {
        //                            History_Deviceitem history_Deviceitem = new History_Deviceitem()
        //                            {
        //                                device_item_guid = item.Select(a => a.device_item_guid).FirstOrDefault(),
        //                                full_name = item.Select(a => a.item_name).FirstOrDefault()
        //                            };
        //                            history_Device.History_Deviceitems.Add(history_Deviceitem);
        //                        }
        //                        history_Build.History_Devices.Add(history_Device);
        //                    }
        //                    history_Sub_System.History_Builds.Add(history_Build);
        //                }
        //                history_Main_System.History_Sub_systems.Add(history_Sub_System);
        //            }
        //            History_Main_system.Add(history_Main_System);
        //        }
        //        apiResult.Code = "0000";
        //        apiResult.Data = History_Main_system;
        //    }
        //    catch (Exception exception)
        //    {
        //        apiResult.Code = "9999";
        //        Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
        //        return Ok(apiResult);
        //    }
        //    return Ok(apiResult);
        //}

        /// <summary>
        /// 歷史資料查詢過濾條件面板
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/GetHistoryFilterPanel")]
        public async Task<ActionResult<ApiResult<History_MainSubBuildFloor>>> GetHistoryFilterPanel(PostHistoryFilterPanel post)
        {
            ApiResult<History_MainSubBuildFloor> apiResult = new ApiResult<History_MainSubBuildFloor>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                #region 取得區域樓層
                var sqlBuildingFloor = $@"SELECT
                                            b.building_guid,
                                            b.full_name AS building_name,
                                            b.priority,
                                            f.floor_guid,
                                            f.full_name AS floor_name,
                                            f.priority
                                          FROM building b
                                          JOIN floor f ON f.deleted = 0 AND f.building_guid = b.building_guid
                                          WHERE b.building_guid IN (
                                                            SELECT
                                                                ap.building_guid
                                                            FROM role_auth ra
                                                            JOIN auth_page ap ON ra.AuthCode = ap.AuthCode
                                                            JOIN userinfo u ON u.role_guid = ra.role_guid WHERE u.account = @Account
                                                            )
                                          ORDER BY b.priority, f.priority";

                var buildingFloorRawDatas = await frontendRepository.GetAllAsync<BuildingFloorRawData>(sqlBuildingFloor, post);

                var buildingFloorRawDatas_GroupBy_building_guid = buildingFloorRawDatas.GroupBy(x => x.building_guid).ToList();

                List<History_Build> history_Builds = new List<History_Build>();
                foreach (var buildingFloorRawData in buildingFloorRawDatas_GroupBy_building_guid)
                {
                    List<History_Floor> history_Floors = new List<History_Floor>();
                    foreach (var floorRawData in buildingFloorRawData)
                    {
                        History_Floor history_Floor = new History_Floor()
                        {
                            floor_guid = floorRawData.floor_guid,
                            full_name = floorRawData.floor_name,
                        };

                        history_Floors.Add(history_Floor);
                    }

                    History_Build history_Build = new History_Build()
                    {
                        building_guid = buildingFloorRawData.Key,
                        full_name = buildingFloorRawData.First().building_name,
                        history_Floors = history_Floors
                    };

                    history_Builds.Add(history_Build);
                }
                #endregion

                #region 取得系統大小類
                var sqlMainSubSystem = $@"SELECT
                                            ms.main_system_guid,
                                            ms.full_name AS main_name,
                                            ss.sub_system_guid,
                                            ss.full_name AS sub_name
                                        FROM sub_system ss
                                        JOIN main_system ms ON ms.deleted = 0 AND ss.main_system_guid = ms.main_system_guid
                                        WHERE ss.deleted = 0
                                        AND ss.sub_system_guid IN (
                                                                SELECT
                                                                    ap.ShowView
                                                                FROM role_auth ra
                                                                JOIN auth_page ap ON ra.AuthCode = ap.AuthCode
                                                                JOIN userinfo u ON u.role_guid = ra.role_guid WHERE u.account = @Account
                                                                )
                                        ORDER BY ms.priority, ss.priority";

                var mainSubSystemRawDatas = await frontendRepository.GetAllAsync<HistoryDBMainSub>(sqlMainSubSystem, post);

                var mainSubSystemRawDatas_GroupBy_main_system_guid = mainSubSystemRawDatas.GroupBy(x => x.main_system_tag).ToList();

                List<History_Main_system> history_Main_Systems = new List<History_Main_system>();
                foreach (var mainSubSystemRawData in mainSubSystemRawDatas_GroupBy_main_system_guid)
                {
                    List<History_Sub_system> history_Sub_Systems = new List<History_Sub_system>();
                    foreach (var SubSystemRawData in mainSubSystemRawData)
                    {
                        History_Sub_system history_Sub_System = new History_Sub_system()
                        {
                            sub_system_tag = SubSystemRawData.sub_system_tag,
                            full_name = SubSystemRawData.sub_name,
                        };

                        history_Sub_Systems.Add(history_Sub_System);
                    }

                    History_Main_system history_Main_System = new History_Main_system()
                    {
                        main_system_tag = mainSubSystemRawData.Key,
                        full_name = mainSubSystemRawData.First().main_name,
                        History_Sub_systems = history_Sub_Systems
                    };

                    history_Main_Systems.Add(history_Main_System);
                }
                #endregion

                History_MainSubBuildFloor history_MainSubBuildFloor = new History_MainSubBuildFloor()
                {
                    history_Builds = history_Builds,
                    history_Main_Systems = history_Main_Systems
                };

                apiResult.Code = "0000";
                apiResult.Data = history_MainSubBuildFloor;

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

        /// <summary>
        /// 取得歷史資料
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/History/GetHistoryRawData")]
        public async Task<ActionResult<ApiResult<List<HistoryRawData>>>> GetHistoryRawData(PostHistoryRawDataFilter post)
        {
            ApiResult<List<HistoryRawData>> apiResult = new ApiResult<List<HistoryRawData>>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                EDFunction ed = new EDFunction();
                var obixApiConfig = new ObixApiConfig();

                var sqlObix = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'obixConfig'";

                var variable = await frontendRepository.GetAllAsync<KeyValue>(sqlObix);
                obixApiConfig.ApiBase = variable.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
                obixApiConfig.UserName = ed.AESDecrypt(variable.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
                obixApiConfig.Password = ed.AESDecrypt(variable.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());

                String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(obixApiConfig.UserName + ":" + obixApiConfig.Password));

                //找出被選擇的設備編號
                var device_numbers = post.HistoryItems.Select(x => x.Device_number_point.Split(":")[0]).Distinct().ToList();

                //依據被選擇的設備找出相對應資料
                var sqlDeviceItemInfo = $@"SELECT
                                b.full_name AS building_name,
                                ms.full_name AS Main_system_name,
                                ss.full_name AS Sub_system_name,
                                temp.device_number,
                                temp.device_name,
                                temp.full_name AS item_name,
                                temp.points,
                                temp.unit
                                FROM ( SELECT
                                        di.*,
                                        d.building_guid,
                                        d.main_system_guid,
                                        -- d.sub_system_guid,
                                        d.device_number,
                                        d.full_name AS device_name,
                                        d.priority
                                        FROM device_item di
                                        JOIN device d ON d.deleted = 0 AND di.sub_system_guid = d.sub_system_guid
                                        WHERE di.deleted = 0 AND di.unit IS NOT NULL AND d.device_number IN @Device_number) temp
                                JOIN building b ON b.deleted = 0 AND temp.building_guid = b.building_guid
                                JOIN main_system ms ON ms.deleted = 0 AND temp.main_system_guid = ms.main_system_guid
                                JOIN sub_system ss ON ss.deleted = 0 AND temp.sub_system_guid = ss.sub_system_guid
                                ORDER BY b.priority, ms.priority, ss.priority, temp.priority";

                var device_item_infos = await frontendRepository.GetAllAsync<DeviceItemInfo>(sqlDeviceItemInfo, new { Device_number = device_numbers });

                //轉換日期格式
                var start = string.Format("{0}T00:00:00.000+08:00", post.Start_timstamp);
                var end = string.Format("{0}T23:59:59.000+08:00", post.End_timstamp);

                var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
                                                <abstime name = 'start' val = '{start}' />
                                                <abstime name = 'end' val = '{end}' />
                                            </obj>";

                XmlDocument xmlDocument = new XmlDocument();
                List<HistoryRawData> historyRawDatas = new List<HistoryRawData>();
                List<string> errorPoints = new List<string>(); //錯誤的設備點位
                foreach (var historyItem in post.HistoryItems)
                {
                    var device_number_point = historyItem.Device_number_point.Replace(":", "_");

                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{device_number_point}/~historyQuery/");
                    request.Method = "POST";
                    request.Headers.Add("Authorization", "Basic " + encoded);
                    request.PreAuthenticate = true;

                    byte[] byteArray = Encoding.UTF8.GetBytes(historyQueryFilter);
                    using (Stream reqStream = request.GetRequestStream())
                    {
                        reqStream.Write(byteArray, 0, byteArray.Length);
                    }

                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                    var responseContent = new StreamReader(response.GetResponseStream()).ReadToEnd();

                    xmlDocument.LoadXml(responseContent);
                    string responseContentJson = JsonConvert.SerializeXmlNode(xmlDocument);
                    JObject responseContentJsonResult = (JObject)JsonConvert.DeserializeObject(responseContentJson);

                    if (responseContentJsonResult.ContainsKey("err")) //抓取錯誤
                    {
                        errorPoints.Add(device_number_point);
                        continue;
                    }

                    if (responseContentJsonResult.ContainsKey("obj")) //表示可以讀取到內容
                    {
                        var countObj = responseContentJsonResult["obj"]["int"];
                        if (countObj != null && countObj["@name"].ToString() == "count")
                        {   //判斷是否有資料筆數
                            if (Convert.ToInt32(countObj["@val"].ToString()) > 0)
                            {
                                var dataList = responseContentJsonResult["obj"]["list"];
                                if (dataList != null && dataList["obj"].HasValues)
                                {
                                    //讀取資料
                                    foreach (var obj in dataList["obj"])
                                    {
                                        HistoryRawData historyRawData = new HistoryRawData();

                                        //取得設備基本資訊
                                        var tempSplit = historyItem.Device_number_point.Split(":");
                                        var device_number = tempSplit[0];
                                        var point = tempSplit[1];
                                        var device_item_info = device_item_infos.Where(x => x.Device_number == device_number && x.Points == point).FirstOrDefault();

                                        historyRawData.Building_name = device_item_info.Building_name;
                                        historyRawData.Main_system_name = device_item_info.Main_system_name;
                                        historyRawData.Sub_system_name = device_item_info.Sub_system_name;
                                        historyRawData.Device_number = device_item_info.Device_number;
                                        historyRawData.Device_name = device_item_info.Device_name;
                                        historyRawData.Item_name = device_item_info.Item_name;
                                        historyRawData.Points = device_item_info.Points;
                                        historyRawData.Unit = device_item_info.Unit;

                                        //取得時間
                                        var abstime = obj["abstime"]["@val"].ToString();
                                        historyRawData.Timestamp = Convert.ToDateTime(abstime).ToString("yyyy-MM-dd HH:mm:ss");
                                        //取得資料
                                        historyRawData.Value = obj["real"]["@val"].ToString();

                                        historyRawDatas.Add(historyRawData);
                                    }
                                }
                            }
                        }
                    }
                }

                if (errorPoints.Count() > 0)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = String.Join(",", errorPoints);

                    return Ok(apiResult);
                }

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