using AMESCoreStudio.CommonTools.Result;
using AMESCoreStudio.Web.Models;
using AMESCoreStudio.Web.ViewModels.PCS;
using AMESCoreStudio.Web.ViewModels.PCB;
using AMESCoreStudio.WebApi.DTO.AMES;
using AMESCoreStudio.WebApi.Enum;
using AMESCoreStudio.WebApi.Models.AMES;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using ClosedXML.Excel;

namespace AMESCoreStudio.Web.Controllers
{
    /// <summary>
    /// PCB管理模組
    /// </summary>
    public class PCBController : Controller
    {
        private readonly ILogger<PCBController> _logger;
        public readonly IPCB _pcbApi;
        private readonly IWebHostEnvironment _env;
        public readonly IPCS _pcsApi;
        public readonly IBLL _bllApi;
        public readonly ISYS _sysApi;
        public PCBController(ILogger<PCBController> logger, IPCB pcbApi, IWebHostEnvironment env, IPCS pcsApi, IBLL bllApi, ISYS sysApi)
        {
            _logger = logger;
            _pcbApi = pcbApi;
            _env = env;
            _pcsApi = pcsApi;
            _bllApi = bllApi;
            _sysApi = sysApi;
        }

        //#region 下拉選單
        /// <summary>
        /// 錫膏狀態
        /// </summary>
        /// <param name="SelectedValue"></param>
        private void GetSolderPasteStatusSelect(string SelectedValue = null)
        {
            List<string> values = new List<string>();
            if (SelectedValue != null)
            {
                values = SelectedValue.Split(',').ToList();
            }
            var q = Enum.GetValues(typeof(EnumPCB.EnumSolderPasteStatus)).Cast<EnumPCB.EnumSolderPasteStatus>()
                       .Select(s => new SelectListItem
                       {
                           Text = EnumPCB.GetDisplayName(s).ToString(),
                           Value = s.ToString()
                       }).ToList();

            ViewBag.GetSolderPasteStatusSelect = q;
        }
        //#endregion

        #region PCB013 鋼板量測紀錄
        public ActionResult PCB013()
        {
            return View();
        }

        public async Task<IActionResult> PCB013QueryAsync(string steelPlateNo, string storageLocation, string item,
                     string date_str, string date_end, string status, string checkOff, int page = 0, int limit = 10)
        {
            if (checkOff == "on")
                checkOff = "Y";

            IResultModel<SteelPlateInfoDto> result = await _pcbApi.GetSteelPlateInfoQuery(steelPlateNo: steelPlateNo, storageLocation: storageLocation,
             item: item, date_str: date_str, date_end: date_end, status: status,
             checkOff: checkOff, page: page, limit: limit);

            if (result.Data.Count() != 0)
            {
                return Json(new Table() { code = 0, msg = "", data = result.Data, count = result.DataTotal });
            }
            return Json(new Table() { count = 0, data = null });
        }

        //新增頁面
        public IActionResult PCB013C()
        {
            return View();
        }

        //修改页面
        [HttpGet]
        public async Task<IActionResult> PCB013U(int id)
        {
            var result = await _pcbApi.GetSteelPlateInfo(id);
            return View(result);
        }

        //頁面提交,id=0 添加,id>0 修改
        [HttpPost]
        public async Task<IActionResult> PCB013Async(SteelPlateInfo model)
        {
            if (ModelState.IsValid)
            {
                model.SteelPlateNo = model.SteelPlateNo.Trim();
                model.Items = model.Items.Trim().ToUpper();

                IResultModel result;
                if (model.SteelPlateID == 0)
                {
                    model.CreateUserID = GetLogInUserID();
                    model.CreateDate = DateTime.Now;
                    model.UpdateUserID = GetLogInUserID();
                    model.UpdateDate = DateTime.Now;
                    result = await _pcbApi.PostSteelPlateInfo(JsonConvert.SerializeObject(model));
                }
                else
                {
                    model.UpdateUserID = GetLogInUserID();
                    model.UpdateDate = DateTime.Now;
                    result = await _pcbApi.PutSteelPlateInfo(JsonConvert.SerializeObject(model));
                }

                if (result.Success)
                {
                    var _msg = model.SteelPlateID == 0 ? "新增成功!" : "修改成功!";
                    return RedirectToAction("Refresh", "Home", new { msg = _msg });
                }
                else
                {

                    ModelState.AddModelError("error", result.Msg);
                }
            }

            if (model.SteelPlateID == 0)
            {
                return View("PCB013C", model);
            }
            return View("PCB013U", model);
        }


        public async Task<IActionResult> PCB013A(int steelPlateID, string steelPlateNo)
        {
            var result = new PCB013ViewModel();
            result.SteelPlateID = steelPlateID;
            result.SteelPlateNo = steelPlateNo;

            var resultSteel = await _pcbApi.GetSteelPlateMeasureBySteelPlateID(steelPlateID);

            var resultSteelInfo = await _pcbApi.GetSteelPlateInfo(result.SteelPlateID);

            if (resultSteelInfo != null)
            {
                result.Items = resultSteelInfo.Items;
            }

            // 鋼板編號沒有量測資料
            if (!resultSteel.Data.Any())
            {
                result.SpMeasureID = 0;
                result.Status = "上線";
            }
            else
            {
                var item = resultSteel.Data.OrderByDescending(o => o.SpMeasureID).FirstOrDefault();

                // 下線資料空白
                if (string.IsNullOrWhiteSpace(item.OffTension1))
                {
                    result.SpMeasureID = item.SpMeasureID;
                    result.Status = "下線";
                }
                else
                {
                    result.SpMeasureID = 0;
                    result.Status = "上線";
                }
            }

            return View(result);
        }

