using FrontendWebApi.Models;
using iTextSharp.text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NPOI.HPSF;
using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.Util;
using Org.BouncyCastle.Crypto.Agreement.JPake;
using Repository.BackendRepository.Interface;
using Repository.FrontendRepository.Interface;
using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Image = System.Drawing.Image;
using System.IdentityModel.Tokens.Jwt;
using System.Net;

namespace FrontendWebApi.ApiControllers
{
    //[Route("api/[controller]")]
    //[ApiController]
    public class OperationController : MyBaseApiController<OperationController>
    {
        private readonly IBackendRepository backendRepository;
        private string operationFileSaveAsPath = "";

        public OperationController(IBackendRepository backendRepository)
        {
            this.backendRepository = backendRepository;
            operationFileSaveAsPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "upload", "operation");
        }

        [HttpPost]
        public async Task<ApiResult<List<Variable>>> MaiSysList()
        {
            ApiResult<List<Variable>> apiResult = new ApiResult<List<Variable>>();
            List<Variable> main_system_list = new List<Variable>();

            try
            {
                var sqlString = @$"SELECT *
                                    FROM variable 
                                    WHERE system_type = @main_system_type AND deleted = 0
                                    ORDER BY system_priority, created_at desc";

                var param = new { @main_system_type = main_system_type };
                main_system_list = await backendRepository.GetAllAsync<Variable>(sqlString, param);

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

            return apiResult;
        }

        [HttpPost]
        public async Task<ApiResult<List<Variable>>> SubSysList([FromBody] Find_Sub_List fsl)
        {
            ApiResult<List<Variable>> apiResult = new ApiResult<List<Variable>>();
            List<Variable> sub_system_list = new List<Variable>();

            try
            {
                var sqlString = @$"SELECT v2.*
                                    FROM variable v2
                                    JOIN variable v1 ON v2.system_parent_id = v1.id AND v1.system_type = @main_system_type AND v1.deleted = 0
                                    WHERE v2.system_type = @sub_system_type AND v2.deleted = 0 AND v1.system_value in @main_system_tag
                                    ORDER BY v2.system_priority, v2.created_at desc";

                var param = new { @main_system_type = main_system_type, @sub_system_type = sub_system_type, @main_system_tag = fsl.main_system_tag };
                sub_system_list = await backendRepository.GetAllAsync<Variable>(sqlString, param);

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

            return apiResult;

        }

        /// <summary>
        /// 地區列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<BuildingList>>> AreaList()
        {
            ApiResult<List<BuildingList>> apiResult = new ApiResult<List<BuildingList>>();
            List<BuildingList> bl = new List<BuildingList>();

            try
            {
                var sqlString = $@"select system_value as device_area_tag, system_key as area_name from variable where system_type = 'area' and deleted = 0";

                bl = await backendRepository.GetAllAsync<BuildingList>(sqlString);

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

            return apiResult;
        }

        /// <summary>
        /// 東別列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<BuildingList>>> BuiList([FromBody] BuildingList b)
        {
            ApiResult<List<BuildingList>> apiResult = new ApiResult<List<BuildingList>>();
            List<BuildingList> bl = new List<BuildingList>();

            try
            {
                var sqlString = @$"select building_tag as device_building_tag, b.full_name as building_name
                                   from building b 
                                   where deleted = 0 and area_tag = @device_area_tag
                                   group by b.full_name, building_tag";

                bl = await backendRepository.GetAllAsync<BuildingList>(sqlString, new { @device_area_tag = b.device_area_tag });

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

            return apiResult;
        }

        /// <summary>
        /// 樓層列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<BuildingList>>> FloList([FromBody] BuildingList b)
        {
            ApiResult<List<BuildingList>> apiResult = new ApiResult<List<BuildingList>>();
            List<BuildingList> bl = new List<BuildingList>();

            try
            {
                var sqlString = @$"select full_name as device_floor_tag
                                   from floor
                                   where deleted = 0 and building_tag = @device_building_tag
                                   group by full_name";

                bl = await backendRepository.GetAllAsync<BuildingList>(sqlString, new { @device_building_tag = b.device_building_tag });

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

            return apiResult;
        }

        /// <summary>
        /// 設備列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<List<Device>>> DevList([FromBody] BuildingList bl)
        {
            ApiResult<List<Device>> apiResult = new ApiResult<List<Device>>();
            List<Device> d = new List<Device>();

            try
            {
                var sqlString = @$"select device_number, concat(device_floor_tag, ' ', full_name) as device_name, full_name, device_floor_tag, device_system_tag, device_name_tag
                                   from device where deleted = 0 and device_area_tag = @device_area_tag and device_building_tag = @device_building_tag and device_name_tag in @list_sub_system_tag  ";

                var param = new { @device_building_tag = bl.device_building_tag, @device_area_tag = bl.device_area_tag, @list_sub_system_tag = bl.list_sub_system_tag };

                d = await backendRepository.GetAllAsync<Device>(sqlString, param);

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

            return apiResult;
        }

        /// <summary>
        /// 汇出excel (work_type: null=廠商, 1=保養, 2=維修)
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult<ApiResult<string>> OpeExportExcel([FromBody] ExportExcel ee)
        {
            ApiResult<string> apiResult = new ApiResult<string>();
            if (ee.work_type > 2 || ee.work_type < 1)
            {
                apiResult.Code = "0001";
                apiResult.Msg = "沒有資料匯入";
                return apiResult;
            }

            var fileDateName = ee.startdate == null ? "" : ee.enddate == null ? "_" + ((DateTime)ee.startdate).ToString("yyyy-MM-dd") : "_" + ((DateTime)ee.startdate).ToString("yyyy-MM-dd") + "_" + ((DateTime)ee.enddate).ToString("yyyy-MM-dd");
            var fileName = (ee.work_type == null ? "廠商資料" : ee.work_type == 1 ? "保養記錄" : ee.work_type == 2 ? "維修" : null) + fileDateName + ".xlsx";
            var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "excel", "operation");

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

                    if (string.IsNullOrEmpty(ee.work_type.ToString()))
                    {
                        var sqlString = $@"select ofi.*, v2.system_key
                                    from operation_firm ofi
                                    left join variable v1 on ofi.device_system_category_layer2 = v1.system_value and v1.system_type = @main_system_type and v1.deleted = 0
                                    left join variable v2 on v1.id = v2.system_parent_id and ofi.device_system_category_layer3 = v2.system_value and v2.system_type = @sub_system_type and v2.deleted = 0
                                        where ofi.deleted = 0";
                        var sheet = workbook.CreateSheet("廠商資料");
                        var operation_firm = backendRepository.GetAllAsync<Operation_Firm>(sqlString, new { @main_system_type = main_system_type, @sub_system_type = sub_system_type });
                        int RowPosition = 0;
                        #region set cell
                        IRow row = sheet.CreateRow(RowPosition);
                        sheet.SetColumnWidth(0, 4 * 160 * 12);
                        sheet.SetColumnWidth(1, 4 * 160 * 12);
                        sheet.SetColumnWidth(2, 4 * 160 * 12);
                        sheet.SetColumnWidth(3, 4 * 160 * 12);
                        sheet.SetColumnWidth(4, 4 * 160 * 12);
                        sheet.SetColumnWidth(5, 4 * 160 * 12);
                        sheet.SetColumnWidth(6, 4 * 160 * 12);
                        sheet.SetColumnWidth(7, 4 * 160 * 12);
                        ICell cell = row.CreateCell(0);
                        cell.SetCellValue("廠商類別");
                        cell.CellStyle = styleLine12;
                        cell = row.CreateCell(1);
                        cell.SetCellValue("廠商名稱");
                        cell.CellStyle = styleLine12;
                        cell = row.CreateCell(2);
                        cell.SetCellValue("聯絡人");
                        cell.CellStyle = styleLine12;
                        cell = row.CreateCell(3);
                        cell.SetCellValue("電話");
                        cell.CellStyle = styleLine12;
                        cell = row.CreateCell(4);
                        cell.SetCellValue("郵箱");
                        cell.CellStyle = styleLine12;
                        cell = row.CreateCell(5);
                        cell.SetCellValue("統一編號");
                        cell.CellStyle = styleLine12;
                        cell = row.CreateCell(6);
                        cell.SetCellValue("備注");
                        cell.CellStyle = styleLine12;
                        cell = row.CreateCell(7);
                        cell.SetCellValue("建立時間");
                        cell.CellStyle = styleLine12;
                        #endregion

                        if (operation_firm.Result.Count > 0)
                        {
                            foreach (var of in operation_firm.Result)
                            {
                                RowPosition += 1;
                                row = sheet.CreateRow(RowPosition);
                                for (var i = 0; i < 8; i++)
                                {
                                    cell = row.CreateCell(i);
                                    if (i == 0)
                                    {
                                        cell.SetCellValue(of.system_key);
                                    }
                                    if (i == 1)
                                    {
                                        cell.SetCellValue(of.name);
                                    }
                                    if (i == 2)
                                    {
                                        cell.SetCellValue(of.contact_person);
                                    }
                                    if (i == 3)
                                    {
                                        cell.SetCellValue(of.phone);
                                    }
                                    if (i == 4)
                                    {
                                        cell.SetCellValue(of.email);
                                    }
                                    if (i == 5)
                                    {
                                        cell.SetCellValue(of.tax_id_number);
                                    }
                                    if (i == 6)
                                    {
                                        cell.SetCellValue(of.remark);
                                    }
                                    if (i == 7)
                                    {
                                        cell.SetCellValue(of.Created_at);
                                    }

                                    cell.CellStyle = style12;
                                }
                            }
                        }
                    }
                    else if (ee.work_type == 1)
                    {
                        var sqlString = $@"select opr.*, concat(d.device_floor_tag, ' ', d.device_last_name, ' ', d.device_serial_tag) as device_name, ui.full_name as user_full_name
                                       from operation_record opr
                                       left join device d on opr.fix_do_code = d.device_number and d.deleted = 0 and d.device_area_tag = SUBSTRING_INDEX(opr.fix_do_code, '_', 1)
				                                           and d.device_building_tag = SUBSTRING_INDEX(opr.fix_do_code, '_', 2) and d.device_floor_tag = SUBSTRING_INDEX(opr.fix_do_code, '_', 5)
				                                           and d.device_system_tag = opr.device_system_category_layer2 and d.device_name_tag = opr.device_system_category_layer3
                                       left join userinfo ui on opr.work_person_id = ui.userinfo_guid
                                       where opr.deleted = 0 and opr.work_type = 1;";
                        var sheet = workbook.CreateSheet("廠商資料");
                        var operation_record = backendRepository.GetAllAsync<Operation_Record>(sqlString, null);
                        List<Operation_Record_File> operation_record_file = new List<Operation_Record_File>();

                        if (operation_record.Result.Count > 0)
                        {
                            foreach (var or in operation_record.Result)
                            {
                                sqlString = $@"select * from operation_record_file where record_id = @record_id";
                                var param = new { @record_id = or.id };
                                operation_record_file = backendRepository.GetAllAsync<Operation_Record_File>(sqlString, param).Result;
                                or.lorf = operation_record_file;
                            }

                            int RowPosition = 0;
                            #region set cell
                            IRow row = sheet.CreateRow(RowPosition);
                            sheet.SetColumnWidth(0, 4 * 160 * 12);
                            sheet.SetColumnWidth(1, 4 * 160 * 12);
                            sheet.SetColumnWidth(2, 4 * 160 * 12);
                            sheet.SetColumnWidth(3, 4 * 160 * 12);
                            sheet.SetColumnWidth(4, 4 * 160 * 12);
                            sheet.SetColumnWidth(5, 4 * 160 * 12);
                            sheet.SetColumnWidth(6, 4 * 160 * 12);
                            sheet.SetColumnWidth(7, 4 * 160 * 12);
                            sheet.SetColumnWidth(8, 4 * 160 * 12);
                            sheet.SetColumnWidth(9, 4 * 160 * 12);
                            ICell cell = row.CreateCell(0);
                            cell.SetCellValue("項目");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(1);
                            cell.SetCellValue("位置");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(2);
                            cell.SetCellValue("表單號");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(3);
                            cell.SetCellValue("設備名稱");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(4);
                            cell.SetCellValue("狀態");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(5);
                            cell.SetCellValue("處理人員");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(6);
                            cell.SetCellValue("預計施工時間");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(7);
                            cell.SetCellValue("檔案上傳");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(8);
                            cell.SetCellValue("完成時間");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(9);
                            cell.SetCellValue("建立時間");
                            cell.CellStyle = styleLine12;
                            #endregion
                            foreach (var or in operation_record.Result)
                            {
                                RowPosition += 1;
                                row = sheet.CreateRow(RowPosition);
                                for (var i = 0; i < 10; i++)
                                {
                                    cell = row.CreateCell(i);
                                    if (i == 0)
                                    {
                                        cell.SetCellValue(or.work_type_name);
                                    }
                                    if (i == 1)
                                    {
                                        cell.SetCellValue(or.location);
                                    }
                                    if (i == 2)
                                    {
                                        cell.SetCellValue(or.formId);
                                    }
                                    if (i == 3)
                                    {
                                        cell.SetCellValue(or.device_name);
                                    }
                                    if (i == 4)
                                    {
                                        cell.SetCellValue(or.status_name);
                                    }
                                    if (i == 5)
                                    {
                                        cell.SetCellValue(or.user_full_name);
                                    }
                                    if (i == 6)
                                    {
                                        cell.SetCellValue(or.start_time != null ? ((DateTime)or.start_time).ToString("yyyy/MM/dd HH:mm:dd") : null);
                                    }
                                    if (i == 7)
                                    {
                                        var imageNames = or.lorf.Count > 0 ? or.lorf.Select(x => x.save_file_name).ToList() : null;
                                        if (imageNames != null)
                                        {
                                            //insert image process
                                            var dy1 = 10;
                                            var dx1 = 10;

                                            //image column
                                            sheet.SetColumnWidth(i, 16 * imageNames.Count * 256); //width: picture width(16:100), image total, per character(256)
                                            foreach (var ins in imageNames)
                                            {
                                                //image initial
                                                var extName = ins.Split('.')[1].ToUpper().Equals("JPG") ? "PNG" : ins.Split('.')[1].ToUpper();
                                                var fullPath = Path.Combine(operationFileSaveAsPath, ins);
                                                var img = Image.FromFile(fullPath);

                                                //compress image
                                                decimal sizeRatio = ((decimal)img.Height / img.Width);
                                                int thumbWidth = 100;
                                                int thumbHeight = decimal.ToInt32(sizeRatio * thumbWidth);
                                                var thumbStream = img.GetThumbnailImage(thumbWidth, thumbHeight, () => false, IntPtr.Zero);
                                                var memoryStream = new MemoryStream();
                                                thumbStream.Save(memoryStream, ImageFormat.Jpeg);

                                                //setting pictureType enum
                                                int format = 0;
                                                var drawing = (XSSFDrawing)sheet.CreateDrawingPatriarch();
                                                format = Convert.ToInt32(Enum.Parse(typeof(PictureType), extName));

                                                //set picture size and location
                                                if (format != 0)
                                                {
                                                    var pictureIds = workbook.AddPicture(memoryStream.ToArray(), format);
                                                    XSSFClientAnchor anchor = new XSSFClientAnchor(XSSFShape.EMU_PER_PIXEL * dx1, XSSFShape.EMU_PER_PIXEL * dy1, 0, 0, i, j, 0, 0);
                                                    anchor.AnchorType = AnchorType.DontMoveAndResize;
                                                    var picture = (XSSFPicture)drawing.CreatePicture(anchor, pictureIds);
                                                    var size = picture.GetImageDimension();
                                                    row.HeightInPoints = size.Height;
                                                    picture.Resize();

                                                    //add 105 each new pic
                                                    dx1 += 105;
                                                }
                                            }
                                        }

                                        j++;
                                    }
                                    if (i == 8)
                                    {
                                        cell.SetCellValue(or.finish_time != null ? ((DateTime)or.finish_time).ToString("yyyy/MM/dd HH:mm:dd") : null);
                                    }
                                    if (i == 9)
                                    {
                                        cell.SetCellValue(or.Created_at);
                                    }

                                    cell.CellStyle = style12;
                                }
                            }
                        }
                    }
                    else if (ee.work_type == 2)
                    {
                        var sqlString = $@"select opr.*, concat(d.device_floor_tag, ' ', d.device_last_name, ' ', d.device_serial_tag) as device_name, ui.full_name as user_full_name
                                       from operation_record opr
                                       left join device d on opr.fix_do_code = d.device_number and d.deleted = 0 and d.device_area_tag = SUBSTRING_INDEX(opr.fix_do_code, '_', 1)
				                                        and d.device_building_tag = SUBSTRING_INDEX(opr.fix_do_code, '_', 2) and d.device_floor_tag = SUBSTRING_INDEX(opr.fix_do_code, '_', 5)
				                                        and d.device_system_tag = opr.device_system_category_layer2 and d.device_name_tag = opr.device_system_category_layer3
                                       left join userinfo ui on opr.work_person_id = ui.userinfo_guid
                                       where opr.deleted = 0 and opr.work_type = 2";
                        var sheet = workbook.CreateSheet("廠商資料");
                        var operation_record = backendRepository.GetAllAsync<Operation_Record>(sqlString);
                        List<Operation_Record_File> operation_record_file = new List<Operation_Record_File>();

                        if (operation_record.Result.Count > 0)
                        {
                            foreach (var or in operation_record.Result)
                            {
                                sqlString = $@"select * from operation_record_file where record_id = @record_id";
                                var param = new { @record_id = or.id };
                                operation_record_file = backendRepository.GetAllAsync<Operation_Record_File>(sqlString, param).Result;
                                or.lorf = operation_record_file;
                            }

                            int RowPosition = 0;
                            #region set cell
                            IRow row = sheet.CreateRow(RowPosition);
                            sheet.SetColumnWidth(0, 4 * 160 * 12);
                            sheet.SetColumnWidth(1, 4 * 160 * 12);
                            sheet.SetColumnWidth(2, 4 * 160 * 12);
                            sheet.SetColumnWidth(3, 4 * 160 * 12);
                            sheet.SetColumnWidth(4, 4 * 160 * 12);
                            sheet.SetColumnWidth(5, 4 * 160 * 12);
                            sheet.SetColumnWidth(6, 4 * 160 * 12);
                            sheet.SetColumnWidth(7, 4 * 160 * 12);
                            sheet.SetColumnWidth(8, 4 * 160 * 12);
                            sheet.SetColumnWidth(9, 4 * 160 * 12);
                            sheet.SetColumnWidth(10, 4 * 160 * 12);
                            ICell cell = row.CreateCell(0);
                            cell.SetCellValue("項目");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(1);
                            cell.SetCellValue("位置");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(2);
                            cell.SetCellValue("異常代號");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(3);
                            cell.SetCellValue("表單號");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(4);
                            cell.SetCellValue("設備名稱");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(5);
                            cell.SetCellValue("狀態");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(6);
                            cell.SetCellValue("處理人員");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(7);
                            cell.SetCellValue("預計施工時間");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(8);
                            cell.SetCellValue("檔案上傳");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(9);
                            cell.SetCellValue("完成時間");
                            cell.CellStyle = styleLine12;
                            cell = row.CreateCell(10);
                            cell.SetCellValue("建立時間");
                            cell.CellStyle = styleLine12;

                            #endregion
                            foreach (var or in operation_record.Result)
                            {
                                RowPosition += 1;
                                row = sheet.CreateRow(RowPosition);
                                for (var i = 0; i < 11; i++)//column
                                {
                                    cell = row.CreateCell(i);
                                    if (i == 0)
                                    {
                                        cell.SetCellValue(or.work_type_name);
                                    }
                                    if (i == 1)
                                    {
                                        cell.SetCellValue(or.location);
                                    }
                                    if (i == 2)
                                    {
                                        cell.SetCellValue(or.error_code);
                                        sheet.AutoSizeColumn(i);
                                    }
                                    if (i == 3)
                                    {
                                        cell.SetCellValue(or.formId);
                                    }
                                    if (i == 4)
                                    {
                                        cell.SetCellValue(or.device_name);
                                    }
                                    if (i == 5)
                                    {
                                        cell.SetCellValue(or.status_name);
                                    }
                                    if (i == 6)
                                    {
                                        cell.SetCellValue(or.user_full_name);
                                    }
                                    if (i == 7)
                                    {
                                        cell.SetCellValue(or.start_time != null ? ((DateTime)or.start_time).ToString("yyyy/MM/dd HH:mm:ss") : null);
                                    }
                                    if (i == 8)//image
                                    {
                                        var imageNames = or.lorf.Count > 0 ? or.lorf.Select(x => x.save_file_name).ToList() : null;
                                        if (imageNames != null)
                                        {
                                            //insert image process
                                            var dy1 = 10;
                                            var dx1 = 10;

                                            //image column
                                            sheet.SetColumnWidth(i, 16 * imageNames.Count * 256); //width: picture width(16:100), image total, per character(256)
                                            foreach (var ins in imageNames)
                                            {
                                                //image initial
                                                var extName = ins.Split('.')[1].ToUpper().Equals("JPG") ? "PNG" : ins.Split('.')[1].ToUpper();
                                                var fullPath = Path.Combine(operationFileSaveAsPath, ins);
                                                var img = Image.FromFile(fullPath);

                                                //compress image
                                                decimal sizeRatio = ((decimal)img.Height / img.Width);
                                                int thumbWidth = 100;
                                                int thumbHeight = decimal.ToInt32(sizeRatio * thumbWidth);
                                                var thumbStream = img.GetThumbnailImage(thumbWidth, thumbHeight, () => false, IntPtr.Zero);
                                                var memoryStream = new MemoryStream();
                                                thumbStream.Save(memoryStream, ImageFormat.Jpeg);

                                                //setting pictureType enum
                                                int format = 0;
                                                var drawing = (XSSFDrawing)sheet.CreateDrawingPatriarch();
                                                format = Convert.ToInt32(Enum.Parse(typeof(PictureType), extName));

                                                //set picture size and location
                                                if (format != 0)
                                                {
                                                    var pictureIds = workbook.AddPicture(memoryStream.ToArray(), format);
                                                    XSSFClientAnchor anchor = new XSSFClientAnchor(XSSFShape.EMU_PER_PIXEL * dx1, XSSFShape.EMU_PER_PIXEL * dy1, 0, 0, i, j, 0, 0);
                                                    anchor.AnchorType = AnchorType.DontMoveAndResize;
                                                    var picture = (XSSFPicture)drawing.CreatePicture(anchor, pictureIds);
                                                    var size = picture.GetImageDimension();
                                                    row.HeightInPoints = size.Height;
                                                    picture.Resize();

                                                    //add 105 each new pic
                                                    dx1 += 105;
                                                }
                                            }
                                        }

                                        j++;
                                    }
                                    if (i == 9)
                                    {
                                        cell.SetCellValue(or.finish_time != null ? ((DateTime)or.finish_time).ToString("yyyy/MM/dd HH:mm:ss") : null);
                                    }
                                    if (i == 10)
                                    {
                                        cell.SetCellValue(or.Created_at);
                                    }

                                    cell.CellStyle = style12;

                                }
                            }
                        }
                    }

                    workbook.Write(fs);
                }

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

            return Ok(apiResult);
        }

        #region 廠商
        /// <summary>
        /// 廠商資料列表(搜寻) / selection列表 ofl = null
        /// </summary>
        /// <param name="ofl"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<Operation_Firm>>> OpeFirSel([FromBody] OperationFindList ofl)
        {
            ApiResult<List<Operation_Firm>> apiResult = new ApiResult<List<Operation_Firm>>();
            List<Operation_Firm> opList = new List<Operation_Firm>();
            try
            {
                var sqlString = $@"select id, name from operation_firm where deleted = 0 and device_system_category_layer3 in @sub_system_tag";
                opList = await backendRepository.GetAllAsync<Operation_Firm>(sqlString, new { @sub_system_tag = ofl.sub_system_tag });

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

            return apiResult;
        }

        /// <summary>
        /// 廠商資料列表(搜寻) / selection列表 ofl = null
        /// </summary>
        /// <param name="ofl"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<Operation_Firm>>> OpeFirList([FromBody] OperationFindList ofl)
        {
            ApiResult<List<Operation_Firm>> apiResult = new ApiResult<List<Operation_Firm>>();
            List<Operation_Firm> opList = new List<Operation_Firm>();
            string sWhere = "";
            try
            {
                if (ofl != null)
                {
                    //if (ofl.start_created_at != null || ofl.end_created_at != null)
                    //{
                    //    sWhere += $@" and (ofi.created_at >= ifnull(@start_created_at, ofi.created_at) AND ofi.created_at <= ifnull(@end_created_at, ofi.created_at))";
                    //}
                    //else if (ofl.today)
                    //{
                    //    sWhere += $@" and convert(of.created_at, DATE) = convert(NOW(), DATE)";
                    //}
                    //else if (ofl.yesterday)
                    //{
                    //    sWhere += $@" and convert(of.created_at, DATE) = convert(ADDDATE(NOW(), -1), DATE)";
                    //}

                    if (ofl.main_system_tag != null)
                    {
                        sWhere += $@" and ofi.device_system_category_layer2 in @main_system_tag";

                    }
                    sWhere += $@" and ofi.device_system_category_layer3 in @sub_system_tag";

                    var sqlString = @$"select ofi.*, v2.system_key
                                    from operation_firm ofi
                                    left join variable v1 on ofi.device_system_category_layer2 = v1.system_value and v1.system_type = @main_system_type and v1.deleted = 0
                                    left join variable v2 on v1.id = v2.system_parent_id and ofi.device_system_category_layer3 = v2.system_value and v2.system_type = @sub_system_type and v2.deleted = 0
                                    where ofi.deleted = 0" + sWhere;

                    var param = new { @main_system_type = main_system_type, @sub_system_type = sub_system_type, @sub_system_tag = ofl.sub_system_tag, @main_system_tag = ofl.main_system_tag };
                    opList = await backendRepository.GetAllAsync<Operation_Firm>(sqlString, param);
                }
                else
                {
                    var sqlString = $@"select id, name from operation_firm where deleted = 0";
                    opList = await backendRepository.GetAllAsync<Operation_Firm>(sqlString);
                }

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

            return apiResult;
        }

        /// <summary>
        /// 廠商資料讀取(搜寻) / selection讀取 ofl = null
        /// </summary>
        /// <param name="ofl"></param>
        /// <returns></returns>
        public async Task<ApiResult<Operation_Firm>> OpeFirRead([FromBody] OperationFindList ofl)
        {
            ApiResult<Operation_Firm> apiResult = new ApiResult<Operation_Firm>();
            Operation_Firm opList = new Operation_Firm();
            try
            {
                var sqlString = @$"select ofi.*, v2.system_key
                                from operation_firm ofi
                                left join variable v1 on ofi.device_system_category_layer2 = v1.system_value and v1.system_type = @main_system_type and v1.deleted = 0 and ofi.device_system_category_layer2 = v1.system_value
                                left join variable v2 on v1.id = v2.system_parent_id and ofi.device_system_category_layer3 = v2.system_value and v2.deleted = 0
                                where ofi.deleted = 0 and ofi.id = @id";

                var param = new { @id = ofl.id };
                opList = await backendRepository.GetOneAsync<Operation_Firm>(sqlString, param);

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

            return apiResult;
        }

        /// <summary>
        /// 新增一笔廠商資料
        /// </summary>
        /// <param name="of"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> SaveOpeFirm([FromBody] Operation_Firm of)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                if (of.tax_id_number != null)
                {
                    var sWhere = "deleted = 0 AND tax_id_number = @tax_id_number";
                    var ofo = await backendRepository.GetOneAsync<Operation_Firm>("operation_firm", sWhere, new { @tax_id_number = of.tax_id_number });
                    if (ofo != null)
                    {
                        apiResult.Code = "0002";
                        apiResult.Data = "已有相同的统一编号";
                        return apiResult;
                    }
                }

                Dictionary<string, object> operation_firm = new Dictionary<string, object>()
                {
                    { "@deleted", 0 },
                    { "@device_system_category_layer2", of.device_system_category_layer2 },
                    { "@device_system_category_layer3", of.device_system_category_layer3 },
                    { "@name", of.name },
                    { "@contact_person", of.contact_person },
                    { "@phone", of.phone },
                    { "@email", of.email },
                    { "@tax_id_number", of.tax_id_number },
                    { "@remark", of.remark },
                    { "@created_by", myUser.userinfo_guid },
                    { "@created_at", DateTime.Now }
                };

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

            return apiResult;
        }

        /// <summary>
        /// 编辑一笔廠商資料
        /// </summary>
        /// <param name="of"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> EdtOneOpeFirm([FromBody] Operation_Firm of)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                var sWhere = @$"deleted = 0 and id = @id";
                var gm = await backendRepository.GetOneAsync<Operation_Firm>("operation_firm", sWhere, new { @id = of.id });

                if (gm == null)
                {
                    apiResult.Code = "0001";
                    apiResult.Data = "無法找到厂商";
                    return apiResult;
                }

                if (of.tax_id_number != null)
                {
                    sWhere = "deleted = 0 AND tax_id_number = @tax_id_number and id != @id";
                    var ofo = await backendRepository.GetOneAsync<Operation_Firm>("operation_firm", sWhere, new { @tax_id_number = of.tax_id_number, @id = of.id });
                    if (ofo != null)
                    {
                        apiResult.Code = "0002";
                        apiResult.Data = "已有相同的统一编号";
                        return apiResult;
                    }
                }

                Dictionary<string, object> operation_firm = new Dictionary<string, object>()
                {
                    { "@device_system_category_layer2", of.device_system_category_layer2 },
                    { "@device_system_category_layer3", of.device_system_category_layer3 },
                    { "@name", of.name },
                    { "@contact_person", of.contact_person },
                    { "@phone", of.phone },
                    { "@email", of.email },
                    { "@tax_id_number", of.tax_id_number },
                    { "@remark", of.remark },
                    { "updated_by", myUser.userinfo_guid },
                    { "updated_at", DateTime.Now }
                };

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

            return apiResult;
        }

        /// <summary>
        /// 廠商---刪除
        /// </summary>
        /// <param name="or"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> DelOpeFirm([FromBody] Operation_Firm or)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                var sqlString = @$"UPDATE operation_firm SET deleted = 1 WHERE id = @id";
                var param = new { @id = or.id };
                await backendRepository.ExecuteSql(sqlString, param);

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

            return apiResult;
        }
        #endregion

        #region 維修/保養
        /// <summary>
        /// 首頁 取得 已完成1 未完成0 總工單數
        /// </summary>
        /// <param name="ofl"></param>
        /// <returns></returns>
        public async Task<ApiResult<object>> OpeRecListAllTime()
        {
            ApiResult<object> apiResult = new ApiResult<object>();
        
            string sWhere = "";
            try
            {
                var sqlString = $@"select distinct(error_code) ,opr.status, concat(d.device_floor_tag, ' ', d.full_name) as device_name, ui.full_name as user_full_name
                                   from operation_record opr
                                   left join device d on opr.fix_do_code = d.device_number and d.deleted = 0 and d.device_area_tag = SUBSTRING_INDEX(opr.fix_do_code, '_', 1)
								   and d.device_building_tag = SUBSTRING_INDEX(SUBSTRING_INDEX(fix_do_code, '_', 2), '_', -1)
                                   and d.device_floor_tag = SUBSTRING_INDEX(SUBSTRING_INDEX(fix_do_code, '_', 5), '_', -1)
								   and d.device_system_tag = opr.device_system_category_layer2 and d.device_name_tag = opr.device_system_category_layer3	
                                   left join userinfo ui on opr.work_person_id = ui.userinfo_guid  and ui.deleted = 0
                                   where opr.deleted = 0 and opr.work_type = 2" + sWhere;

                List<Operation_Record> orl = await backendRepository.GetAllAsync<Operation_Record>(sqlString);
                int Finished = orl.Where(x => x.status_name == "完成").Count();
                int NotFinished = orl.Where(x => x.status_name == "未完成").Count();
                object Status = new {finish= Finished, notfinish= NotFinished };
                
                apiResult.Code = "0000";
                apiResult.Data = Status;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return apiResult;
        }
        /// <summary>
        /// 維修/保養 列表(work_type)
        /// </summary>
        /// <param name="ofl"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<Operation_Record>>> OpeRecList([FromBody] OperationFindList ofl)
        {
            ApiResult<List<Operation_Record>> apiResult = new ApiResult<List<Operation_Record>>();
            List<Operation_Record> orl = new List<Operation_Record>();
            string sWhere = "";
            try
            {
                if (ofl.work_type != 1 && ofl.work_type != 2)
                {
                    apiResult.Code = "0001";
                    apiResult.Msg = "無此項目類別";
                    return apiResult;
                }

                if (ofl.start_created_at != null || ofl.end_created_at != null)
                {
                    sWhere += $@" and (opr.created_at >= ifnull(@start_created_at, opr.created_at) AND opr.created_at <= ifnull(@end_created_at, opr.created_at))";
                }
                //else if (ofl.today)
                //{
                //    sWhere += $@" and convert(opr.created_at, DATE) = convert(NOW(), DATE)";
                //}
                //else if (ofl.yesterday)
                //{
                //    sWhere += $@" and convert(opr.created_at, DATE) = convert(ADDDATE(NOW(), -1), DATE)";
                //}

                if (ofl.main_system_tag != null)
                {
                    sWhere += $@" and opr.device_system_category_layer2 in @main_system_tag";
                }
                 
                if (ofl.serial_number != null)
                {
                    sWhere += $@" and opr.formId like '%{ofl.serial_number}%'";
                }

                sWhere += $@" and opr.device_system_category_layer3 in @sub_system_tag";
                var sqlString = $@"select opr.* , concat(d.device_floor_tag, ' ', d.full_name) as device_name, ui.full_name as user_full_name
                                   from operation_record opr
                                   left join device d on opr.fix_do_code = d.device_number and d.deleted = 0 and d.device_area_tag = SUBSTRING_INDEX(opr.fix_do_code, '_', 1)
									                                   and d.device_building_tag = SUBSTRING_INDEX(SUBSTRING_INDEX(fix_do_code, '_', 2), '_', -1)
                                                                       and d.device_floor_tag = SUBSTRING_INDEX(SUBSTRING_INDEX(fix_do_code, '_', 5), '_', -1)
									                                   and d.device_system_tag = opr.device_system_category_layer2 and d.device_name_tag = opr.device_system_category_layer3	
                                   left join userinfo ui on opr.work_person_id = ui.userinfo_guid  and ui.deleted = 0
                                   where opr.deleted = 0 and opr.work_type = @work_type" + sWhere;

                var param = new { @work_type = ofl.work_type, @start_created_at = ofl.start_created_at, @end_created_at = ofl.end_created_at, @sub_system_tag = ofl.sub_system_tag, @main_system_tag = ofl.main_system_tag };

                orl = await backendRepository.GetAllAsync<Operation_Record>(sqlString, param);

                if (orl.Count > 0)
                {
                    foreach(var or in orl)
                    {
                        sqlString = $@"select * from operation_record_file where record_id = @record_id and deleted = 0";
                        var oParam = new { @record_id = or.id };
                        var orfl = await backendRepository.GetAllAsync<Operation_Record_File>(sqlString, oParam);
                        or.lorf = orfl;
                    }
                }

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

            return apiResult;
        }
        
        /// <summary>
        /// 維修/保養 讀取(work_type)
        /// </summary>
        /// <param name="ofl"></param>
        /// <returns></returns>
        public async Task<ApiResult<Operation_Record>> OpeRecRead([FromBody] OperationFindList ofl)
        {
            ApiResult<Operation_Record> apiResult = new ApiResult<Operation_Record>();
            Operation_Record orl = new Operation_Record();
            
            try
            {
                var sqlString = $@"select opr.*,d.device_area_tag,d.device_building_tag,d.device_floor_tag, ui.full_name as user_full_name
                                   from operation_record opr
                                   left join device d on opr.fix_do_code = d.device_number
                                   left join userinfo ui on opr.work_person_id = ui.userinfo_guid 
                                   where opr.deleted = 0 and opr.id = @id";

                var param = new { @id = ofl.id };

                orl = await backendRepository.GetOneAsync<Operation_Record>(sqlString, param);

                if (orl != null)
                {
                    sqlString = $@"select * from operation_record_file where record_id = @record_id and deleted = 0";
                    var oParam = new { @record_id = orl.id };
                    var orfl = await backendRepository.GetAllAsync<Operation_Record_File>(sqlString, oParam);
                    orl.lorf = orfl;
                }

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

            return apiResult;
        }
        
        /// <summary>
        /// 維修/保養---新增/編輯
        /// </summary>
        /// <param name="or"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> SavOpeRecord([FromForm] Operation_Record or)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                var sqlString = $@"select * from operation_record where id = @id";
                var param = new { @id = or.id };
                var ori = await backendRepository.GetOneAsync<Operation_Record>(sqlString, param);

                sqlString = $@"select formId from operation_record where convert(created_at, DATE) = convert(NOW(), DATE) order by id desc limit 1";
                var formId = await backendRepository.GetOneAsync<string>(sqlString);
                formId = formId != null ? "op" + DateTime.Now.ToString("yyyyMMdd") + (Int32.Parse(formId.Substring(10)) + 1).ToString().PadLeft(3, '0') : "op" + DateTime.Now.ToString("yyyyMMdd") + "001";

                if (ori == null) //create
                {
                    var new_guid = Guid.NewGuid();
                    Dictionary<string, object> operation_record = new Dictionary<string, object>()
                    {
                        { "@deleted", 0},
                        { "@formId", formId},
                        { "@location", or.location},
                        { "@location_code", or.location_code},
                        { "@device_system_category_layer2", or.device_system_category_layer2},
                        { "@device_system_category_layer3", or.device_system_category_layer3},
                        { "@work_type", or.work_type},
                        { "@error_code", or.error_code},
                        { "@fix_do", or.fix_do},
                        { "@fix_do_code", or.fix_do_code },
                        { "@fix_firm", or.fix_firm},
                        { "@status", or.status},
                        { "@work_person_id", or.work_person_id},
                        { "@start_time", or.start_time},
                        { "@end_time", or.end_time},
                        { "@work_time", or.work_time},
                        { "@finish_time", or.finish_time},
                        { "@notice", or.notice},
                        { "@description", or.description},
                        { "@created_by", myUser.userinfo_guid},
                        { "@created_at", DateTime.Now}
                    };
                    await backendRepository.AddOneByCustomTable(operation_record, "operation_record");

                    if (or.lorf != null)
                    {
                        if (or.lorf.Count > 0)
                    {
                        foreach(var orf in or.lorf)
                        {
                            sqlString = $@"select id from operation_record where formId = @formId";
                            var fParam = new { @formId = formId };
                            var record_id = await backendRepository.GetOneAsync<int>(sqlString, fParam);
                            new_guid = Guid.NewGuid();
                            Dictionary<string, object> operation_record_file = new Dictionary<string, object>()
                            {
                                { "@deleted", 0},
                                { "@record_id", record_id},
                                { "@ori_file_name", orf.ori_file_name},
                                { "@save_file_name", new_guid},
                                { "@created_by", myUser.userinfo_guid},
                                { "@created_at", DateTime.Now}
                            };

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


                            var fileName = new_guid + "." + orf.ori_file_name.Split('.')[1];

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

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

                            await backendRepository.AddOneByCustomTable(operation_record_file, "operation_record_file");
                        }
                    }
                    }

                    apiResult.Data = "新增成功";
                }
                else //edit
                {
                    Dictionary<string, object> operation_record = new Dictionary<string, object>()
                    {
                        { "@location", or.location},
                        { "@location_code", or.location_code},
                        { "@device_system_category_layer2", or.device_system_category_layer2},
                        { "@device_system_category_layer3", or.device_system_category_layer3},
                        { "@error_code", or.error_code},
                        { "@fix_do", or.fix_do},
                        { "@fix_do_code", or.fix_do_code },
                        { "@fix_firm", or.fix_firm},
                        { "@status", or.status},
                        { "@work_person_id", or.work_person_id},
                        { "@start_time", or.start_time},
                        { "@end_time", or.end_time},
                        { "@work_time", or.work_time},
                        { "@finish_time", or.finish_time},
                        { "@notice", or.notice},
                        { "@description", or.description},
                        { "@updated_by", myUser.userinfo_guid},
                        { "@updated_at", DateTime.Now}
                    };
                    await backendRepository.UpdateOneByCustomTable(operation_record , "operation_record", "id = " + or.id + "");

                    if (or.lorf != null)
                    {
                        if (or.lorf.Count > 0)
                    {
                        foreach(var orf in or.lorf)
                        {
                            //刪除原本檔案
                            if (orf.id != 0 && orf.save_file_name != null && orf.ori_file_name != null)
                            {
                                //FolderFunction folderFunction = new FolderFunction();
                                //folderFunction.DeleteFile(Path.Combine(operationFileSaveAsPath, orf.save_file_name));
                                Dictionary<string, object> operation_record_file = new Dictionary<string, object>()
                                {
                                    { "@deleted", 1},
                                };
                                await backendRepository.UpdateOneByCustomTable(operation_record_file, "operation_record_file", "id = " + orf.id + "");
                            }

                            if (orf.ori_file_name != null && orf.file != null) {
                                var new_guid = Guid.NewGuid();
                                Dictionary<string, object> operation_record_file = new Dictionary<string, object>()
                                {
                                    { "@deleted", 0},
                                    { "@record_id", or.id},
                                    { "@ori_file_name", orf.ori_file_name},
                                    { "@save_file_name", new_guid},
                                    { "@created_by", myUser.userinfo_guid},
                                    { "@created_at", DateTime.Now}
                                };

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

                                var fileName = new_guid + "." + orf.ori_file_name.Split('.')[1];

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

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

                                await backendRepository.AddOneByCustomTable(operation_record_file, "operation_record_file");
                            }

                            //if (orf.id == 0)//create
                            //{
                            //    Dictionary<string, object> operation_record_file = new Dictionary<string, object>()
                            //    {
                            //        { "@deleted", 0},
                            //        { "@formId", or.formId},
                            //        { "@ori_file_name", orf.ori_file_name},
                            //        { "@save_file_name", orf.save_file_name},
                            //        { "@created_by", myUser.userinfo_guid},
                            //        { "@created_at", DateTime.Now}
                            //    };

                            //    if (!System.IO.Directory.Exists(operationFileSaveAsPath))
                            //        System.IO.Directory.CreateDirectory(operationFileSaveAsPath);

                            //    var new_guid = Guid.NewGuid();

                            //    var fileName = new_guid + "." + orf.ori_file_name.Split('.')[1];

                            //    var fullPath = Path.Combine(operationFileSaveAsPath, fileName);

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

                            //    await backendRepository.AddOneByCustomTable(operation_record_file, "operation_record_file");
                            //}
                            //else//delete
                            //{
                            //    Dictionary<string, object> operation_record_file = new Dictionary<string, object>()
                            //    {
                            //        { "@deleted", 1},
                            //    };
                            //    await backendRepository.UpdateOneByCustomTable(operation_record_file, "operation_record_file", "id = " + orf.id + "");
                            //}
                        }
                    }
                    }

                    apiResult.Data = "修改成功";
                }

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

            return apiResult;
        }

        /// <summary>
        /// 維修/保養---刪除
        /// </summary>
        /// <param name="or"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> DelOpeRecord([FromBody] Operation_Record or)
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                var sqlString = $@"select formId from operation_record where id = @id";
                var param = new { @id = or.id };
                var formId = await backendRepository.GetOneAsync<string>(sqlString, param);

                sqlString = @$"UPDATE operation_record_file SET deleted = 1 WHERE record_id = @record_id";
                var dParam = new { @record_id = or.id };
                await backendRepository.ExecuteSql(sqlString, dParam);

                sqlString = @$"UPDATE operation_record SET deleted = 1 WHERE id = @id";
                param = new { @id = or.id };
                await backendRepository.ExecuteSql(sqlString, param);

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

            return apiResult;
        }

        /// <summary>
        /// 獲取維修/保養 單號
        /// </summary>
        /// <returns></returns>
        public async Task<ApiResult<string>> GetFormId()
        {
            ApiResult<string> apiResult = new ApiResult<string>();

            try
            {
                var sqlString = $@"select formId from operation_record where convert(created_at, DATE) = convert(NOW(), DATE) order by id desc limit 1";
                var formId = await backendRepository.GetOneAsync<string>(sqlString);
                formId = formId != null ? "op" + DateTime.Now.ToString("yyyyMMdd") + (Int32.Parse(formId.Substring(10)) + 1).ToString().PadLeft(3, '0') : "op" + DateTime.Now.ToString("yyyyMMdd") + "001";

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

            return apiResult;
        }
        #endregion
    }
}