using Backend.Models;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using Dapper;
using System.Linq;
using Newtonsoft.Json.Linq;
using System.Xml;
using System.Net;
using System.IO;
using Newtonsoft.Json;

namespace BackendWorkerService.Services.Implement
{
    /// <summary>
    /// 電錶補償歸檔
    /// </summary>
    public class ProcEletricMeterService
    {
        string Connection1 = string.Empty;
        IDbConnection conn;

        public ProcEletricMeterService(string Connection_parame = null)
        {
            if (!string.IsNullOrEmpty(Connection_parame))
            {
                Connection1 = Connection_parame;
                conn = new SqlConnection(Connection_parame);
            }
            else
            {
                //Connection1 = ConfigurationManager.ConnectionStrings["mySql"].ConnectionString;
            }
        }

        public bool ArchiveData()
        {
            bool result = false;
            int repeatTimes = 0;
            string targetTable = string.Empty;

            EDFunction ed = new EDFunction();
            XmlDocument xmlDocument = new XmlDocument();
            var obixApiConfig = new ObixApiConfig();
            string encoded = string.Empty;

            try
            {
                //取得可錯誤次數
                using (IDbConnection conn = new SqlConnection(Connection1))
                {
                    var sqlArchive = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'archiveConfig'";

                    var variableArchive = conn.Query<KeyValue>(sqlArchive);
                    repeatTimes = Convert.ToInt32(variableArchive.Where(x => x.Name == "RepeatTimes").Select(x => x.Value).FirstOrDefault());

                    conn.Close();
                }

                #region 取得obix 設定
                using (IDbConnection conn = new SqlConnection(Connection1))
                {

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

                    var variableObix = conn.Query<KeyValue>(sqlObix).ToList();
                    obixApiConfig.ApiBase = variableObix.Where(x => x.Name == "ApiBase").Select(x => x.Value).FirstOrDefault();
                    obixApiConfig.UserName = ed.AESDecrypt(variableObix.Where(x => x.Name == "UserName").Select(x => x.Value).FirstOrDefault());
                    obixApiConfig.Password = ed.AESDecrypt(variableObix.Where(x => x.Name == "Password").Select(x => x.Value).FirstOrDefault());

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

                    conn.Close();
                }
                #endregion 取得obix 設定

                //取得錯誤的設備sql format
                var sql_error_format = @"SELECT * FROM {0} WHERE is_complete = 0 AND repeat_times < @RepeatTimes";

                //新增/修改sql format
                var sql_update_format = @"BEGIN TRANSACTION;

                                            UPDATE {0} SET 
                                                    count_rawdata = @count_rawdata,
                                                    min_rawdata = @min_rawdata,
                                                    max_rawdata = @max_rawdata,
                                                    avg_rawdata = @avg_rawdata,
                                                    sum_rawdata = @sum_rawdata,
                                                    is_complete = @is_complete,
                                                    repeat_times = @repeat_times,
                                                    fail_reason = @fail_reason,
                                                    updated_at = @updated_at
                                                 WHERE device_number = @device_number
                                                    AND point = @point
                                                    AND start_timestamp = @start_timestamp;

                                            IF @@ROWCOUNT = 0
                                            BEGIN
                                                INSERT INTO {0} (
                                                    device_number,
                                                    point,
                                                    start_timestamp,
                                                    end_timestamp,
                                                    count_rawdata,
                                                    min_rawdata,
                                                    max_rawdata,
                                                    avg_rawdata,
                                                    sum_rawdata,
                                                    is_complete,
                                                    repeat_times,
                                                    fail_reason)
                                                VALUES (
                                                    @device_number,
                                                    @point,
                                                    @start_timestamp,
                                                    @end_timestamp,
                                                    @count_rawdata,
                                                    @min_rawdata,
                                                    @max_rawdata,
                                                    @avg_rawdata,
                                                    @sum_rawdata,
                                                    @is_complete,
                                                    @repeat_times,
                                                    @fail_reason)
                                            END

                                        COMMIT TRANSACTION;";

                #region 時歸檔補償
                using (IDbConnection conn = new SqlConnection(Connection1))
                {
                    //取得所有須補償的設備資訊
                    targetTable = "archive_electric_meter_hour";
                    var sql_error_hour = string.Format(sql_error_format, targetTable);
                    var error_hours = conn.Query<ArchiveElectricMeter>(sql_error_hour, new { RepeatTimes = repeatTimes }).ToList();

                    List<Dictionary<string, object>> archiveHourRawDatas = new List<Dictionary<string, object>>();
                    if (error_hours.Count() > 0)
                    {
                        foreach (var error_hour in error_hours)
                        {
                            DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
                            deviceNumberPoint.DeviceNumber = error_hour.Device_number;
                            deviceNumberPoint.Point = error_hour.Point;
                            deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_hour.Device_number, error_hour.Point);

                            var startTimestamp = string.Format("{0}+08:00", error_hour.Start_timestamp.Replace(" ", "T"));
                            var endTimestamp = string.Format("{0}+08:00", error_hour.End_timestamp.Replace(" ", "T"));

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

                            HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
                            //HttpWebRequest archiveHourRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
                            archiveHourRequest.Method = "POST";
                            archiveHourRequest.Headers.Add("Authorization", "Basic " + encoded);
                            archiveHourRequest.PreAuthenticate = true;

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

                            HttpWebResponse archiveHourResponse = (HttpWebResponse)archiveHourRequest.GetResponse();
                            var archiveHourResponseContent = new StreamReader(archiveHourResponse.GetResponseStream()).ReadToEnd();

                            xmlDocument.LoadXml(archiveHourResponseContent);
                            string archiveHourJson = JsonConvert.SerializeXmlNode(xmlDocument);
                            JObject archiveHourJsonResult = (JObject)JsonConvert.DeserializeObject(archiveHourJson);

                            if (archiveHourJsonResult.ContainsKey("err")) //抓取錯誤
                            {
                                Dictionary<string, object> archiveDayRawData = new Dictionary<string, object>();
                                archiveDayRawData.Add("@device_number", error_hour.Device_number);
                                archiveDayRawData.Add("@point", error_hour.Point);
                                archiveDayRawData.Add("@start_timestamp", error_hour.Start_timestamp);
                                archiveDayRawData.Add("@end_timestamp", error_hour.End_timestamp);
                                archiveDayRawData.Add("@is_complete", 0);
                                archiveDayRawData.Add("@repeat_times", ++error_hour.Repeat_times);
                                archiveDayRawData.Add("@fail_reason", archiveHourJson);

                                archiveDayRawData.Add("@count_rawdata", 0);
                                archiveDayRawData.Add("@min_rawdata", 0);
                                archiveDayRawData.Add("@max_rawdata", 0);
                                archiveDayRawData.Add("@avg_rawdata", 0);
                                archiveDayRawData.Add("@sum_rawdata", 0);
                                archiveDayRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

                                archiveHourRawDatas.Add(archiveDayRawData);
                            }

                            if (archiveHourJsonResult.ContainsKey("obj")) //表示可以讀取到內容
                            {
                                var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveHourJsonResult);
                                if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
                                {
                                    archiveHourRawDatas.AddRange(ArrangeRawDatas);
                                }
                            }
                        }

                        if (archiveHourRawDatas.Count() > 0)
                        {
                            var sql_error_update = string.Format(sql_update_format, targetTable);
                            conn.Execute(sql_error_update, archiveHourRawDatas);
                        }
                    }
                    conn.Close();
                }
                #endregion 時歸檔補償