        /// <summary>
        /// 鋼板量測記錄
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> PCB013ASave(PCB013ViewModel model)
        {
            IResultModel result;
            // 量測基準 35 小於通知寄信
            if (double.Parse(model.Tension1) < 35 || double.Parse(model.Tension2) < 35 || double.Parse(model.Tension3) < 35 ||
                double.Parse(model.Tension4) < 35 || double.Parse(model.Tension5) < 35)
            {
                #region 紀錄log及改狀態
                var SteelPlateMeasureNg = new SteelPlateMeasureNg
                {
                    SteelPlateID = model.SteelPlateID,
                    Status = model.Status,
                    Tension1 = model.Tension1,
                    Tension2 = model.Tension2,
                    Tension3 = model.Tension3,
                    Tension4 = model.Tension4,
                    Tension5 = model.Tension5,
                    CreateUserID = GetLogInUserID()
                };
                await _pcbApi.PostSteelPlateMeasureNg(JsonConvert.SerializeObject(SteelPlateMeasureNg));

                var data = new SteelPlateInfo
                {
                    SteelPlateID = model.SteelPlateID,
                    Status = "0",
                    UpdateUserID = GetLogInUserID(),
                };
                await _pcbApi.PutSteelPlateInfoByStatus(JsonConvert.SerializeObject(data));
                #endregion

                #region 寄通知信
                string NgMsg = $"{model.Status}量測";
                if (double.Parse(model.Tension1) < 35)
                    NgMsg += $"第一點量測值({model.Tension1})、";
                if (double.Parse(model.Tension2) < 35)
                    NgMsg += $"第二點量測值({model.Tension2})、";
                if (double.Parse(model.Tension3) < 35)
                    NgMsg += $"第三點量測值({model.Tension3})、";
                if (double.Parse(model.Tension4) < 35)
                    NgMsg += $"第四點量測值({model.Tension4})、";
                if (double.Parse(model.Tension5) < 35)
                    NgMsg += $"第五點量測值({model.Tension5})、";

                NgMsg = NgMsg.Substring(0, NgMsg.Length - 1) + "小於告警值";

                string MailGroup = "STEEL_ALARM";
                string Subject = $"[AMES系統通知] 鋼板量測值告警通知";
                string Body = $"鋼板編號:{model.SteelPlateNo}<br/>" +
                              $"量測日期[{DateTime.Now:yyyy/MM/dd}]<br/>" +
                              $"量測時間[{DateTime.Now:HH:mm:ss}]<br/>" +
                              $"量測人員[{await GetUserName()}]<br/>{NgMsg}";

                await _bllApi.PostToMail(Subject, Body, string.Join(',', MailGroup), "");


                WipAlarm wipAlarm = new WipAlarm();
                wipAlarm.AlarmTypeID = (int)EnumWipAlarm.EnumTypeId.SteelPlateNg;
                wipAlarm.WipNO = model.SteelPlateNo;
                wipAlarm.AlarmParam = model.Status;
                wipAlarm.AlarmValue = "1";
                wipAlarm.AlarmDesc = Subject;
                wipAlarm.AlarmDateTime = DateTime.Now;
                await _pcbApi.PostWipAlarm(JsonConvert.SerializeObject(wipAlarm));
                #endregion

                return RedirectToAction("Refresh", "Home", new { msg = "量測張力低於基準35,不做紀錄" });
            }
            else
            {
                var data = new SteelPlateMeasure();
                // 新增一筆 上線
                if (model.SpMeasureID == 0)
                {
                    data.SteelPlateID = model.SteelPlateID;
                    data.OnTension1 = model.Tension1;
                    data.OnTension2 = model.Tension2;
                    data.OnTension3 = model.Tension3;
                    data.OnTension4 = model.Tension4;
                    data.OnTension5 = model.Tension5;
                    data.OnUserID = GetLogInUserID();
                    data.OnDate = DateTime.Now;

                    result = await _pcbApi.PostSteelPlateMeasure(JsonConvert.SerializeObject(data));
                }
                // 更新一筆 下線
                else
                {
                    data.SpMeasureID = model.SpMeasureID;
                    data.SteelPlateID = model.SteelPlateID;
                    data.OffTension1 = model.Tension1;
                    data.OffTension2 = model.Tension2;
                    data.OffTension3 = model.Tension3;
                    data.OffTension4 = model.Tension4;
                    data.OffTension5 = model.Tension5;
                    data.OffUserID = GetLogInUserID();
                    data.OffDate = DateTime.Now;

                    result = await _pcbApi.PutSteelPlateMeasure(JsonConvert.SerializeObject(data));
                }

                if (result.Success)
                {
                    var _msg = "新增量測記錄成功!";
                    return RedirectToAction("Refresh", "Home", new { msg = _msg });
                }
                else
                {
                    ModelState.AddModelError("error", result.Msg);
                }
            }

            return View("PCB013A", model);
        }

