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;

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>
        /// SOP_Type
        /// </summary>
        /// <param name="SelectedValue"></param>
        private void GetSteelPlateStatusSelect(string SelectedValue = null)
        {
            List<string> values = new List<string>();
            if (SelectedValue != null)
            {
                values = SelectedValue.Split(',').ToList();
            }
            var q = Enum.GetValues(typeof(EnumPCB.EnumSteelPlateStatus)).Cast<EnumPCB.EnumSteelPlateStatus>()
                       .Select(s => new SelectListItem
                       {
                           Text = EnumPCB.GetDisplayName(s).ToString(),
                           Value = s.ToString()
                       }).ToList();

            ViewBag.GetSteelPlateStatusSelect = 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 side, 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, side: side, 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();

                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);

            // 鋼板編號沒有量測資料
            if (resultSteel.Data.Count() == 0)
            {
                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, int page = 0, int limit = 10)
        {

            IResultModel<PCB016ViewDto> 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()
        {
            return View();
        }

        public async Task<IActionResult> PCB014QueryAsync(string solderPasteNo, string status, int page = 0, int limit = 10)
        {
            IResultModel<SolderPasteInfoDto> result = await _pcbApi.GetSolderPasteInfoQuery(solderPasteNo: solderPasteNo, 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);
        }

        //頁面提交,id=0 添加,id>0 修改
        [HttpPost]
        public async Task<IActionResult> PCB014Async(SolderPasteInfo model)
        {
            // 日期判斷
            if (model.EffectiveDate < model.ManufactoringDate)
            {
                ModelState.AddModelError("error", "有效日期不能小於製造日期");
            }
            else if (ModelState.IsValid)
            {
                IResultModel result;

                if (model.SolderPasteID == 0)
                {
                    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 ? "新增成功!" : "修改成功!";
                    return RedirectToAction("Refresh", "Home", new { msg = _msg });
                }
                else
                {
                    ModelState.AddModelError("error", result.Msg);
                }
            }


            if (model.SolderPasteID == 0)
            {
                return View("PCB014C", model);
            }
            return View("PCB014U", model);
        }
        #endregion

        #region PCB015連板綁定作業

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

            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 });


        }
        #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;
        }
    }
}