using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using SolarPower.Models;
using SolarPower.Models.PowerStation;
using SolarPower.Models.Role;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Transactions;
using System.Text.RegularExpressions;

namespace SolarPower.Controllers
{
    public class OperationController : MyBaseController<OperationController>
    {
        private readonly IOperationRepository operationRepository;
        private readonly IPowerStationRepository powerStationRepository;
        private readonly IUserRepository userRepository;
        private readonly INoticeScheduleRepository noticeScheduleRepository;
        private string operationRecordFilePath = "/upload/operation_recode/";
        private string operationRecordSaveAsPath = "";

        public OperationController(
            IOperationRepository operationRepository, IWebHostEnvironment environment,IPowerStationRepository powerStationRepository,IUserRepository userRepository,INoticeScheduleRepository noticeScheduleRepository) : base()
        {
            this.noticeScheduleRepository = noticeScheduleRepository;
            this.userRepository = userRepository;
            this.powerStationRepository = powerStationRepository;
            this.operationRepository = operationRepository;
            operationRecordSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "operation_recode");
        }

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

        public IActionResult Record()
        {
            return View("~/Views/Operation/OperationRecord.cshtml");
        }

        public ApiResult<List<MyCity>> GetMyCities()
        {
            ApiResult<List<MyCity>> apiResult = new ApiResult<List<MyCity>>();
            try
            {
                apiResult.Code = "0000";
                apiResult.Data = myPowerStationService.GetMyCities(myUser);
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = exception.ToString();
            }

            return apiResult;
        }

        public ApiResult<List<PowerStation>> GetPowerStationByFilter(List<int> cityIds)
        {
            ApiResult<List<PowerStation>> apiResult = new ApiResult<List<PowerStation>>();
            try
            {

                var myPowerStations = myPowerStationService.GetMyPowerStations(myUser,1, cityIds);

                apiResult.Code = "0000";
                apiResult.Data = myPowerStations;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = exception.ToString();
            }

            return apiResult;
        }