        /// <summary>
        /// 鋼板量測紀錄 View
        /// </summary>
        /// <param name="steelPlateID"></param>
        /// <param name="steelPlateNo"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult PCB013V(int steelPlateID, string steelPlateNo)
        {
            ViewBag.steelPlateID = steelPlateID;
            ViewBag.steelPlateNo = steelPlateNo;
            return View();
        }

        [HttpGet]
        public IActionResult PCB016()
        {
            return View();
        }

        public async Task<IActionResult> PCB016QueryAsync(string steelPlateNo, string storageLocation, string item,
                    string date_str, string date_end, string wipNo, string checkOff, int page = 0, int limit = 10)
        {
            IResultModel<PCB016ViewDto> result;
            if (checkOff == "on")
            {
                result = await _pcbApi.GetSteelPlateInfoReportByUnused(steelPlateNo: steelPlateNo, storageLocation: storageLocation,
                                 item: item, date_str: date_str, date_end: date_end, wipNo: wipNo, page: page, limit: limit);

            }
            else
            {
                result = await _pcbApi.GetSteelPlateInfoReport(steelPlateNo: steelPlateNo, storageLocation: storageLocation,
                                item: item, date_str: date_str, date_end: date_end, wipNo: wipNo, page: page, limit: limit);
            }

            if (result.Data.Count() != 0)
            {
                return Json(new Table() { code = 0, msg = "", data = result.Data, count = result.DataTotal });
            }
            return Json(new Table() { count = 0, data = null });
        }


        [HttpGet]
        public async Task<IActionResult> PCB013VQuery(int steelPlateID, string steelPlateNo, int page = 0, int limit = 10)
        {
            var result = await _pcbApi.GetSteelPlateMeasureBySteelPlateID(steelPlateID, page, limit);

            if (result.DataTotal > 0)
            {
                return Json(new Table() { code = 0, msg = "", data = result.Data, count = result.DataTotal });
            }

            return Json(new Table() { count = 0, data = null });
        }
        #endregion

        #region PCB014 錫膏使用管控
        public ActionResult PCB014()
        {
            GetSolderPasteStatusSelect();
            return View();
        }

        public async Task<IActionResult> PCB014QueryAsync(string solderPasteNo, string description, string vendor, string status = "WI", int page = 0, int limit = 10)
        {
            IResultModel<SolderPasteInfoDto> result = await _pcbApi.GetSolderPasteInfoQuery(solderPasteNo: solderPasteNo,
                description: description, vendor: vendor, status: status, page: page, limit: limit);

            if (result.Data.Count() != 0)
            {
                return Json(new Table() { code = 0, msg = "", data = result.Data, count = result.DataTotal });
            }
            return Json(new Table() { count = 0, data = null });
        }

        //新增頁面
        public IActionResult PCB014C()
        {
            return View();
        }

        //修改页面
        [HttpGet]
        public async Task<IActionResult> PCB014U(int id)
        {
            var result = await _pcbApi.GetSolderPasteInfo(id);
            return View(result);
        }

        /// <summary>
        /// 頁面提交,id=0 添加,id>0 修改 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="numbergeneration">編碼生成</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> PCB014Async(SolderPasteInfo model, string numbergeneration, int qty = 1)
        {
            var msg = string.Empty;
            // 日期判斷
            if (model.EffectiveDate < model.ManufactoringDate)
            {
                msg = "有效日期不能小於製造日期";
                ModelState.AddModelError("error", "有效日期不能小於製造日期");
            }
            else if (ModelState.IsValid)
            {
                IResultModel result;

                // 新增
                if (model.SolderPasteID == 0)
                {

                    // 錫膏編號自動編碼
                    if (numbergeneration == "A")
                    {
                        // 用規格帶出流水碼
                        model.SolderPasteNo = await _pcbApi.GetSolderPasteSerialByAutoSerialNo(model.Description.Trim());
                        if (string.IsNullOrWhiteSpace(model.SolderPasteNo))
                        {
                            msg = "找不到規格對應的代碼";
                        }

                        // 判斷數量是否正確
                        if (qty < 1 || qty > 100)
                        {
                            msg = "數量只能在1 ~ 100";
                        }

                        // 有錯誤訊息
                        if (!string.IsNullOrWhiteSpace(msg))
                        {
                            ModelState.AddModelError("error", msg);
                            return Json(new { msg = msg, success = false });
                            //return View("PCB014C", model);
                        }
                    }
                    // 人工手動給予
                    else if (numbergeneration == "M")
                    {

                        if (string.IsNullOrWhiteSpace(model.SolderPasteNo))
                            msg = "請輸入錫膏編號";
                        else
                        {
                            List<SolderPasteSerial> solderPasteSerials = await _pcbApi.GetSolderPasteSerial();
                            // 目前有設定的代號
                            var serialNo = solderPasteSerials.Select(s => s.SerialNo).ToList();

                            if (serialNo.Any(code => model.SolderPasteNo.StartsWith(code)))
                            {
                                msg = "不可以輸入系統指定代碼";
                            }

                            var query = await _pcbApi.GetSolderPasteInfoQuery(solderPasteNo: model.SolderPasteNo);
                            // 錫膏編號重複
                            if (query.DataTotal != 0)
                                msg = "該錫膏編號已建立過";
                        }

                        // 有錯誤訊息
                        if (!string.IsNullOrWhiteSpace(msg))
                        {
                            ModelState.AddModelError("error", msg);
                            return Json(new { msg = msg, success = false });
                            //return View("PCB014C", model);
                        }
                    }


                    model.CreateUserID = GetLogInUserID();
                    model.CreateDate = DateTime.Now;
                    model.UpdateUserID = GetLogInUserID();
                    model.UpdateDate = DateTime.Now;
                    result = await _pcbApi.PostSolderPasteInfo(JsonConvert.SerializeObject(model));
                    // 自動取號 && 數量不等於 1跑迴圈
                    if (qty != 1 && numbergeneration == "A")
                    {
                        for (int i = 1; i < qty; i++)
                        {
                            model.SolderPasteNo = await _pcbApi.GetSolderPasteSerialByAutoSerialNo(model.Description.Trim());
                            model.CreateUserID = GetLogInUserID();
                            model.CreateDate = DateTime.Now;
                            model.UpdateUserID = GetLogInUserID();
                            model.UpdateDate = DateTime.Now;
                            result = await _pcbApi.PostSolderPasteInfo(JsonConvert.SerializeObject(model));
                        }
                    }
                }
                else
                {
                    model.UpdateUserID = GetLogInUserID();
                    model.UpdateDate = DateTime.Now;
                    result = await _pcbApi.PutSolderPasteInfo(JsonConvert.SerializeObject(model));
                }

                if (result.Success)
                {
                    var _msg = model.SolderPasteID == 0 ? "新增成功!" : "修改成功!";
                    if (model.SolderPasteID == 0)
                        return Json(new { msg = "新增成功!", success = true });
                    else
                        return RedirectToAction("Refresh", "Home", new { msg = _msg });
                }
                else
                {
                    msg = result.Msg;
                    ModelState.AddModelError("error", result.Msg);
                }
            }

            if (model.SolderPasteID == 0)
            {
                return Json(new { msg = msg, success = false });
                //return View("PCB014C", model);
            }
            return View("PCB014U", model);
        }

