using FrontendWebApi.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Repository.FrontendRepository.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FrontendWebApi.ApiControllers
{
    /// <summary>
    /// 告警紀錄
    /// </summary>
    public class AlarmRecordController : MyBaseApiController<AlarmRecordController>
    {
        private readonly IFrontendRepository frontendRepository;
        
        public AlarmRecordController
        (
            IFrontendRepository frontendRepository
        )
        {
            this.frontendRepository = frontendRepository;
        }

        /// <summary>
        /// 告警紀錄過濾條件面板
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("api/AlarmRecord/GetAlarmRecordFilterPanel")]
        public async Task<ActionResult<ApiResult<List<AlarmRecordPanel>>>> GetAlarmRecordFilterPanel(string account)
        {
            ApiResult<List<AlarmRecordPanel>> apiResult = new ApiResult<List<AlarmRecordPanel>>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                var sqlBuildingMain = $@"SELECT
                                            b.building_tag,
                                            b.full_name AS building_name,
                                            v1.system_value,
										    v1.system_key
                                        FROM 
                                        (SELECT * FROM building_menu ORDER BY priority) bm
                                        INNER JOIN (
                                            SELECT
                                               ap.building_tag, 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
                                           AND ap.building_tag IS NOT NULL
                                        ) ap ON bm.building_tag = ap.building_tag 
                                        JOIN building b ON bm.building_tag = b.building_tag and b.deleted = 0
                                        join variable v2 on ap.ShowView = v2.id and v2.deleted = 0
                                        join variable v1 on v2.system_parent_id = v1.id
                                        GROUP BY b.building_tag, b.full_name, v1.system_value, v1.system_key";

                var alarmRecordPanelRawDatas = await frontendRepository.GetAllAsync<AlarmRecordPanelRawData>(sqlBuildingMain, new { Account = account });

                List<AlarmRecordPanel> alarmRecordPanels = new List<AlarmRecordPanel>();

                var alarmRecordPanelRawDatas_GroupBy = alarmRecordPanelRawDatas.GroupBy(x => x.building_tag);

                foreach (var building in alarmRecordPanelRawDatas_GroupBy)
                {
                    AlarmRecordPanel alarmRecordPanel = new AlarmRecordPanel();
                    alarmRecordPanel.building_tag = building.Key;
                    alarmRecordPanel.building_name = building.First().building_name;
                    alarmRecordPanel.mainSystemPanels = new List<MainSystemPanel>();
                    foreach (var tempData in building)
                    {
                        MainSystemPanel mainSystemPanel = new MainSystemPanel();
                        mainSystemPanel.system_value = tempData.system_value;
                        mainSystemPanel.system_key = tempData.system_key;

                        alarmRecordPanel.mainSystemPanels.Add(mainSystemPanel);
                    }

                    alarmRecordPanels.Add(alarmRecordPanel);
                }

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

        [HttpPost]
        [Route("api/AlarmRecord/GetAllAlarmRecord")]
        public async Task<ActionResult<ApiResult<List<AlarmRecordFullInfo>>>> GetAllAlarmRecord(AlarmRecordFilter post)
        {
            ApiResult<List<AlarmRecordFullInfo>> apiResult = new ApiResult<List<AlarmRecordFullInfo>>(jwt_str);
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                var sql = $@"SELECT 
		                            temp_path.source AS alarm_path,
		                            temp_msg.source_msg AS msgText,
		                            from_unixtime(record.timestamp/1000,'%Y-%m-%d %H:%i:%s') alarm_timestamp,
		                            record.priority,
		                            CASE WHEN record.normalTime > 0 THEN from_unixtime(record.normalTime/1000,'%Y-%m-%d %H:%i:%s')
		                            ELSE NULL
		                            END AS normal_timestamp,
		                            record.sourceState AS ackState,
		                            class.alarmclass AS alarm_className,
		                            record.userAccount

                            FROM alarmOrion_OrionAlarmRecord record 
                            JOIN (
		                            SELECT sourceorder.* ,temp_source.source
		                            FROM alarmOrion_OrionAlarmSourceOrder sourceorder
		                            JOIN alarmOrion_OrionAlarmSource temp_source ON sourceorder.alarmSource = temp_source.id
                            ) temp_path ON record.id = temp_path.alarm
                            JOIN(
			                            SELECT 
					                            val.alarm,
					                            val.value AS source_msg
			                            FROM alarmOrion_OrionAlarmFacetValue val 
			                            JOIN alarmOrion_OrionAlarmFacetName nam ON val.facetName = nam.id AND nam.facetName = 'msgText'
                            ) temp_msg ON record.id = temp_msg.alarm
                            JOIN alarmOrion_OrionAlarmClass class ON record.alarmClass = class.id
                            WHERE from_unixtime(record.timestamp/1000,'%Y-%m-%d %H:%i:%s') BETWEEN @StartTimestamp AND @EndTimeStamp";

                if (post.IsSolve != 0)
                {
                    if(post.IsSolve == 1)
                    {   //未解決
                        sql += " AND record.normalTime = 0";
                    }
                    else if(post.IsSolve == 2)
                    {   //已解決
                        sql += " AND record.normalTime > 0";
                    }
                }

                if (post.IsAck != 0)
                {
                    if (post.IsAck == 1)
                    {   //未確認
                        sql += " AND record.sourceState = 1";
                    }
                    else if (post.IsAck == 2)
                    {   //已確認
                        sql += " AND record.sourceState = 0";
                    }
                }

                var alarmRecords = await frontendRepository.GetAllAsync<AlarmRecord>(sql, post);

                foreach (var alarmRecord in alarmRecords)
                {
                    var alarmSplit = alarmRecord.alarm_path.Split("|");
                    var deviceSplit = alarmSplit[alarmSplit.Length - 1].Split("/");
                    var device_number = deviceSplit[deviceSplit.Length - 3];
                    var point = deviceSplit[deviceSplit.Length - 2];

                    alarmRecord.device_number = device_number.Replace("$3", "");
                    alarmRecord.device_point = point.Replace("$3", "");
                }

                //找出設備資訊
                var sql_device = $@"SELECT * 
                                    FROM device d 
                                    WHERE d.deleted = 0 
                                        AND d.device_building_tag = @building_tag
                                        AND d.device_system_tag IN @main_system_tag";

                var devices = await frontendRepository.GetAllAsync<Device>(sql_device, post);

                List<AlarmRecordFullInfo> alarmRecordFullInfos = new List<AlarmRecordFullInfo>();
                foreach (var alarmRecord in alarmRecords)
                {
                    var selected_device = devices.Where(x => x.device_number == alarmRecord.device_number).FirstOrDefault();

                    if (selected_device != null)
                    {
                        var tempMsgText = alarmRecord.msgText.Replace("s:", "").Replace("$", "\\");
                        byte[] bytes = Encoding.Default.GetBytes(tempMsgText);

                        var tempStr = string.Empty;
                        string[] strlist = tempMsgText.Replace("\\", "").Split('u');
                        try
                        {
                            for (int i = 1; i < strlist.Length; i++)
                            {
                                //將unicode轉為10進制整數,然後轉為char中文
                                tempStr += (char)int.Parse(strlist[i], System.Globalization.NumberStyles.HexNumber);
                            }
                        }
                        catch (FormatException ex)
                        {

                        }

                        alarmRecord.msgText = tempStr;

                        AlarmRecordFullInfo alarmRecordFullInfo = new AlarmRecordFullInfo();
                        alarmRecordFullInfo.device_number = alarmRecord.device_number;
                        alarmRecordFullInfo.device_name = selected_device.full_name;
                        alarmRecordFullInfo.device_point = alarmRecord.device_point;
                        alarmRecordFullInfo.priority = alarmRecord.priority;
                        alarmRecordFullInfo.msgText = alarmRecord.msgText;
                        alarmRecordFullInfo.alarm_timestamp = alarmRecord.alarm_timestamp;
                        alarmRecordFullInfo.normal_timestamp = alarmRecord.normal_timestamp;
                        alarmRecordFullInfo.ackState = alarmRecord.ackState;
                        alarmRecordFullInfo.ackText = alarmRecord.ackState == 1 ? "unack" : "ack";
                        alarmRecordFullInfo.alarm_className = alarmRecord.alarm_className;
                        alarmRecordFullInfo.userAccount = alarmRecord.userAccount;

                        alarmRecordFullInfos.Add(alarmRecordFullInfo);
                    }
                }

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


        [HttpPost]
        [Route("api/AlarmRecord/GetAllAlarmRecordExcel")]
        public ActionResult<ApiResult<string>> GetAllAlarmRecordExcel(AlarmRecordFilter post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            var Workbook = new XSSFWorkbook();
            var ms = new NpoiMemoryStream
            {
                AllowClose = false
            };
            #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
            try 
            {
                IActionResult RecordBack = GetAllAlarmRecord(post).Result.Result;
                var RecordBacks = RecordBack as OkObjectResult;
                ApiResult<List<AlarmRecordFullInfo>> Records = (ApiResult<List<AlarmRecordFullInfo>>)RecordBacks.Value;

                var sheet = Workbook.CreateSheet("告警紀錄");
                int RowPosition = 0;
                IRow row = sheet.CreateRow(RowPosition);
                sheet.SetColumnWidth(0, 10 * 160 * 6);
                sheet.SetColumnWidth(1, 4 * 160 * 6);
                sheet.SetColumnWidth(2, 4 * 160 * 6);
                sheet.SetColumnWidth(3, 4 * 160 * 6);
                sheet.SetColumnWidth(4, 6 * 160 * 6);
                sheet.SetColumnWidth(5, 8 * 160 * 6);
                sheet.SetColumnWidth(6, 8 * 160 * 6);
                sheet.SetColumnWidth(7, 4 * 160 * 6);
                sheet.SetColumnWidth(8, 6 * 160 * 6);
                sheet.SetColumnWidth(9, 6 * 160 * 6);
                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;
                cell = row.CreateCell(3);
                cell.SetCellValue("告警層級");
                cell.CellStyle = styleLine12;
                cell = row.CreateCell(4);
                cell.SetCellValue("訊息");
                cell.CellStyle = styleLine12;
                cell = row.CreateCell(5);
                cell.SetCellValue("發報時間");
                cell.CellStyle = styleLine12;
                cell = row.CreateCell(6);
                cell.SetCellValue("賦歸時間");
                cell.CellStyle = styleLine12;
                cell = row.CreateCell(7);
                cell.SetCellValue("確認狀態");
                cell.CellStyle = styleLine12;
                cell = row.CreateCell(8);
                cell.SetCellValue("報警類別");
                cell.CellStyle = styleLine12;
                cell = row.CreateCell(9);
                cell.SetCellValue("確認者");
                cell.CellStyle = styleLine12;

                foreach(var oneRecord in Records.Data)
                {
                    RowPosition += 1;
                    row = sheet.CreateRow(RowPosition);
                    cell = row.CreateCell(0);
                    cell.SetCellValue(oneRecord.device_number);
                    cell.CellStyle = style12;
                    cell = row.CreateCell(1);
                    cell.SetCellValue(oneRecord.device_name);
                    cell.CellStyle = style12;
                    cell = row.CreateCell(2);
                    cell.SetCellValue(oneRecord.device_point);
                    cell.CellStyle = style12;
                    cell = row.CreateCell(3);
                    cell.SetCellValue(oneRecord.priority);
                    cell.CellStyle = style12;
                    cell = row.CreateCell(4);
                    cell.SetCellValue(oneRecord.msgText);
                    cell.CellStyle = style12;
                    cell = row.CreateCell(5);
                    cell.SetCellValue(oneRecord.alarm_timestamp);
                    cell.CellStyle = style12;
                    cell = row.CreateCell(6);
                    cell.SetCellValue(oneRecord.normal_timestamp);
                    cell.CellStyle = style12;
                    cell = row.CreateCell(7);
                    cell.SetCellValue(oneRecord.ackText);
                    cell.CellStyle = style12;
                    cell = row.CreateCell(8);
                    cell.SetCellValue(oneRecord.alarm_className);
                    cell.CellStyle = style12;
                    cell = row.CreateCell(9);
                    cell.SetCellValue(oneRecord.userAccount);
                    cell.CellStyle = style12;
                }

                Workbook.Write(ms);
                ms.Flush();
                ms.Seek(0, SeekOrigin.Begin);

                if (!Directory.Exists(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")))
                {
                    Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot"));
                }
                if (!Directory.Exists(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Excel")))
                {
                    Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Excel"));
                }
                var time = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
                time = time.Replace("/", "").Replace(" ", "_").Replace(":", "");

                var n = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Excel", "告警紀錄_" + time + ".xlsx");
                FileStream FS = new FileStream(n, FileMode.Create, FileAccess.Write);
                Workbook.Write(FS);
                FS.Close();

                apiResult.Data = Path.Combine("Excel", "告警紀錄_" + time + ".xlsx");
                apiResult.Code = "0000";

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

            return Ok(apiResult);
        }
    }
}