        /// <summary>
        /// 取得電站Option
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<PowerStationIdList>>> GetPowerStationSelectOption()
        {
            ApiResult<List<PowerStationIdList>> apiResult = new ApiResult<List<PowerStationIdList>>();
            try
            {
                var PowerStationIdLists = new List<PowerStationIdList>();
                PowerStationIdLists = await operationRepository.GetPowerStationIdList(myUser.Id);
                apiResult.Code = "0000";
                apiResult.Data = PowerStationIdLists;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            apiResult.Msg = errorCode.GetString(apiResult.Code);
            return apiResult;
        }

        /// <summary>
        /// 儲存計畫
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> SaveOperationPlan(OperationCreatePlanModal post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();
            try
            {
                if (Convert.ToDateTime(post.StartTime) < Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")))
                {
                    apiResult.Msg = "開始時間不能選擇過去";
                    apiResult.Code = "0099";
                    return apiResult;
                }


                if (post.Id == 0)
                {
                    var now = DateTime.Now.ToString("yyyy-MM-dd");
                    var finalid = await operationRepository.GetCurrentSerialNumber("operation_plan_create", $"PowerStationId = {post.PowerStationId} AND CreatedAt LIKE '%{now}%'");
                    var newSerialNumber = GetLastSerialNumber(finalid);
                    var OperationPlan = new OperationCreatePlan()
                    {
                        EmailType = post.EmailType,
                        ScheduleNum = post.ScheduleNum,
                        Description = post.Description,
                        WorkDay = post.WorkDay,
                        ScheduleType = post.ScheduleType,
                        SerialNumber = newSerialNumber,
                        StartTime = post.StartTime,
                        PowerStationId = post.PowerStationId,
                        Type = post.Type,
                        PlanId = DateTime.Now.ToString("yyyyMMdd") + newSerialNumber,
                        CreatedBy = myUser.Id
                    };
                    List<string> properties = new List<string>()
                    {
                        "EmailType",
                        "ScheduleNum",
                        "Description",
                        "WorkDay",
                        "ScheduleType",
                        "SerialNumber",
                        "StartTime",
                        "PowerStationId",
                        "Type",
                        "PlanId",
                        "CreatedBy"
                    };



                    if (post.StartTime == DateTime.Now.ToString("yyyy-MM-dd"))
                    {
                        string endtime = "";
                        switch (post.ScheduleType)
                        {
                            case 0:
                                endtime = (Convert.ToDateTime(post.StartTime).AddDays(post.ScheduleNum)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 1:
                                endtime = (Convert.ToDateTime(post.StartTime).AddDays(post.ScheduleNum * 7)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 2:
                                endtime = (Convert.ToDateTime(post.StartTime).AddMonths(post.ScheduleNum)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 3:
                                endtime = (Convert.ToDateTime(post.StartTime).AddMonths(post.ScheduleNum * 3)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 4:
                                endtime = (Convert.ToDateTime(post.StartTime).AddYears(post.ScheduleNum * 3)).ToString("yyyy-MM-dd 00:00:00"); break;
                        }
                        var record = new PlanToRecord()
                        {
                            WorkType = post.Type,
                            PowerStationId = post.PowerStationId,
                            StartTime = post.StartTime,
                            CreatedBy = myUser.Id,
                            EndTime = endtime
                        };
                        List<string> properties2 = new List<string>()
                        {
                            "WorkType",
                            "PowerStationId",
                            "StartTime",
                            "CreatedBy",
                            "EndTime"
                        };
                        OperationPlan.LastCreateTime = DateTime.Now.ToString("yyyy-MM-dd 00:00:00");
                        properties.Add("LastCreateTime");

                        await operationRepository.AddToRecord(record, properties2);
                    }
                    await operationRepository.AddOperationPlan(OperationPlan, properties);
                    apiResult.Code = "0000";
                    apiResult.Msg = "新增成功";
                }
                else
                {
                    var OperationPlan = new OperationCreatePlan()
                    {
                        Id = post.Id,
                        EmailType = post.EmailType,
                        ScheduleNum = post.ScheduleNum,
                        Description = post.Description,
                        WorkDay = post.WorkDay,
                        ScheduleType = post.ScheduleType,
                        StartTime = post.StartTime,
                        PowerStationId = post.PowerStationId,
                        Type = post.Type,
                        UpdatedBy = myUser.Id
                    };
                    List<string> properties = new List<string>()
                    {
                        "Id",
                        "EmailType",
                        "ScheduleNum",
                        "Description",
                        "WorkDay",
                        "ScheduleType",
                        "StartTime",
                        "PowerStationId",
                        "Type",
                        "UpdatedBy"
                    };
                    if (post.StartTime == DateTime.Now.ToString("yyyy-MM-dd"))
                    {
                        string endtime = "";
                        switch (post.ScheduleType)
                        {
                            case 0:
                                endtime = (Convert.ToDateTime(post.StartTime).AddDays(post.ScheduleNum)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 1:
                                endtime = (Convert.ToDateTime(post.StartTime).AddDays(post.ScheduleNum * 7)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 2:
                                endtime = (Convert.ToDateTime(post.StartTime).AddMonths(post.ScheduleNum)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 3:
                                endtime = (Convert.ToDateTime(post.StartTime).AddMonths(post.ScheduleNum * 3)).ToString("yyyy-MM-dd 00:00:00"); break;
                            case 4:
                                endtime = (Convert.ToDateTime(post.StartTime).AddYears(post.ScheduleNum * 3)).ToString("yyyy-MM-dd 00:00:00"); break;
                        }
                        var record = new PlanToRecord()
                        {
                            WorkType = post.Type,
                            PowerStationId = post.PowerStationId,
                            StartTime = post.StartTime,
                            CreatedBy = myUser.Id,
                            EndTime = endtime
                        };
                        List<string> properties2 = new List<string>()
                        {
                            "WorkType",
                            "PowerStationId",
                            "StartTime",
                            "CreatedBy",
                            "EndTime"
                        };
                        OperationPlan.LastCreateTime = DateTime.Now.ToString("yyyy-MM-dd 00:00:00");
                        properties.Add("LastCreateTime");

                        await operationRepository.AddToRecord(record, properties2);
                    }

                    await operationRepository.UpdateOperationPlan(OperationPlan, properties);
                    apiResult.Code = "0000";
                    apiResult.Msg = "編輯成功";
                }



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

            apiResult.Msg = errorCode.GetString(apiResult.Code);
            return apiResult;
        }

        /// <summary>
        /// 定時計畫datatable
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ActionResult> OperationPlanTable(List<int> id, int type)
        {
            List<OperationPlanTable> OperationPlanTable = new List<OperationPlanTable>();
            ApiResult<List<OperationPlanTable>> apiResult = new ApiResult<List<OperationPlanTable>>();
            try
            {
                apiResult.Code = "0000";
                OperationPlanTable = await operationRepository.OperationPlanTable(id, type);
                foreach (OperationPlanTable a in OperationPlanTable)
                {
                    if (a.Type == 0)
                    {
                        a.TypeName = "清洗";
                    }
                    else
                    {
                        a.TypeName = "巡檢";
                    }

                    if (a.ScheduleType == 0)
                    {
                        a.Schedule = "每" + a.ScheduleNum.ToString() + "天";
                    }
                    else if (a.ScheduleType == 1)
                    {
                        a.Schedule = "每" + a.ScheduleNum.ToString() + "周";
                    }
                    else if (a.ScheduleType == 2)
                    {
                        a.Schedule = "每" + a.ScheduleNum.ToString() + "月";
                    }
                    else if (a.ScheduleType == 3)
                    {
                        a.Schedule = "每" + a.ScheduleNum.ToString() + "季";
                    }
                    else if (a.ScheduleType == 4)
                    {
                        a.Schedule = "每" + a.ScheduleNum.ToString() + "年";
                    }

                    a.StartTimeString = a.StartTime;
                    var crst = a.CreatedAt.Split(" ");
                    a.CreateTimeString = crst[0];

                    if (a.EmailType == 0)
                    {
                        a.EmailTypeName = "當天";
                    }
                    else if (a.EmailType == 1)
                    {
                        a.EmailTypeName = "前一天";
                    }
                    else if (a.EmailType == 2)
                    {
                        a.EmailTypeName = "前兩天";
                    }
                    else if (a.EmailType == 3)
                    {
                        a.EmailTypeName = "前三天";
                    }

                    a.Function = @"
                                <button type='button' class='btn btn-primary btn-pills waves-effect waves-themed edit-btn'>修改</button>
                                <button type='button' class='btn btn-danger btn-pills waves-effect waves-themed del-btn'>刪除</button>";
                }

                apiResult.Data = OperationPlanTable;

            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = exception.ToString();
            }
            var result = Json(new
            {
                data = apiResult
            });

            return result;
        }
        /// <summary>
        /// 刪除定時計畫
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> DeleteOneOperationPlan(int Id)
        {
            ApiResult<string> apiResult = new ApiResult<string>();
            OperationCreatePlan operation = new OperationCreatePlan();
            try
            {
                operation = await operationRepository.GetOneOperation(Id);

                if (operation == null)
                {
                    apiResult.Code = "9998";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                await operationRepository.DeleteOneByIdWithCustomTable(Id, "operation_plan_create");

                apiResult.Code = "0000";
                apiResult.Msg = "刪除成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + Id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        public async Task<ApiResult<OperationCreatePlan>> GetOneOperationPlan(int Id)
        {
            ApiResult<OperationCreatePlan> apiResult = new ApiResult<OperationCreatePlan>();
            OperationCreatePlan operationCreatePlan = new OperationCreatePlan();
            try
            {
                apiResult.Code = "0000";
                operationCreatePlan = await operationRepository.GetOneOperation(Id);
                apiResult.Data = operationCreatePlan;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = exception.ToString();
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + Id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            return apiResult;
        }

        /// <summary>
        /// 運維作業記錄列表
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult> OperationRecordListAsync(PostOperationRecordFilter post)
        {
            ApiResult<List<OperationRecordDataTable>> apiResult = new ApiResult<List<OperationRecordDataTable>>();

            int totalRecords = 0; //總資料筆數
            int recFilter = 0; //過濾後資料筆數

            List<OperationRecordDataTable> records = null;

            try
            {

                records = await operationRepository.GetAllRecordByFilterAsync(post);

                foreach (var record in records)
                {
                    if(post.Status == 2)
                    {
                        record.Function = "<button class='btn btn-primary redu-btn'>還原</button>";
                        if (string.IsNullOrEmpty(record.FormId))
                        {
                            record.FormId = "";
                        }
                        else
                        {
                            record.FormId = record.FormId;
                        }
                    }
                    else
                    {
                        
                        record.Function = "<button class='btn btn-danger del-btn'>刪除</button>";
                        if (string.IsNullOrEmpty(record.FormId))
                        {
                            record.FormId = @$"<a href='javascript:;' class='btn btn-success waves-effect waves-themed mb-3 mr-2 edit-btn'>填寫表單</a>";
                        }
                        else
                        {
                            record.FormId = @$"<a href='javascript:;' class='waves-effect waves-themed mb-3 mr-2 edit-btn'>{record.FormId}</a>";
                        }
                    }
                    if (record.RecordFiles != null && record.RecordFiles.Count > 0)
                    {
                        foreach (var file in record.RecordFiles)
                        {
                            file.FileName = Path.Combine(operationRecordFilePath, record.Id.ToString()) + "/" + file.FileName;
                        }
                    }

                }

                totalRecords = records.Count();
                recFilter = records.Count();

                apiResult.Code = "0000";
                apiResult.Data = records;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            apiResult.Msg = errorCode.GetString(apiResult.Code);
            var result = Json(new
            {
                recordsTotal = totalRecords,
                recordsFiltered = recFilter,
                data = apiResult
            });

            return result;
        }

        /// <summary>
        /// 取得單一運維作業記錄列表
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<OperationRecord>> GetOneOperationRecord(int id)
        {
            ApiResult<OperationRecord> apiResult = new ApiResult<OperationRecord>();

            OperationRecord operationRecord;

            try
            {

                //if (!IsPlatformLayer(myUser.Role.Layer))
                //{   //如果只是身分公司管理員 或 公司使用者，就只能看自己公司的資料
                //    post.SelectedCompanyId = myUser.CompanyId;
                //}

                operationRecord = await operationRepository.GetOneOperationRecordAsync(id);

                if (operationRecord == null)
                {
                    apiResult.Code = "9989";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                foreach (var recordFile in operationRecord.RecordFiles)
                {
                    recordFile.FileName = Path.Combine(operationRecordFilePath, operationRecord.Id.ToString()) + "/" + recordFile.FileName;
                }

                apiResult.Code = "0000";
                apiResult.Data = operationRecord;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 新增 維修單 / 修改運維作業記錄
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> SaveOperationRecord([FromForm] PostOperationRecord post)
        {
            ApiResult<int> apiResult = new ApiResult<int>();

            OperationRecord operationRecord = null;
            var id = 0;

            try
            {
                operationRecord = await operationRepository.GetOneOperationRecordAsync(post.Id);

                //取得運維作業記錄最後流水號
                var currentSerialNumber = await operationRepository.GetCurrentSerialNumber("operation_record");

                if (operationRecord == null)
                {
                    if (post.Id != 0)
                    {
                        apiResult.Code = "9989";
                        apiResult.Msg = errorCode.GetString(apiResult.Code);
                        return apiResult;
                    }

                    #region 新增運維作業記錄 - 維修單

                    var tempSerialNumber = GetLastSerialNumber(currentSerialNumber);

                    var finishTime = string.Empty;
                    if (post.Status == (int)OperationRecordStatusEnum.Complete)
                    {
                        finishTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    }

                    operationRecord = new OperationRecord()
                    {
                        FormId = "op" + DateTime.Now.ToString("yyyyMMdd") + tempSerialNumber,
                        SerialNumber = tempSerialNumber,
                        PowerStationId = post.PowerStationId,
                        WorkType = (int)OperationRecordWorkTypeEnum.Fix,
                        ErrorCode = post.ErrorCode,
                        FixDo = post.FixDo,
                        FixFirm = post.FixFirm,
                        Status = post.Status,
                        //WorkPersonId = post.WorkPersonId,
                        FinishTime = finishTime,
                        WorkTime = post.WorkTime,
                        Notice = post.Notice,
                        Description = post.Description,
                        CreatedBy = myUser.Id
                    };

                    List<string> properties = new List<string>()
                        {
                            "FormId",
                            "SerialNumber",
                            "PowerStationId",
                            "WorkType",
                            "ErrorCode",
                            "FixDo",
                            "FixFirm",
                            "Status",
                            //"WorkPersonId",
                            "FinishTime",
                            "WorkTime",
                            "Notice",
                            "Description",
                            "CreatedBy"
                        };

                    id = await operationRepository.AddOneOperationRecordAsync(operationRecord, properties);

                    //加入執行人員
                    if (post.WorkPersonIds != null)
                    {
                        List<OperationRecordPersonnel> insertOperationRecordPersonnels = new List<OperationRecordPersonnel>();

                        foreach (var op in post.WorkPersonIds)
                        {
                            OperationRecordPersonnel operationRecordPersonnel = new OperationRecordPersonnel();
                            operationRecordPersonnel.OperationRecordId = id;
                            operationRecordPersonnel.UserId = op;
                            operationRecordPersonnel.CreatedBy = myUser.Id;
                            insertOperationRecordPersonnels.Add(operationRecordPersonnel);
                        }

                        List<string> operationRecordPersonnelProperties = new List<string>()
                            {
                                "OperationRecordId",
                                "UserId",
                                "CreatedBy"
                            };

                        await operationRepository.AddOperationRecordPersonnelAsync(insertOperationRecordPersonnels, operationRecordPersonnelProperties);


                    }

                    if(post.Emailcheck == 1)
                    {
                        var powerstations = await powerStationRepository.GetOneAsync(post.PowerStationId);
                        if (post.WorkPersonIds != null)
                        {
                           
                            List<NoticeSchedule> noticeSchedules = new List<NoticeSchedule>();
                            foreach (var person in post.WorkPersonIds)
                            {
                                var fixtype = post.WorkType switch
                                {
                                    0 => "清洗",
                                    1 => "巡檢",
                                    2 => "維修",
                                    _ => ""
                                };
                                var user = await userRepository.GetOneAsync(person);
                                if (IsValidEmail(user.Email))
                                {
                                    NoticeSchedule schedule = new NoticeSchedule()
                                    {
                                        EmailType = 3,
                                        Type = 1,
                                        UserId = person,
                                        RecipientName = user.Name,
                                        RecipientEmail = user.Email,
                                        Subject = powerstations.Name + "-" + fixtype + "-" + post.WorkTime,
                                        Content = "維修項目" + post.FixDo + "</br>注意事項 :" + post.Notice,
                                    };
                                    noticeSchedules.Add(schedule);
                                }
                            }
                            properties = new List<string>()
                            {
                                "UserId",
                                "EmailType",
                                "RecipientEmail",
                                "Subject",
                                "Content",
                                "RecipientName",
                                "Type",
                                "ExceptionId"
                            };
                            if (noticeSchedules.Count > 0)
                            {
                                await noticeScheduleRepository.AddAnyThing<List<NoticeSchedule>>(noticeSchedules, properties, "notice_schedule");
                            }
                        }

                        if (post.FixFirm != 0)
                        {
                            //var powerstations = await powerStationRepository.GetOneAsync(post.PowerStationId);
                            var fixtype = operationRecord.WorkType switch
                            {
                                0 => "清洗",
                                1 => "巡檢",
                                2 => "維修",
                                _ => ""
                            };
                            //var powerstation = await powerStationRepository.GetOneAsync(post.PowerStationId);
                            var firm = await operationRepository.GetOneWithCustomDBNameAndTableAsync<OperationInfo>(post.FixFirm, powerstations.SiteDB, "operation_firm");
                            if (IsValidEmail(firm.Email))
                            {
                                NoticeSchedule schedule = new NoticeSchedule()
                                {
                                    EmailType = 3,
                                    Type = 1,
                                    RecipientName = firm.Name,
                                    RecipientEmail = firm.Email,
                                    Subject = powerstations.Name + "-" + fixtype + "-" + post.WorkTime,
                                    Content = "維修項目" + post.FixDo + "</br>注意事項 :" + post.Notice,
                                };

                                properties = new List<string>()
                                {
                                    "UserId",
                                    "EmailType",
                                    "RecipientEmail",
                                    "Subject",
                                    "Content",
                                    "RecipientName",
                                    "Type",
                                    "ExceptionId"
                                };
                                await noticeScheduleRepository.AddAnyThing<NoticeSchedule>(schedule, properties, "notice_schedule");
                            }
                        }
                    }
                    //using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Suppress))
                    //{
                        
                    //    scope.Complete();
                    //}

                    apiResult.Code = "0000";
                    apiResult.Msg = "儲存成功";
                    apiResult.Data = id;
                    #endregion
                }
                else
                {
                    //var transactionOption = new TransactionOptions();
                    //transactionOption.IsolationLevel = IsolationLevel.ReadUncommitted;
                    //using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOption, TransactionScopeAsyncFlowOption.Enabled))
                    //{
                        
                    //    scope.Complete();
                    //}
                    #region 修改運維作業記錄
                    var finishTime = string.Empty;
                    if (post.Status == (int)OperationRecordStatusEnum.Complete)
                    {
                        finishTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    }

                    if (operationRecord.WorkType != (int)OperationRecordWorkTypeEnum.Fix)
                    {   //針對清洗、巡檢
                        var now = DateTime.Now;

                        var startTime = DateTime.Parse(post.StartTime + " 00:00:00");
                        var endTime = DateTime.Parse(post.EndTime + " 23:59:59");

                        if (now > endTime)
                        {
                            if (post.Status == (int)OperationRecordStatusEnum.NoneComplete)
                            {   //超過時間修改成 未完成-過期
                                post.Status = (int)OperationRecordStatusEnum.NoneCompleteExpired;
                            }
                            else if (post.Status == (int)OperationRecordStatusEnum.Complete)
                            {   //超過時間修改成 完成-過期
                                post.Status = (int)OperationRecordStatusEnum.CompleteExpired;
                            }
                        }
                    }

                    UpdateOperationRecord update = new UpdateOperationRecord()
                    {
                        Id = post.Id,
                        ErrorCode = post.ErrorCode,
                        FixDo = post.FixDo,
                        FixFirm = post.FixFirm,
                        Status = post.Status,
                        FinishTime = !string.IsNullOrEmpty(finishTime) ? finishTime : null,
                        //WorkPersonId = post.WorkPersonId,
                        WorkTime = post.WorkTime,
                        Notice = post.Notice,
                        Description = post.Description,
                        UpdatedBy = myUser.Id
                    };

                    List<string> properties = new List<string>()
                        {
                            "Id",
                            "ErrorCode",
                            "FixDo",
                            "FixFirm",
                            "Status",
                            "FinishTime",
                            "WorkTime",
                            "Notice",
                            "Description",
                            //"WorkPersonId",
                            "UpdatedBy",
                        };

                    if (string.IsNullOrEmpty(operationRecord.FormId))
                    {
                        var tempSerialNumber = GetLastSerialNumber(currentSerialNumber);

                        update.FormId = "op" + DateTime.Now.ToString("yyyyMMdd") + tempSerialNumber;
                        update.SerialNumber = tempSerialNumber;

                        properties.Add("FormId");
                        properties.Add("SerialNumber");
                    }

                    await operationRepository.UpdateOperationRecordAsync(update, properties);

                    List<int> origOperationRecordPersonnels = null; //原先的運維人員

                    origOperationRecordPersonnels = await operationRepository.GetOperationRecordPersonnelIdsByOperationRecordId(operationRecord.Id);

                    //判斷新進來的執行人員是否要歸類到新增 or 刪除
                    #region 刪除執行人員編號
                    if (post.WorkPersonIds != null && post.WorkPersonIds.Count() > 0)
                    {
                        //找出要刪除的
                        List<int> deleteOperationRecordPersonnelIds = origOperationRecordPersonnels.Where(x => !post.WorkPersonIds.Contains(x)).ToList();

                        List<OperationRecordPersonnel> deleteOperationRecordPersonnels = new List<OperationRecordPersonnel>();
                        foreach (var opId in deleteOperationRecordPersonnelIds)
                        {
                            OperationRecordPersonnel operationRecordPersonnel = new OperationRecordPersonnel();
                            operationRecordPersonnel.OperationRecordId = operationRecord.Id;
                            operationRecordPersonnel.UserId = opId;

                            deleteOperationRecordPersonnels.Add(operationRecordPersonnel);
                        }

                        //刪除執行人員
                        await operationRepository.DeleteOperationRecordPersonnel(deleteOperationRecordPersonnels);
                    }
                    #endregion

                    #region 新增人員
                    //找出要新增的
                    if (post.WorkPersonIds != null && post.WorkPersonIds.Count() > 0)
                    {
                        List<int> insertOperationRecordPersonnelIds = post.WorkPersonIds.Where(x => !origOperationRecordPersonnels.Contains(x)).ToList();

                        List<OperationRecordPersonnel> insertOperationRecordPersonnels = new List<OperationRecordPersonnel>();

                        foreach (var op in insertOperationRecordPersonnelIds)
                        {
                            OperationRecordPersonnel operationPersonnel = new OperationRecordPersonnel();
                            operationPersonnel.OperationRecordId = operationRecord.Id;
                            operationPersonnel.Deleted = 0;
                            operationPersonnel.UserId = op;
                            operationPersonnel.CreatedBy = myUser.Id;

                            insertOperationRecordPersonnels.Add(operationPersonnel);
                        }
                        List<string> operationRecordPersonnelProperties = new List<string>()
                            {
                                "OperationRecordId",
                                "Deleted",
                                "UserId",
                                "CreatedBy",
                            };
                        await operationRepository.AddOperationRecordPersonnelAsync(insertOperationRecordPersonnels, operationRecordPersonnelProperties);
                    }

                    #endregion
                    if (post.Emailcheck == 1)
                    {
                        var powerstations = await powerStationRepository.GetOneAsync(post.PowerStationId);
                        if (post.WorkPersonIds != null)
                        { 
                            List<NoticeSchedule> noticeSchedules = new List<NoticeSchedule>();
                            foreach (var person in post.WorkPersonIds)
                            {
                                var fixtype = operationRecord.WorkType switch
                                {
                                    0 => "清洗",
                                    1 => "巡檢",
                                    2 => "維修",
                                    _ => ""
                                };
                                var user = await userRepository.GetOneAsync(person);
                                if (IsValidEmail(user.Email))
                                {
                                    NoticeSchedule schedule = new NoticeSchedule()
                                    {
                                        EmailType = 3,
                                        Type = 1,
                                        UserId = person,
                                        RecipientName = user.Name,
                                        RecipientEmail = user.Email,
                                        Subject = powerstations.Name + "-" + fixtype + "-" + post.WorkTime,
                                        Content = "維修項目:" + post.FixDo + "</br>注意事項 :" + post.Notice,
                                    };
                                    noticeSchedules.Add(schedule);
                                }
                            }
                            properties = new List<string>()
                            {
                                "UserId",
                                "EmailType",
                                "RecipientEmail",
                                "Subject",
                                "Content",
                                "RecipientName",
                                "Type",
                                "ExceptionId"
                            };
                            if (noticeSchedules.Count > 0)
                            {
                                await noticeScheduleRepository.AddAnyThing<List<NoticeSchedule>>(noticeSchedules, properties, "notice_schedule");
                            }
                        }
                        if (post.FixFirm != 0)
                        {
                            //var powerstations = await powerStationRepository.GetOneAsync(post.PowerStationId);
                            var fixtype = post.WorkType switch
                            {
                                0 => "清洗",
                                1 => "巡檢",
                                2 => "維修",
                                _ => ""
                            };
                           // var powerstation = await powerStationRepository.GetOneAsync(post.PowerStationId);
                            var firm = await operationRepository.GetOneWithCustomDBNameAndTableAsync<OperationInfo>(post.FixFirm, powerstations.SiteDB, "operation_firm");
                            if (IsValidEmail(firm.Email))
                            {
                                NoticeSchedule schedule = new NoticeSchedule()
                                {
                                    EmailType = 3,
                                    Type = 1,
                                    RecipientName = firm.Name,
                                    RecipientEmail = firm.Email,
                                    Subject = powerstations.Name + "-" + fixtype + "-" + post.WorkTime,
                                    Content = "維修項目:" + post.FixDo + "</br>注意事項 :" + post.Notice,
                                };

                                properties = new List<string>()
                                {
                                    "UserId",
                                    "EmailType",
                                    "RecipientEmail",
                                    "Subject",
                                    "Content",
                                    "RecipientName",
                                    "Type",
                                    "ExceptionId"
                                };
                                await noticeScheduleRepository.AddAnyThing<NoticeSchedule>(schedule, properties, "notice_schedule");
                            }

                        }
                    }



                    


                    #endregion

                    apiResult.Code = "0000";
                    apiResult.Msg = "儲存成功";
                    apiResult.Data = operationRecord.Id;
                    
                }
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        public async Task<ApiResult<string>> DeleteOneOperationRecord(int id)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                var operationRecord = await operationRepository.GetOneOperationRecordAsync(id);

                if (operationRecord == null)
                {
                    apiResult.Code = "9989";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                await operationRepository.DeleteOneOperationRecordAsync(id);

                apiResult.Code = "0000";
                apiResult.Msg = "刪除成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        public async Task<ApiResult<string>> ReductionOneOperationRecord(int id)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                //var operationRecord = await operationRepository.GetOneOperationRecordAsync(id);

                //if (operationRecord == null)
                //{
                //    apiResult.Code = "9989";
                //    apiResult.Msg = errorCode.GetString(apiResult.Code);
                //    return apiResult;
                //}

                await operationRepository.ReductionOneOperationRecordAsync(id);

                apiResult.Code = "0000";
                apiResult.Msg = "還原成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + "Id=" + id);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        /// <summary>
        /// 儲存運維作業記錄檔案
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<OperationRecord>> SaveOperationRecordFile([FromForm] PostOperationRecord post)
        {
            ApiResult<OperationRecord> apiResult = new ApiResult<OperationRecord>();

            OperationRecord operationRecord = null;

            try
            {
                operationRecord = await operationRepository.GetOneOperationRecordAsync(post.Id);

                if (operationRecord == null)
                {
                    apiResult.Code = "9989";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                #region 新增運維作業記錄檔案
                List<OperationRecordFile> operationRecordFiles;

                if (post.RecordFiles != null && post.RecordFiles.Length > 0)
                {
                    FolderFunction folderFunction = new FolderFunction();

                    var fileSaveAsPath = Path.Combine(operationRecordSaveAsPath, operationRecord.Id.ToString());

                    folderFunction.CreateFolder(fileSaveAsPath, 0);

                    operationRecordFiles = new List<OperationRecordFile>();

                    foreach (var file in post.RecordFiles)
                    {
                        var split = file.FileName.Split(".");

                        var fileName = Guid.NewGuid() + "." + split[split.Length - 1];

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

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

                        OperationRecordFile operationRecordFile = new OperationRecordFile()
                        {
                            RecordId = operationRecord.Id,
                            FileName = fileName,
                            CreatedBy = myUser.Id
                        };

                        operationRecordFiles.Add(operationRecordFile);
                    }

                    List<string> fileProperties = new List<string>()
                        {
                            "RecordId",
                            "FileName",
                            "CreatedBy"
                        };

                    await operationRepository.AddOperationRecordFilesAsync(operationRecordFiles, fileProperties);
                }
                #endregion

                apiResult.Code = "0000";
                apiResult.Msg = "儲存成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        public async Task<ApiResult<string>> DeleteOperationRecordFile(PostOperationRecordIdAndSelectedId post)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            OperationRecord operationRecord = null;
            OperationRecordFile operationRecordFile = null;

            try
            {
                operationRecord = await operationRepository.GetOneOperationRecordAsync(post.ReocdeId);

                if (operationRecord == null)
                {
                    apiResult.Code = "9989";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                operationRecordFile = await operationRepository.GetOneOperationRecordFileAsync(post.SelectedId);

                if (operationRecordFile == null)
                {
                    apiResult.Code = "9987";
                    apiResult.Msg = errorCode.GetString(apiResult.Code);
                    return apiResult;
                }

                await operationRepository.DeleteOneOperationRecordFile(post.SelectedId);

                apiResult.Code = "0000";
                apiResult.Msg = "刪除成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = errorCode.GetString(apiResult.Code);
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }

        public async Task<ApiResult<List<OperationRecordDataTable>>> ExportOperationRecordExcel(PostOperationRecordFilter post)
        {
            ApiResult<List<OperationRecordDataTable>> apiResult = new ApiResult<List<OperationRecordDataTable>>();

            List<OperationRecordDataTable> records = null;

            try
            {

                //if (!IsPlatformLayer(myUser.Role.Layer))
                //{   //如果只是身分公司管理員 或 公司使用者，就只能看自己公司的資料
                //    post.SelectedCompanyId = myUser.CompanyId;
                //}

                records = await operationRepository.GetAllRecordByFilterAsync(post);

                foreach (var record in records)
                {
                    record.PowerStationName = !string.IsNullOrEmpty(record.PowerStationName) ? record.PowerStationName : "";
                    record.FormId = !string.IsNullOrEmpty(record.FormId) ? record.FormId : "";
                    record.FixDo = !string.IsNullOrEmpty(record.FixDo) ? record.FixDo : "";
                    record.WorkPersonName = !string.IsNullOrEmpty(record.WorkPersonName) ? record.WorkPersonName : "";
                    //record.FinishTime = !string.IsNullOrEmpty(record.FinishTime) ? record.FinishTime : "";

                    if (record.RecordFiles != null && record.RecordFiles.Count > 0)
                    {
                        foreach (var file in record.RecordFiles)
                        {
                            var hyperLink = "<a href='" + baseURL + file.FileName + "'>" + file.FileName + "</a>";
                            if (record.HyperLinks == null)
                            {
                                record.HyperLinks = new List<string>();
                            }
                            record.HyperLinks.Add(hyperLink);
                        }
                    }
                }

                apiResult.Code = "0000";
                apiResult.Data = records;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                string json = System.Text.Json.JsonSerializer.Serialize(post);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + json);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            apiResult.Msg = errorCode.GetString(apiResult.Code);
            return apiResult;
        }

        public async void Schedule()
        {
            try
            {
                var getTime = await operationRepository.GetOperationSchedules();
                foreach (OperationCreatePlanModal a in getTime)
                {
                    DateTime Updatedtime;
                    if (a.ScheduleType == 0)//日
                    {
                        Updatedtime = Convert.ToDateTime(a.StartTime).AddDays(a.ScheduleNum);
                    }
                    else if (a.ScheduleType == 1)//周
                    {
                        Updatedtime = Convert.ToDateTime(a.StartTime).AddDays(a.ScheduleNum * 7);
                    }
                    else if (a.ScheduleType == 2)//月
                    {
                        Updatedtime = Convert.ToDateTime(a.StartTime).AddMonths(a.ScheduleNum);
                    }
                    else if (a.ScheduleType == 3)//季
                    {
                        Updatedtime = Convert.ToDateTime(a.StartTime).AddMonths(a.ScheduleNum * 3);
                    }
                    else // 年
                    {
                        Updatedtime = Convert.ToDateTime(a.StartTime).AddYears(a.ScheduleNum);
                    }

                    if (Updatedtime < DateTime.Now)
                    {
                        var now = DateTime.Now.ToString("yyyy-MM-dd");
                        var finalid = await operationRepository.GetCurrentSerialNumber("operation_plan_create", $"PowerStationId = {a.PowerStationId} AND CreatedAt LIKE '%{now}%'");
                        var newSerialNumber = GetLastSerialNumber(finalid);
                        var OperationPlan = new OperationCreatePlan()
                        {
                            EmailType = a.EmailType,
                            ScheduleNum = a.ScheduleNum,
                            Description = a.Description,
                            WorkDay = a.WorkDay,
                            ScheduleType = a.ScheduleType,
                            SerialNumber = newSerialNumber,
                            StartTime = Updatedtime.ToString("yyyy-MM-dd hh:mm:ss"),
                            PowerStationId = a.PowerStationId,
                            Type = a.Type,
                            PlanId = DateTime.Now.ToString("yyyyMMdd") + newSerialNumber,
                            CreatedBy = myUser.Id
                        };
                        List<string> properties = new List<string>()
                        {
                            "EmailType",
                            "ScheduleNum",
                            "Description",
                            "WorkDay",
                            "ScheduleType",
                            "SerialNumber",
                            "StartTime",
                            "PowerStationId",
                            "Type",
                            "PlanId",
                            "CreatedBy"
                        };
                        await operationRepository.AddOperationPlan(OperationPlan, properties);

                        var record = new PlanToRecord()
                        {
                            WorkType = a.Type,
                            PowerStationId = a.PowerStationId,
                            StartTime = Updatedtime.ToString("yyyy-MM-dd hh:mm:ss"),
                            CreatedBy = myUser.Id,
                            EndTime = Updatedtime.AddDays(a.WorkDay).ToString("yyyy-MM-dd hh:mm:ss")
                        };
                        List<string> properties2 = new List<string>()
                        {
                            "WorkType",
                            "PowerStationId",
                            "StartTime",
                            "CreatedBy",
                            "EndTime"
                        };
                        await operationRepository.AddToRecord(record, properties2);
                        var operation = await operationRepository.GetOneOperation(a.Id);
                        await operationRepository.DeleteOneByIdWithCustomTable(a.Id, "operation_plan_create");

                    }

                }
            }
            catch (Exception exception)
            {
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
        }

        bool IsValidEmail(string strIn)
        {
            // Return true if strIn is in valid e-mail format.
            return Regex.IsMatch(strIn, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
        }

    }
}