        /// <summary>
        /// PCB014 錫膏刪除
        /// </summary>
        /// <param name="id">錫膏ID</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> PCB014D(int id)
        {
            var result = await _pcbApi.DeleteSolderPasteInfo(id);
            if (result.Success)
                return Json(new Result() { success = true, msg = "刪除成功" });
            else
                return Json(new Result() { success = false, msg = "刪除失敗" });
        }

        [HttpGet]
        public IActionResult PCB017()
        {
            return View();
        }

        /// <summary>
        /// 錫膏管制查詢
        /// </summary>
        /// <param name="solderPasteNo">錫膏編號</param>
        /// <param name="status">狀態</param>
        /// <param name="wipNo">工單號碼</param>
        /// <param name="strDate">開始_收貨時間</param>
        /// <param name="endDate">結束_收貨時間</param>
        /// <param name="page">頁數</param>
        /// <param name="limit">筆數</param>
        /// <returns></returns>
        public async Task<IActionResult> PCB017QueryAsync(string solderPasteNo, string wipNo,
            string strDate, string endDate, string status, int page = 0, int limit = 10)
        {
            IResultModel<PCB017ViewDto> result = await _pcbApi.GetSolderPasteInfoReport(solderPasteNo: solderPasteNo, status: status,
             strDate: strDate, endDate: endDate, wipNo: wipNo, page: page, limit: limit);

            if (result.Data.Count() != 0)
            {
                return Json(new Table() { code = 0, msg = "", data = result.Data, count = result.DataTotal });
            }
            return Json(new Table() { count = 0, data = null });
        }

        /// <summary>
        /// 錫膏管制作業-新增
        /// </summary>
        /// <returns></returns>
        public IActionResult PCB017C()
        {
            PCB017ViewModel model = new PCB017ViewModel();
            return View(model);
        }