                #region 天歸檔補償
                using (IDbConnection conn = new SqlConnection(Connection1))
                {
                    //取得所有須補償的設備資訊
                    targetTable = "archive_electric_meter_day";
                    var sql_error_day = string.Format(sql_error_format, targetTable);
                    var error_days = conn.Query<ArchiveElectricMeter>(sql_error_day, new { RepeatTimes = repeatTimes }).ToList();

                    List<Dictionary<string, object>> archiveDayRawDatas = new List<Dictionary<string, object>>();
                    if (error_days.Count() > 0)
                    {
                        foreach (var error_day in error_days)
                        {
                            DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
                            deviceNumberPoint.DeviceNumber = error_day.Device_number;
                            deviceNumberPoint.Point = error_day.Point;
                            deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_day.Device_number, error_day.Point);

                            var startTimestamp = string.Format("{0}+08:00", error_day.Start_timestamp.Replace(" ", "T"));
                            var endTimestamp = string.Format("{0}+08:00", error_day.End_timestamp.Replace(" ", "T"));

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

                            HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
                            //HttpWebRequest archiveDayRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
                            archiveDayRequest.Method = "POST";
                            archiveDayRequest.Headers.Add("Authorization", "Basic " + encoded);
                            archiveDayRequest.PreAuthenticate = true;

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

                            HttpWebResponse archiveDayResponse = (HttpWebResponse)archiveDayRequest.GetResponse();
                            var archiveDayResponseContent = new StreamReader(archiveDayResponse.GetResponseStream()).ReadToEnd();

                            xmlDocument.LoadXml(archiveDayResponseContent);
                            string archiveDayJson = JsonConvert.SerializeXmlNode(xmlDocument);
                            JObject archiveDayJsonResult = (JObject)JsonConvert.DeserializeObject(archiveDayJson);

                            if (archiveDayJsonResult.ContainsKey("err")) //抓取錯誤
                            {
                                Dictionary<string, object> archiveDayRawData = new Dictionary<string, object>();
                                archiveDayRawData.Add("@device_number", error_day.Device_number);
                                archiveDayRawData.Add("@point", error_day.Point);
                                archiveDayRawData.Add("@start_timestamp", error_day.Start_timestamp);
                                archiveDayRawData.Add("@end_timestamp", error_day.End_timestamp);
                                archiveDayRawData.Add("@is_complete", 0);
                                archiveDayRawData.Add("@repeat_times", ++error_day.Repeat_times);
                                archiveDayRawData.Add("@fail_reason", archiveDayJson);

                                archiveDayRawData.Add("@count_rawdata", 0);
                                archiveDayRawData.Add("@min_rawdata", 0);
                                archiveDayRawData.Add("@max_rawdata", 0);
                                archiveDayRawData.Add("@avg_rawdata", 0);
                                archiveDayRawData.Add("@sum_rawdata", 0);
                                archiveDayRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

                                archiveDayRawDatas.Add(archiveDayRawData);
                            }

                            if (archiveDayJsonResult.ContainsKey("obj")) //表示可以讀取到內容
                            {
                                var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveDayJsonResult);
                                if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
                                {
                                    archiveDayRawDatas.AddRange(ArrangeRawDatas);
                                }
                            }
                        }