        /// <summary>
        /// 錫膏管制作業-新增 
        /// </summary>
        /// <param name="solderPasteNo">錫膏編號</param>
        /// <param name="status">狀態(I=入冰箱 ; O=出冰箱 ; C=使用完 ; X=報廢)</param>
        /// <param name="qty">數量</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> PCB017Async(PCB017ViewModel model)
        {
            List<SolderPasteSerial> solderPasteSerials = await _pcbApi.GetSolderPasteSerial();
            // 目前有設定的代號
            var serialNo = solderPasteSerials.Select(s => s.SerialNo).ToList();

            if (string.IsNullOrEmpty(model.solderPasteNo))
            {
                ModelState.AddModelError("error", "請輸入錫膏編號");
                return View("PCB017C", model);
            }

            if (model.qty == null && model.status == "I")
            {
                ModelState.AddModelError("error", "請輸入錫膏入冰箱數量");
                return View("PCB017C", model);
            }
            // 狀態為入冰箱 => 找倉庫-出冰箱
            // 狀態為出冰箱 => 找入冰箱  
            // 狀態為使用完 => 找開封中
            var selectStatus = model.status == "I" ? "WO" :
                               model.status == "O" ? "I" :
                               model.status == "C" ? "U" : model.status;
            var query = await _pcbApi.GetSolderPasteInfoByStatus(selectStatus);

            List<SolderPasteRecord> solderPasteRecords = new List<SolderPasteRecord>();

            switch (model.status)
            {
                case "I": // 入冰箱
                    // 判斷是否有序號且未使用
                    if (query.Where(w => w.SolderPasteNo == model.solderPasteNo).Any())
                    {
                        var Sn = model.solderPasteNo.Substring(0, 2);
                        var queryByNo = query.Where(w => w.SolderPasteNo.StartsWith(Sn)).ToList();
                        if (model.qty > queryByNo.Count())
                        {
                            ModelState.AddModelError("error", "目前能入冰箱錫膏數量不足,請確認");
                            return View("PCB017C", model);
                        }

                        foreach (var item in queryByNo.OrderBy(o => o.SolderPasteNo).Take(int.Parse(model.qty.ToString())))
                        {
                            solderPasteRecords.Add(new SolderPasteRecord
                            {
                                SolderPasteID = item.SolderPasteID,
                                Status = model.status,
                                CreateUserID = GetLogInUserID(),
                                CreateDate = DateTime.Now
                            });
                        }
                    }
                    else
                    {
                        ModelState.AddModelError("error", "找不到該筆錫膏編號是 倉庫-出冰箱 狀態,請確認");
                        return View("PCB017C", model);
                    }
                    break;
                case "O": // 出冰箱
                    // 判斷是否有序號且已入冰箱
                    if (query.Where(w => w.SolderPasteNo == model.solderPasteNo).Any())
                    {
                        var Sn = model.solderPasteNo.Substring(0, 2);
                        var queryByNo = query.Where(w => w.SolderPasteNo.StartsWith(Sn)).ToList();
                        var first = queryByNo.OrderBy(o => o.UpdateDate).ThenBy(o => o.SolderPasteNo).FirstOrDefault();
                        if (model.solderPasteNo != first.SolderPasteNo)
                        {
                            ModelState.AddModelError("error", "該筆錫膏編號順序不正確,請確認");
                            return View("PCB017C", model);
                        }

                        solderPasteRecords.Add(new SolderPasteRecord
                        {
                            SolderPasteID = first.SolderPasteID,
                            Status = model.status,
                            CreateUserID = GetLogInUserID(),
                            CreateDate = DateTime.Now
                        });
                    }
                    else
                    {
                        ModelState.AddModelError("error", "找不到該筆錫膏編號是入冰箱狀態,請確認");
                        return View("PCB017C", model);
                    }
                    break;
                case "C": // 使用完
                          // 判斷是否有序號且已開封
                    if (query.Where(w => w.SolderPasteNo == model.solderPasteNo).Any())
                    {
                        var first = query.Where(w => w.SolderPasteNo == model.solderPasteNo).FirstOrDefault();
                        solderPasteRecords.Add(new SolderPasteRecord
                        {
                            SolderPasteID = first.SolderPasteID,
                            Status = model.status,
                            CreateUserID = GetLogInUserID(),
                            CreateDate = DateTime.Now
                        });
                    }
                    else
                    {
                        ModelState.AddModelError("error", "找不到該筆錫膏編號是開封狀態,請確認");
                        return View("PCB017C", model);
                    }
                    break;
                case "X": // 報廢
                    if (query.Where(w => w.SolderPasteNo == model.solderPasteNo).Any())
                    {
                        var first = query.Where(w => w.SolderPasteNo == model.solderPasteNo).FirstOrDefault();
                        solderPasteRecords.Add(new SolderPasteRecord
                        {
                            SolderPasteID = first.SolderPasteID,
                            Status = model.status,
                            CreateUserID = GetLogInUserID(),
                            CreateDate = DateTime.Now
                        });
                    }
                    else
                    {
                        ModelState.AddModelError("error", "找不到該筆錫膏編號可報廢狀態,請確認");
                        return View("PCB017C", model);
                    }
                    break;
            }

            var aa = await _pcbApi.PostSolderPasteRecord(JsonConvert.SerializeObject(solderPasteRecords));
            return RedirectToAction("Refresh", "Home", new { msg = "新增成功!" });
        }

        [HttpGet]
        public IActionResult PCB018()
        {
            return View();
        }

        /// <summary>
        /// 錫膏報表查詢
        /// </summary>
        /// <param name="solderPasteNo">錫膏編號</param>
        /// <param name="wipNo">工單號碼</param>
        /// <param name="page">頁數</param>
        /// <param name="limit">筆數</param>
        /// <returns></returns>
        public async Task<IActionResult> PCB018QueryAsync(string solderPasteNo, string wipNo, int page = 0, int limit = 10)
        {
            IResultModel<PCB017ViewDto> result = await _pcbApi.GetSolderPasteInfoReport(solderPasteNo: solderPasteNo,
             wipNo: wipNo, page: page, limit: limit);

            if (result.Data.Count() != 0)
            {
                return Json(new Table() { code = 0, msg = "", data = result.Data, count = result.DataTotal });
            }
            return Json(new Table() { count = 0, data = null });
        }

        /// <summary>
        /// 倉庫錫膏管控
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult PCB019()
        {
            return View();
        }

        /// <summary>
        /// 倉庫錫膏管控查詢
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> PCB019QueryAsync()
        {
            IResultModel<dynamic> result = await _pcbApi.GetSolderPasteInfoReportByWareHouse();
            if (result.Data.Count() != 0)
            {
                return Json(new Table() { code = 0, msg = "", data = result.Data, count = result.DataTotal });
            }
            return Json(new Table() { count = 0, data = null });
        }

        /// <summary>
        /// 倉庫錫膏管制作業-新增
        /// </summary>
        /// <returns></returns>
        public IActionResult PCB019C()
        {
            PCB017ViewModel model = new PCB017ViewModel();
            return View(model);
        }

        /// <summary>
        /// 倉庫錫膏管制作業-新增 
        /// </summary>
        /// <param name="solderPasteNo">錫膏編號</param>
        /// <param name="qty">數量</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> PCB019Async(PCB017ViewModel model)
        {
            List<SolderPasteSerial> solderPasteSerials = await _pcbApi.GetSolderPasteSerial();
            // 目前有設定的代號
            var serialNo = solderPasteSerials.Select(s => s.SerialNo).ToList();

            if (string.IsNullOrEmpty(model.solderPasteNo))
            {
                ModelState.AddModelError("error", "請輸入錫膏編號");
                return View("PCB019C", model);
            }

            if (model.qty == null)
            {
                ModelState.AddModelError("error", "請輸入錫膏出冰箱數量");
                return View("PCB019C", model);
            }

            // 狀態為倉庫-入冰箱
            var query = await _pcbApi.GetSolderPasteInfoByStatus("WI");
            var minSolderPasteNo = string.Empty;
            List<SolderPasteRecord> solderPasteRecords = new List<SolderPasteRecord>();

            // 判斷是否有序號且未使用
            if (query.Where(w => w.SolderPasteNo == model.solderPasteNo).Any())
            {
                var Sn = model.solderPasteNo.Substring(0, 2);
                var queryByNo = query.Where(w => w.SolderPasteNo.StartsWith(Sn)).ToList();
                if (model.qty > queryByNo.Count())
                {
                    ModelState.AddModelError("error", "目前能入冰箱錫膏數量不足,請確認");
                    return View("PCB019C", model);
                }

                foreach (var item in queryByNo.OrderBy(o => o.SolderPasteNo).Take(int.Parse(model.qty.ToString())))
                {
                    if (string.IsNullOrWhiteSpace(minSolderPasteNo))
                        minSolderPasteNo = item.SolderPasteNo;
                    solderPasteRecords.Add(new SolderPasteRecord
                    {
                        SolderPasteID = item.SolderPasteID,
                        Status = "WO",
                        CreateUserID = GetLogInUserID(),
                        CreateDate = DateTime.Now
                    });
                }
            }
            else
            {
                ModelState.AddModelError("error", "找不到該筆錫膏編號是 倉庫-入冰箱 狀態,請確認");
                return View("PCB019C", model);
            }

            var aa = await _pcbApi.PostSolderPasteRecord(JsonConvert.SerializeObject(solderPasteRecords));
            return RedirectToAction("Refresh", "Home", new { msg = $"新增成功!從錫膏編號【{minSolderPasteNo}】開始,出冰箱數{model.qty}" });
        }

        #endregion

        #region PCB015連板綁定作業

        public async Task<IActionResult> PCB015()
        {

            return View();
        }

        public async Task<IActionResult> PCB015V(int WipID)
        {

            WipDataViewModel model = new WipDataViewModel();
            var q = await _pcsApi.GetWipInfo(WipID);
            if (q.Count != 0)
            {
                model.wipInfo = q.FirstOrDefault();
                model.wipAtt = await _pcsApi.GetWipAtt(model.wipInfo.WipNO);
                model.wipBarcodes = await _pcsApi.GetWipBarcode(model.wipInfo.WipNO);
                model.wipBarcode = model.wipBarcodes.FirstOrDefault();
                model.ruleStations = await _pcsApi.GetRuleStationByWipNo(model.wipInfo.WipNO, model.wipInfo.FlowRuleID);

            }

            return View("PCB015V", model);
        }


        public async Task<IActionResult> PCB015GetGroupAsync(string id, string groupID = null, int page = 0, int limit = 10)
        {
            var result = await _pcbApi.GetBarcodeGroupsByWipNO(id: id, groupID: groupID, page: page, limit: limit);
            //groupID = '' 抓全部
            //groupID = 0 不抓資料

            if (result.Data.Count() != 0)
            {
                return Json(new Table() { code = 0, msg = "", data = result.Data, count = result.DataTotal });
            }
            return Json(new Table() { count = 0, data = null });
        }
        public async Task<IActionResult> GetWipInfoAsync(string id, string unit_No)
        {

            var result = await _pcsApi.GetWipAtt(id);
            if (result != null)
            {
                var result1 = await _pcsApi.GetWipInfoByWipNO(id);
                var GroupData = await _pcbApi.GetBarcodeGroupsByWipNO(id, "");
                string GroupQTY = GroupData.DataTotal.ToString();

                result.Side = result1.Where(w => w.UnitNO == unit_No).Select(s => s.WipID).FirstOrDefault();
                result.CPN = GroupQTY + "/" + result1.Where(w => w.UnitNO == unit_No).Select(s => s.PlanQTY).FirstOrDefault().ToString();
                result.PBType = result1.Where(w => w.UnitNO == unit_No).Select(s => s.PlanQTY).FirstOrDefault().ToString();

                if (result != null)
                {
                    return Json(new Result() { success = true, msg = "", data = result });
                    // return Json(new Table() { code = 0, msg = "", data = result, count = 1 });
                }
            }

            // return Json(new Table() { count = 0, msg = "查無工單資料", data = null });
            return Json(new Result() { success = false, msg = "查無工單資料", data = null });
        }

        /// <summary>
        /// 刪除連板群組
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<IActionResult> PCB015DAsync(int id)
        {
            var result = await _pcsApi.DeleteBarcodeGroupByGroupID(id);
            return Json(new Result() { success = true, msg = "刪除成功" });
        }