                        if (archiveDayRawDatas.Count() > 0)
                        {
                            var sql_error_update = string.Format(sql_update_format, targetTable);
                            conn.Execute(sql_error_update, archiveDayRawDatas);
                        }
                    }

                    conn.Close();
                }
                #endregion 天歸檔補償

                #region 週歸檔補償
                using (IDbConnection conn = new SqlConnection(Connection1))
                {
                    //取得所有須補償的設備資訊
                    targetTable = "archive_electric_meter_week";
                    var sql_error_week = string.Format(sql_error_format, targetTable);
                    var error_weeks = conn.Query<ArchiveElectricMeter>(sql_error_week, new { RepeatTimes = repeatTimes }).ToList();

                    List<Dictionary<string, object>> archiveWeekRawDatas = new List<Dictionary<string, object>>();
                    if (error_weeks.Count() > 0)
                    {
                        foreach (var error_week in error_weeks)
                        {
                            DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
                            deviceNumberPoint.DeviceNumber = error_week.Device_number;
                            deviceNumberPoint.Point = error_week.Point;
                            deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_week.Device_number, error_week.Point);

                            var startTimestamp = string.Format("{0}+08:00", error_week.Start_timestamp.Replace(" ", "T"));
                            var endTimestamp = string.Format("{0}+08:00", error_week.End_timestamp.Replace(" ", "T"));

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

                            HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
                            //HttpWebRequest archiveWeekRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
                            archiveWeekRequest.Method = "POST";
                            archiveWeekRequest.Headers.Add("Authorization", "Basic " + encoded);
                            archiveWeekRequest.PreAuthenticate = true;

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

                            HttpWebResponse archiveWeekResponse = (HttpWebResponse)archiveWeekRequest.GetResponse();
                            var archiveWeekResponseContent = new StreamReader(archiveWeekResponse.GetResponseStream()).ReadToEnd();

                            xmlDocument.LoadXml(archiveWeekResponseContent);
                            string archiveWeekJson = JsonConvert.SerializeXmlNode(xmlDocument);
                            JObject archiveWeekJsonResult = (JObject)JsonConvert.DeserializeObject(archiveWeekJson);

                            if (archiveWeekJsonResult.ContainsKey("err")) //抓取錯誤
                            {
                                Dictionary<string, object> archiveWeekRawData = new Dictionary<string, object>();
                                archiveWeekRawData.Add("@device_number", error_week.Device_number);
                                archiveWeekRawData.Add("@point", error_week.Point);
                                archiveWeekRawData.Add("@start_timestamp", error_week.Start_timestamp);
                                archiveWeekRawData.Add("@end_timestamp", error_week.End_timestamp);
                                archiveWeekRawData.Add("@is_complete", 0);
                                archiveWeekRawData.Add("@repeat_times", ++error_week.Repeat_times);
                                archiveWeekRawData.Add("@fail_reason", archiveWeekJson);

                                archiveWeekRawData.Add("@count_rawdata", 0);
                                archiveWeekRawData.Add("@min_rawdata", 0);
                                archiveWeekRawData.Add("@max_rawdata", 0);
                                archiveWeekRawData.Add("@avg_rawdata", 0);
                                archiveWeekRawData.Add("@sum_rawdata", 0);
                                archiveWeekRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

                                archiveWeekRawDatas.Add(archiveWeekRawData);
                            }

                            if (archiveWeekJsonResult.ContainsKey("obj")) //表示可以讀取到內容
                            {
                                var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveWeekJsonResult);
                                if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
                                {
                                    archiveWeekRawDatas.AddRange(ArrangeRawDatas);
                                }
                            }
                        }

                        if (archiveWeekRawDatas.Count() > 0)
                        {
                            var sql_error_update = string.Format(sql_update_format, targetTable);
                            conn.Execute(sql_error_update, archiveWeekRawDatas);
                        }
                    }

                    conn.Close();
                }
                #endregion 週歸檔補償

                #region 月歸檔補償
                using (IDbConnection conn = new SqlConnection(Connection1))
                {
                    //取得所有須補償的設備資訊
                    targetTable = "archive_electric_meter_month";
                    var sql_error_month = string.Format(sql_error_format, targetTable);
                    var error_months = conn.Query<ArchiveElectricMeter>(sql_error_month, new { RepeatTimes = repeatTimes }).ToList();

                    List<Dictionary<string, object>> archiveMonthRawDatas = new List<Dictionary<string, object>>();
                    if (error_months.Count() > 0)
                    {
                        foreach (var error_month in error_months)
                        {
                            DeviceNumberPoint deviceNumberPoint = new DeviceNumberPoint();
                            deviceNumberPoint.DeviceNumber = error_month.Device_number;
                            deviceNumberPoint.Point = error_month.Point;
                            deviceNumberPoint.FullDeviceNumberPoint = string.Format("{0}_{1}", error_month.Device_number, error_month.Point);

                            var startTimestamp = string.Format("{0}+08:00", error_month.Start_timestamp.Replace(" ", "T"));
                            var endTimestamp = string.Format("{0}+08:00", error_month.End_timestamp.Replace(" ", "T"));

                            var startDateTime = Convert.ToDateTime(error_month.Start_timestamp);
                            var dayInMonth = DateTime.DaysInMonth(startDateTime.Year, startDateTime.Month);

                            var historyQueryFilter = $@"<obj is='obix: HistoryFilter'>
                                                    <abstime name='start' val='{startTimestamp}' />
                                                    <abstime name='end' val='{endTimestamp}' />
                                                    <reltime name='interval' val = 'PT{dayInMonth}D' />
                                                </obj>";

                            HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/{deviceNumberPoint.FullDeviceNumberPoint}/~historyRollup/");
                            //HttpWebRequest archiveMonthRequest = (HttpWebRequest)WebRequest.Create($"{obixApiConfig.ApiBase}obix/histories/FIC_Center/H_E1_B1F_MVCB_MVCBH_V1/~historyRollup/");
                            archiveMonthRequest.Method = "POST";
                            archiveMonthRequest.Headers.Add("Authorization", "Basic " + encoded);
                            archiveMonthRequest.PreAuthenticate = true;

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

                            HttpWebResponse archiveMonthResponse = (HttpWebResponse)archiveMonthRequest.GetResponse();
                            var archiveMonthResponseContent = new StreamReader(archiveMonthResponse.GetResponseStream()).ReadToEnd();

                            xmlDocument.LoadXml(archiveMonthResponseContent);
                            string archiveMonthJson = JsonConvert.SerializeXmlNode(xmlDocument);
                            JObject archiveMonthJsonResult = (JObject)JsonConvert.DeserializeObject(archiveMonthJson);

                            if (archiveMonthJsonResult.ContainsKey("err")) //抓取錯誤
                            {
                                Dictionary<string, object> archiveMonthRawData = new Dictionary<string, object>();
                                archiveMonthRawData.Add("@device_number", error_month.Device_number);
                                archiveMonthRawData.Add("@point", error_month.Point);
                                archiveMonthRawData.Add("@start_timestamp", error_month.Start_timestamp);
                                archiveMonthRawData.Add("@end_timestamp", error_month.End_timestamp);
                                archiveMonthRawData.Add("@is_complete", 0);
                                archiveMonthRawData.Add("@repeat_times", ++error_month.Repeat_times);
                                archiveMonthRawData.Add("@fail_reason", archiveMonthJson);

                                archiveMonthRawData.Add("@count_rawdata", 0);
                                archiveMonthRawData.Add("@min_rawdata", 0);
                                archiveMonthRawData.Add("@max_rawdata", 0);
                                archiveMonthRawData.Add("@avg_rawdata", 0);
                                archiveMonthRawData.Add("@sum_rawdata", 0);
                                archiveMonthRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

                                archiveMonthRawDatas.Add(archiveMonthRawData);
                            }

                            if (archiveMonthJsonResult.ContainsKey("obj")) //表示可以讀取到內容
                            {
                                var ArrangeRawDatas = ArrangeRawData(deviceNumberPoint, archiveMonthJsonResult);
                                if (ArrangeRawDatas != null && ArrangeRawDatas.Count() > 0)
                                {
                                    archiveMonthRawDatas.AddRange(ArrangeRawDatas);
                                }
                            }
                        }

                        if (archiveMonthRawDatas.Count() > 0)
                        {
                            var sql_error_update = string.Format(sql_update_format, targetTable);
                            conn.Execute(sql_error_update, archiveMonthRawDatas);
                        }
                    }

                    conn.Close();
                }
                #endregion 月歸檔補償

                result = true;
            }
            catch (Exception exception)
            {
                throw exception;
            }

            return result;
        }

        private List<Dictionary<string, object>> ArrangeRawData(DeviceNumberPoint deviceNumberPoint, JObject jsonResult)
        {
            List<Dictionary<string, object>> arrangeRawDatas = new List<Dictionary<string, object>>();
            var histories = jsonResult["obj"]["list"];
            var rawdateCount = Convert.ToInt32(jsonResult["obj"]["int"]["@val"].ToString());

            if (rawdateCount == 0)
            {
                return null;
            }

            if (histories != null && histories.HasValues)
            {
                if (rawdateCount > 1)
                {   //多筆資料
                    foreach (var history in histories)
                    {
                        Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
                        arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
                        arrangeRawData.Add("@point", deviceNumberPoint.Point);

                        //時間
                        if (history["abstime"] != null && history["abstime"].HasValues)
                        {
                            foreach (var abstime in history["abstime"])
                            {
                                var name = abstime["@name"].ToString();
                                switch (name)
                                {
                                    case "start":
                                        var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
                                        arrangeRawData.Add("@start_timestamp", startTimstamp);
                                        break;
                                    case "end":
                                        var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
                                        arrangeRawData.Add("@end_timestamp", endTimstamp);
                                        break;
                                }
                            }
                        }

                        //區間內資料筆數
                        if (history["int"] != null && history["int"].HasValues)
                        {
                            var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
                            arrangeRawData.Add("@count_rawdata", count);
                        }

                        //整合數值(最大、最小、平均、總和)
                        if (history["real"] != null && history["real"].HasValues)
                        {
                            foreach (var real in history["real"])
                            {
                                var name = real["@name"].ToString();
                                switch (name)
                                {
                                    case "min":
                                        var min = Convert.ToDecimal(real["@val"].ToString());
                                        arrangeRawData.Add("@min_rawdata", min);
                                        break;
                                    case "max":
                                        var max = Convert.ToDecimal(real["@val"].ToString());
                                        arrangeRawData.Add("@max_rawdata", max);
                                        break;
                                    case "avg":
                                        var avg = Convert.ToDecimal(real["@val"].ToString());
                                        arrangeRawData.Add("@avg_rawdata", avg);
                                        break;
                                    case "sum":
                                        var sum = Convert.ToDecimal(real["@val"].ToString());
                                        arrangeRawData.Add("@sum_rawdata", sum);
                                        break;
                                }
                            }
                        }
                        arrangeRawData.Add("@is_complete", 1);
                        arrangeRawData.Add("@repeat_times", 0);
                        arrangeRawData.Add("@fail_reason", null);
                        arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

                        arrangeRawDatas.Add(arrangeRawData);
                    }
                }
                else
                {   //單筆資料
                    Dictionary<string, object> arrangeRawData = new Dictionary<string, object>();
                    arrangeRawData.Add("@device_number", deviceNumberPoint.DeviceNumber);
                    arrangeRawData.Add("@point", deviceNumberPoint.Point);

                    //時間
                    if (histories["obj"]["abstime"] != null && histories["obj"]["abstime"].HasValues)
                    {
                        foreach (var abstime in histories["obj"]["abstime"])
                        {
                            var name = abstime["@name"].ToString();
                            switch (name)
                            {
                                case "start":
                                    var startTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
                                    arrangeRawData.Add("@start_timestamp", startTimstamp);
                                    break;
                                case "end":
                                    var endTimstamp = Convert.ToDateTime(abstime["@val"].ToString()).ToString("yyyy-MM-dd HH:mm:ss");
                                    arrangeRawData.Add("@end_timestamp", endTimstamp);
                                    break;
                            }
                        }
                    }

                    //區間內資料筆數
                    if (histories["obj"]["int"] != null && histories["obj"]["int"].HasValues)
                    {
                        var count = Convert.ToInt32(histories["obj"]["int"]["@val"].ToString());
                        arrangeRawData.Add("@count_rawdata", count);
                    }

                    //整合數值(最大、最小、平均、總和)
                    if (histories["obj"]["real"] != null && histories["obj"]["real"].HasValues)
                    {
                        foreach (var real in histories["obj"]["real"])
                        {
                            var name = real["@name"].ToString();
                            switch (name)
                            {
                                case "min":
                                    var min = Convert.ToDecimal(real["@val"].ToString());
                                    arrangeRawData.Add("@min_rawdata", min);
                                    break;
                                case "max":
                                    var max = Convert.ToDecimal(real["@val"].ToString());
                                    arrangeRawData.Add("@max_rawdata", max);
                                    break;
                                case "avg":
                                    var avg = Convert.ToDecimal(real["@val"].ToString());
                                    arrangeRawData.Add("@avg_rawdata", avg);
                                    break;
                                case "sum":
                                    var sum = Convert.ToDecimal(real["@val"].ToString());
                                    arrangeRawData.Add("@sum_rawdata", sum);
                                    break;
                            }
                        }
                    }

                    arrangeRawData.Add("@is_complete", 1);
                    arrangeRawData.Add("@repeat_times", 0);
                    arrangeRawData.Add("@fail_reason", null);
                    arrangeRawData.Add("@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

                    arrangeRawDatas.Add(arrangeRawData);
                }
            }

            return arrangeRawDatas;
        }
    }
}