        public async Task<IActionResult> CheckBarcodeNOandGroupAsync(string BarcodeNo, string WipNo, int WipID, int Boards, string PlanQTY)
        {
            //生產序號不在工單區間
            var WipBarcode = await _pcbApi.GetWipBarcodesCheckInRange(WipNo, BarcodeNo);
            int snLen = PlanQTY.Length;
            if (snLen < 4) snLen = 4;
            if (WipBarcode.Count > 0)
            {
                #region 取區間內最大號
                int Maxnumber = 0;
                string WipBarcodeEnd = WipBarcode.Select(s => s.EndNO).LastOrDefault();
                if (WipBarcodeEnd.Length < 4)
                {
                    return Json(new Result() { success = false, msg = "生產序號區間長度不可小於4", data = WipBarcodeEnd });
                }
                bool conversionSuccessful = int.TryParse(WipBarcodeEnd.Substring(WipBarcodeEnd.Length - snLen, snLen), out Maxnumber);
                if (!conversionSuccessful)
                {

                    return Json(new Result() { success = false, msg = "生產序號區間未" + snLen.ToString() + "碼不為數字", data = WipBarcodeEnd });
                }
                #endregion

                #region 依連板展開序號
                //此段在展開序號可判斷是否已超出結束序號,若有超出則乎略
                List<string> serialNumbers = Enumerable.Range(0, Boards)
               .Select(i =>
               {
                   string newSerialNumber = $"{BarcodeNo.Substring(0, BarcodeNo.Length - snLen)}{(int.Parse(BarcodeNo.Substring(BarcodeNo.Length - snLen)) + i).ToString().PadLeft(snLen, '0')}";
                   return newSerialNumber;
               })
               .TakeWhile(serialNumber => int.Parse(serialNumber.Substring(serialNumber.Length - snLen)) <= Maxnumber)
               .ToList();


                #endregion

                if (serialNumbers.Count() > 0)
                {

                    #region  判斷展開的序號是否已綁Group & 產生BarcodeInfo 
                    foreach (var item in serialNumbers)
                    {
                        var BarCodeinto = await _pcsApi.GetBarcodeInfoesByNo(item);
                        if (BarCodeinto.Count() > 0)
                        {
                            var BarcodeGroup = await _pcsApi.GetBarcodeGroupByBarCodeID(BarCodeinto.Select(s => s.BarcodeID).FirstOrDefault());
                            if (BarcodeGroup.Count() > 0)
                            {
                                return Json(new Result() { success = false, msg = "生產序號" + item + "已綁定群組" + BarcodeGroup.Select(s => s.GroupID).FirstOrDefault() + ",不可重覆綁定", data = null });
                            }
                        }
                        else
                        {
                            var barcodeInfo = new BarcodeInfo
                            {
                                BarcodeNo = item,
                                StationID = -1,
                                LocationID = -1,
                                WipID = -1,
                                RuleStatus = "P",
                                StatusID = -1,
                                SysType = "S",
                                StatusNo = "-1",
                                CreateUserID = GetLogInUserID()
                            };

                            var PostResult = await _pcsApi.PostBarcodeInfoes(JsonConvert.SerializeObject(barcodeInfo));

                        }
                    }
                    #endregion

                    #region 綁定Group

                    var barcodeinfo = await _pcbApi.PostDapperByListBarcodeNO(JsonConvert.SerializeObject(serialNumbers));
                    int UserID = GetLogInUserID();

                    List<BarcodeGroup> barcodeGroups = barcodeinfo
                    .Select((b, index) => new BarcodeGroup
                    {
                        BarcodeID = b.BarcodeID,
                        GroupID = 0,
                        Sequence = index + 1,
                        CreateUserID = UserID,
                        WipNo = WipNo
                    })
                    .ToList();

                    var BarCodeGroup = await _pcbApi.PostBarcodeGroupList(JsonConvert.SerializeObject(barcodeGroups));

                    return Json(new Result() { success = true, msg = "綁定成功", data = BarCodeGroup.Data.Select(s => s.GroupID).FirstOrDefault() });

                    #endregion
                }
                else
                {
                    return Json(new Result() { success = false, msg = "無生產序號可綁定", data = null });
                }

            }
            return Json(new Result() { success = false, msg = "生產序號不在工單區間內", data = null });


        }



        /// <summary>
        /// PCBGroup 綁定Excel匯入
        /// </summary>
        /// <param name="Uploader"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<JsonResult> PCB015ExcelUpload(IFormFile Uploader)
        {
           
            //通過上傳檔案流初始化Mapper
            using (var workbook = new XLWorkbook(Uploader.OpenReadStream()))
            {
                try
                {
                    List<BarcodeGroupDto> barcodeGroup = new List<BarcodeGroupDto>();
                   
                    string Msg = string.Empty;
                    var worksheet = workbook.Worksheet(1);
                    // 定義資料起始/結束 Cell
                    var firstCell = worksheet.FirstCellUsed();
                    var lastCell = worksheet.LastCellUsed();

                    // 使用資料起始/結束 Cell,來定義出一個資料範圍
                    var data = worksheet.Range(firstCell.Address, lastCell.Address);
                    var rowCount = data.RowCount();
                    var columnCount = data.ColumnCount();
                    for (int i = 2; i <= rowCount; i++)
                    {
                        string seq = data.Cell(i, 2).Value.ToString();
                        int sequence;
                        bool isNumeric = int.TryParse(seq, out sequence);

                        if (!isNumeric)
                        {
                            return Json(new Result() { success = false, msg = "Group順序" + seq + "請輸入數字", data = null });
                           
                        }

                        barcodeGroup.Add(new BarcodeGroupDto
                        {
                            WipNo = data.Cell(i, 1).Value.ToString(),
                            Sequence = int.Parse(data.Cell(i, 2).Value.ToString()),
                            BarcodeNo = data.Cell(i, 3).Value.ToString(),
                        });


                        #region 判斷序號是否在工單區間內
                        var WipBarcode = await _pcbApi.GetWipBarcodesCheckInRange(data.Cell(i, 1).Value.ToString(), data.Cell(i, 3).Value.ToString());
                        if (WipBarcode.Count == 0)
                        {
                            return Json(new Result() { success = false, msg = "生產序號" + data.Cell(i, 3).Value.ToString() + "不在工單"+ data.Cell(i, 1).Value.ToString() + "區間內", data = null });
                        }
                        #endregion

                        #region 判斷序號在Excel中是否重覆
                        var duplicateBarcodeNos = barcodeGroup.GroupBy(x => x.BarcodeNo)
                                      .Where(group => group.Count() > 1)
                                      .Select(group => group.Key);
                        if (duplicateBarcodeNos.Any())
                        {

                            return Json(new Result() { success = false, msg = "Excel檔案內的生產序號"+ string.Join(", ", duplicateBarcodeNos) + "重覆", data = null });
                        }
                            #endregion
                            #region 判斷序號是否已綁定群組

                            var BarCodeinto = await _pcsApi.GetBarcodeInfoesByNo(data.Cell(i, 3).Value.ToString());
                        if (BarCodeinto.Count() > 0)
                        {
                            var BarcodeGroup = await _pcsApi.GetBarcodeGroupByBarCodeID(BarCodeinto.Select(s => s.BarcodeID).FirstOrDefault());
                            if (BarcodeGroup.Count() > 0)
                            {
                                return Json(new Result() { success = false, msg = "生產序號" + data.Cell(i, 3).Value.ToString()+ "已綁定群組" + BarcodeGroup.Select(s => s.GroupID).FirstOrDefault() + ",不可重覆綁定", data = null });
                            }
                        }


                        #endregion
                    }
                    #region 檢查工單是否全部一致
                    if (barcodeGroup.Select(s => s.WipNo).Distinct().Count() != 1)
                    {
                        return Json(new Result() { success = false, msg = "Excel檔案內的工單不一致不可匯入", data = null });

                    }
                    #endregion



                    foreach (var item in barcodeGroup.Select(s =>s.Sequence).Distinct())
                    {
                        foreach (var item1 in barcodeGroup.Where(w => w.Sequence == item))
                        {

                            #region  產生BarcodeInfo 
                            var barcodeInfo = new BarcodeInfo
                            {
                                BarcodeNo = item1.BarcodeNo,
                                StationID = -1,
                                LocationID = -1,
                                WipID = -1,
                                RuleStatus = "P",
                                StatusID = -1,
                                SysType = "S",
                                StatusNo = "-1",
                                CreateUserID = GetLogInUserID()
                            };

                            var PostResult = await _pcsApi.PostBarcodeInfoes(JsonConvert.SerializeObject(barcodeInfo));

                            #endregion
                        }
                            #region 綁定Group

                            var barcodeinfo = await _pcbApi.PostDapperByListBarcodeNO(JsonConvert.SerializeObject(barcodeGroup.Where(w => w.Sequence == item).Select(s=>s.BarcodeNo)));
                            int UserID = GetLogInUserID();

                            List<BarcodeGroup> barcodeGroups = barcodeinfo
                            .Select((b, index) => new BarcodeGroup
                            {
                                BarcodeID = b.BarcodeID,
                                GroupID = 0,
                                Sequence = item,
                                CreateUserID = UserID,
                                WipNo = barcodeGroup.Select(s=>s.WipNo).FirstOrDefault()
                            })
                            .ToList();

                            var BarCodeGroup = await _pcbApi.PostBarcodeGroupList(JsonConvert.SerializeObject(barcodeGroups));

                           
                            #endregion
                        

                    }

                    return Json(new Result() { success = true, msg = "綁定成功", data = null });


                }
                catch (Exception ex)
                {
                    return Json(new { data = ex.Message, success = false });
                }
            }

            

                //将資料Json化并传到前台视图
             return Json(new { data = "", success = true });
            
        }


        #endregion


        /// <summary>
        /// 登入UserID
        /// </summary>
        /// <returns></returns>
        public int GetLogInUserID()
        {
            int user_id = -1;
            HttpContext.Request.Cookies.TryGetValue("UserID", out string userID);

            if (userID != null)
            {
                if (int.Parse(userID.ToString()) >= 0)
                {
                    user_id = int.Parse(userID.ToString());
                }
            }
            return user_id;
        }

        /// <summary>
        /// 登入User名稱
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<string> GetUserName()
        {
            int userId = GetLogInUserID();

            var user = await _sysApi.GetUserInfo(userId);
            if (!user.Any())
                return "";
            else
                return user.FirstOrDefault().UserName;
        }
    }
}