using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using AMESCoreStudio.WebApi;
using AMESCoreStudio.WebApi.Models.AMES;
using AMESCoreStudio.CommonTools.Result;
using Dapper;
using AMESCoreStudio.WebApi.Extensions;

namespace AMESCoreStudio.WebApi.Controllers.AMES
{
    /// <summary>
    /// 條碼過站資料檔
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class BarcodeStationController : ControllerBase
    {
        private readonly AMESContext _context;

        public BarcodeStationController(AMESContext context)
        {
            _context = context;
        }

        // GET: api/BarcodeStation
        [HttpGet]
        public async Task<ActionResult<IEnumerable<BarcodeStation>>> GetBarcodeStation()
        {
            return await _context.BarcodeStation.ToListAsync();
        }

        // GET: api/BarcodeStation/5
        [HttpGet("{id}")]
        public async Task<ActionResult<BarcodeStation>> GetBarcodeStation(decimal id)
        {
            var barcodeStation = await _context.BarcodeStation.FindAsync(id);

            if (barcodeStation == null)
            {
                return NotFound();
            }

            return barcodeStation;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="barcodeID">內務條碼ID</param>
        /// <param name="wipID">工單ID</param>
        /// <param name="StationID">流程站別ID</param>
        /// <param name="FlowStationID">流程ID</param>
        /// <returns></returns>
        [HttpGet("Key")]
        public async Task<ActionResult<BarcodeStation>> GetBarcodeStationByKey(int barcodeID, int wipID
           , int StationID, int FlowStationID)
        {
            var barcodeStation = await _context.BarcodeStation
                .Where(w => w.BarcodeID == barcodeID
                && w.WipID == wipID
                && w.StationID == StationID
                && w.FlowRuleID == FlowStationID).FirstOrDefaultAsync();


            //if (barcodeStation == null)
            //{
            //    return NotFound();
            //}

            return barcodeStation;
        }

        /// <summary>
        /// 用BarCode查詢過站紀錄
        /// </summary>
        /// <param name="barcodeID">barcodeID</param>
        /// <returns></returns>
        [HttpGet("BarCodeID/{barcodeID}")]
        public async Task<ActionResult<IEnumerable<BarcodeStation>>> GetBarcodeStationByBarCodeID(int barcodeID)
        {
            var q = from q1 in _context.BarcodeStation.Where(w => w.BarcodeID == barcodeID)
                    join q2 in _context.UserInfoes on q1.CreateUserID equals q2.UserID
                    join q3 in _context.RuleStations on new { q1.StationID, q1.FlowRuleID } equals new { q3.StationID, q3.FlowRuleID }
                    select new BarcodeStation
                    {
                        BarcodeID = q1.BarcodeID,
                        WipID = q1.WipID,
                        StationID = q1.StationID,
                        RuleStatus = q1.RuleStatus,
                        Systype = q1.Systype,
                        CreateDate = q1.CreateDate,
                        GetRuleStation = q3,
                        FlowRuleID = q1.FlowRuleID,
                        UserName = q2.UserName
                    };
            return await q.ToListAsync();
        }

        /// <summary>
        /// 基本查詢
        /// </summary>
        /// <param name="wipID">工單ID</param>
        /// <param name="stationID">流程ID</param>
        /// <param name="dateStart">開始日期</param>
        /// <param name="dateEnd">結束日期</param>
        /// <returns></returns>
        [HttpGet("GetBarcodeStation4QRS009Group")]
        public async Task<ResultModel<dynamic>> GetBarcodeStation4QRS009Group(int wipID, int stationID, string dateStart, string dateEnd)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();

            IQueryable<BarcodeStation> q = _context.BarcodeStation;


            if (wipID != 0)
                q = q.Where(w => w.WipID == wipID);


            if (stationID != 0)
                q = q.Where(w => w.StationID == stationID);

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            var g = q.GroupBy(x => new { x.WipID, x.StationID, x.BarcodeID }).Select(x => new
            {
                WipID = x.Key.WipID,
                StationID = x.Key.StationID,
                BarcodeID = x.Key.BarcodeID,
                FirstCnt = x.Count()
            });

            var g1 = await g.Distinct().ToListAsync();

            var g2 = q.GroupBy(x1 => new { x1.WipID, x1.StationID, x1.RuleStatus }).Select(x1 => new
            {
                WipID = x1.Key.WipID,
                StationID = x1.Key.StationID,
                RuleStatus = x1.Key.RuleStatus,
                FirstCnt = x1.Count(),
                SumCnt = g1.Count
            });

            result.DataTotal = g2.ToList().Count;

            result.Data = g2.ToList();

            return result;
        }

        /// <summary>
        /// 查詢工單站別條碼資料
        /// </summary>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetWipStationBarcode4QRS009(int wipID, int stationID, string ruleStatus, int page = 0, int limit = 10)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.BarcodeStation
                    join q2 in _context.BarcodeInfoes on q1.BarcodeID equals q2.BarcodeID
                    join q3 in _context.LineInfoes on q1.LineId equals q3.LineID into line_data
                    from x in line_data.DefaultIfEmpty()
                    join q4 in _context.UserInfoes on q1.CreateUserID equals q4.UserID
                    select new
                    {
                        q1.BarcodeID,
                        q1.WipID,
                        q1.StationID,
                        q2.BarcodeNo,
                        x.LineDesc,
                        q1.RuleStatus,
                        q1.Systype,
                        q1.InputDate,
                        q4.UserName
                    };

            q = q.Where(w => w.WipID == wipID && w.StationID == stationID && w.RuleStatus == ruleStatus);


            //紀錄筆數
            result.DataTotal = q.Count();

            //Table 頁數
            if (page > 0)
            {
                q = q.Skip((page - 1) * limit).Take(limit);
            }

            result.Data = await q.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 查詢工單站別條碼資料 By 條碼批次查詢
        /// </summary>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetWipStationBarcodeByPCS022(int wipID, int stationID, int page = 0, int limit = 10)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.BarcodeStation
                    join q2 in _context.BarcodeInfoes on q1.BarcodeID equals q2.BarcodeID
                    join q3 in _context.LineInfoes on q1.LineId equals q3.LineID
                    join q4 in _context.UserInfoes on q1.CreateUserID equals q4.UserID
                    select new
                    {
                        q1.BarcodeID,
                        q1.WipID,
                        q1.StationID,
                        q2.BarcodeNo,
                        q3.LineDesc,
                        q1.RuleStatus,
                        q1.Systype,
                        q1.InputDate,
                        q4.UserName
                    };

            q = q.Where(w => w.WipID == wipID && w.StationID == stationID && w.RuleStatus != "F");


            //紀錄筆數
            result.DataTotal = q.Count();

            //Table 頁數
            if (page > 0)
            {
                q = q.Skip((page - 1) * limit).Take(limit);
            }

            result.Data = await q.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 查詢 已過站數量
        /// </summary>
        /// <param name="wipID">工單ID</param>
        /// <param name="stationID">站別ID</param>
        /// <returns></returns>
        [HttpGet("InputQty/{wipID}/{stationID}")]
        public async Task<ActionResult<int>> GetBarcodeStationByInputQty(int wipID, int stationID)
        {
            // 取BarcodeID Distinct 數量
            var barcodeStation = await _context.BarcodeStation
                .Where(w => wipID == w.WipID && w.StationID == stationID).Select(s => s.BarcodeID)
                .Distinct().ToListAsync();
            return barcodeStation.Count();
        }

        /// <summary>
        /// 用工單ID查是否有過站紀錄
        /// </summary>
        /// <param name="wipID">工單ID</param>
        /// <returns></returns>
        [HttpGet("WipID")]
        public async Task<ActionResult<IEnumerable<BarcodeStation>>> GetBarcodeStationByWipID(int wipID)
        {

            var barcodeStation = await _context.BarcodeStation
                .Where(w => wipID == w.WipID).ToListAsync();

            if (barcodeStation == null)
            {
                return NotFound();
            }

            return barcodeStation;
        }

        /// <summary>
        /// 條碼漏刷查詢
        /// </summary>
        /// <returns></returns>
        [HttpGet("PCS019Query")]
        public async Task<ResultModel<dynamic>> GetBarcodeStationPCS019Query(string wipNo, string unitNo, string station, int page = 0, int limit = 10)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.BarcodeStation
                    join q2 in _context.BarcodeInfoes on q1.BarcodeID equals q2.BarcodeID
                    join q3 in _context.LineInfoes on q1.LineId equals q3.LineID
                    join q4 in _context.UserInfoes on q1.CreateUserID equals q4.UserID
                    select new
                    {
                        q1.BarcodeID,
                        q1.WipID,
                        q1.StationID,
                        q2.BarcodeNo,
                        q3.LineDesc,
                        q1.RuleStatus,
                        q1.Systype,
                        q1.InputDate,
                        q4.UserName
                    };

            //q = q.Where(w => w.WipID == wipID && w.RuleStationID == ruleStationID && w.RuleStatus == ruleStatus);


            //紀錄筆數
            result.DataTotal = q.Count();

            //Table 頁數
            if (page > 0)
            {
                q = q.Skip((page - 1) * limit).Take(limit);
            }

            result.Data = await q.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }


        /// <summary>
        /// 查詢工單站別條碼資料 By 條碼批次查詢
        /// </summary>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetWipStationBarcodeByPCS038(int wipID, int stationID, int page = 0, int limit = 10)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.BarcodeStation
                    where q1.WipID == wipID
                    join q2 in _context.BarcodeInfoes on q1.BarcodeID equals q2.BarcodeID
                    join q3 in _context.LineInfoes on q1.LineId equals q3.LineID
                    join q4 in _context.UserInfoes on q1.CreateUserID equals q4.UserID
                    select new
                    {
                        q1.BarcodeID,
                        q1.WipID,
                        q1.StationID,
                        q2.BarcodeNo,
                        q3.LineDesc,
                        q1.RuleStatus,
                        q1.Systype,
                        q1.InputDate,
                        q4.UserName
                    };

            if (stationID == 0)
                q = q.Where(w => w.WipID == wipID && w.RuleStatus != "F").OrderBy(o => o.BarcodeNo);
            else
                q = q.Where(w => w.WipID == wipID && w.StationID == stationID && w.RuleStatus != "F").OrderBy(o => o.BarcodeNo);

            if (q.Count() == 0)
            {
                var q1 = _context.BarcodeInfoes.Where(w => w.WipID == wipID).Select(s => new
                {
                    s.WipID,
                    s.StationID,
                    s.BarcodeNo,
                    s.RuleStatus,
                    s.SysType,
                    s.CreateDate
                });


                if (q1.Count() > 0)
                {
                    q1 = q1.Where(w => w.RuleStatus != "F").OrderBy(o => o.BarcodeNo);
                    //紀錄筆數
                    result.DataTotal = q1.Count();

                    //Table 頁數
                    if (page > 0)
                    {
                        q1 = q1.Skip((page - 1) * limit).Take(limit);
                    }

                    result.Data = await q1.ToListAsync();

                    if (result == null)
                    {
                        result.Msg = "查無資料";
                        result.Success = false;
                        return result;
                    }

                    result.Success = true;
                    result.Msg = "OK";
                    return result;

                }
                else
                {
                    result.Msg = "查無資料";
                    result.Success = false;
                    return result;
                }


            }
            else
            {




                //紀錄筆數
                result.DataTotal = q.Count();

                //Table 頁數
                if (page > 0)
                {
                    q = q.Skip((page - 1) * limit).Take(limit);
                }

                result.Data = await q.ToListAsync();

                if (result == null)
                {
                    result.Msg = "查無資料";
                    result.Success = false;
                    return result;
                }

                result.Success = true;
                result.Msg = "OK";
                return result;
            }
        }

        /// <summary>
        /// 查詢工單站別條碼資料 By 條碼批次查詢
        /// </summary>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetWipStationBarcodeByParam(int wipID, int stationID)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.BarcodeStation
                    where q1.WipID == wipID
                    join q2 in _context.BarcodeInfoes on q1.BarcodeID equals q2.BarcodeID
                    select new
                    {
                        q1.BarcodeID,
                        q1.WipID,
                        q1.StationID,
                        q2.BarcodeNo,
                        q1.RuleStatus,
                        q1.Systype,
                        q1.InputDate,
                    };

            if (stationID == 0)
                q = q.Where(w => w.WipID == wipID && w.RuleStatus != "F").OrderBy(o => o.BarcodeNo);
            else
                q = q.Where(w => w.WipID == wipID && w.StationID == stationID && w.RuleStatus != "F").OrderBy(o => o.BarcodeNo);

            if (q.Count() == 0)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }
            else
            {

                //紀錄筆數
                result.DataTotal = q.Count();

                result.Data = await q.ToListAsync();

                if (result == null)
                {
                    result.Msg = "查無資料";
                    result.Success = false;
                    return result;
                }

                result.Success = true;
                result.Msg = "OK";
                return result;
            }
        }

        /// <summary>
        /// 查詢工單站別條碼資料 By 條碼批次查詢(包含Fail)
        /// </summary>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetWipStationBarcodeByParam_A(int wipID, int stationID)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.BarcodeStation
                    where q1.WipID == wipID
                    join q2 in _context.BarcodeInfoes on q1.BarcodeID equals q2.BarcodeID
                    select new
                    {
                        q1.BarcodeID,
                        q1.WipID,
                        q1.StationID,
                        q2.BarcodeNo,
                        q1.RuleStatus,
                        q1.Systype,
                        q1.InputDate,
                    };

            if (stationID == 0)
                q = q.Where(w => w.WipID == wipID).OrderBy(o => o.BarcodeNo);
            else
                q = q.Where(w => w.WipID == wipID && w.StationID == stationID).OrderBy(o => o.BarcodeNo);

            if (q.Count() == 0)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }
            else
            {

                //紀錄筆數
                result.DataTotal = q.Count();

                result.Data = await q.ToListAsync();

                if (result == null)
                {
                    result.Msg = "查無資料";
                    result.Success = false;
                    return result;
                }

                result.Success = true;
                result.Msg = "OK";
                return result;
            }
        }

        /// <summary>
        /// 查詢 指定站別已過站日期&數量
        /// </summary>
        /// <param name="wipID">工單ID</param>
        /// <param name="stationID">站別ID</param>
        /// <param name="inputDate">過站日期</param>
        /// <returns></returns>
        [HttpGet("InputDateQty")]
        public async Task<IEnumerable<PcbaPPMDTO>> GetBarcodeStationByDateInputQty(int wipID, int stationID)
        {

            var query = await _context.BarcodeStation
                    .Where(w => w.WipID == wipID && w.StationID == stationID)
                    .Select(s => new PcbaPPMDTO { FinishDate = s.InputDate.ToString("yyyy/MM/dd"), FinishQty = 1, WipID = s.BarcodeID }).ToListAsync();

            var queryData = query.GroupBy(o => new { o.FinishDate }).Select(s => new PcbaPPMDTO { FinishDate = s.Key.FinishDate, FinishQty = s.Sum(x => x.FinishQty) }).ToList();
            foreach (var item in queryData)
            {
                item.barcodeID = query.Where(s => s.FinishDate == item.FinishDate).Select(s => s.WipID).ToList();
            }


            return queryData;
        }

        /// <summary>
        /// 查詢工單資料QRS011 生產進度查詢 過站數量
        /// </summary>
        /// <param name="wipID">工單id</param>
        /// <param name="stationID">作業站id</param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<IEnumerable<dynamic>> GetBarcodeStation4QRS011Group(int wipID, int stationID)
        {
            // 計算 過站數 不良數
            var querySql = @$" SELECT WIP_ID as wipid , 
                               STATION_ID as stationid, 
                               RULE_STATUS as rulestation , 
                               COUNT(*) as first FROM 
                               (SELECT DISTINCT BARCODE_ID , WIP_ID , STATION_ID , RULE_STATUS 
                               FROM JHAMES.BARCODE_STATION
                               WHERE WIP_ID=:WipId 
                               AND STATION_ID=:StationId )
                               GROUP BY WIP_ID , STATION_ID , RULE_STATUS ";

            DynamicParameters p = new DynamicParameters();
            p.Add("WipId", wipID);
            p.Add("StationId", stationID);
            return await _context.Database.DapperQueryAsync<dynamic>(querySql, p);
        }

        /// <summary>
        /// 查詢工單資料QRS011 生產進度查詢 完工數量
        /// </summary>
        /// <param name="wipID">工單id</param>
        /// <param name="stationID">作業站id</param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<IEnumerable<dynamic>> GetBarcodeStation4QRS011GroupOverStationQty(int wipID, int stationID)
        {
            // 計算 下一站是完工站 取得總過站數量
            var querySql = @$" SELECT WIP_ID , STATION_ID , COUNT(*) FIRST FROM 
                                                (SELECT DISTINCT A.BARCODE_ID , A.WIP_ID , A.STATION_ID , A.RULE_STATUS 
                                                FROM JHAMES.BARCODE_STATION A
                                                LEFT JOIN JHAMES.RULES R ON A.FLOW_RULE_ID = R.FLOW_RULE_ID 
                                                WHERE A.STATION_ID = R.STATION_ID 
                                                AND R.NEXT_STATION_ID = 1000 -- 完工站
                                                AND A.RULE_STATUS = R.RULE_STATUS -- 狀態需一致
                                                AND A.WIP_ID = :WipId 
                                                AND A.STATION_ID =:StationId )
                                                GROUP BY WIP_ID , STATION_ID ";

            DynamicParameters p = new DynamicParameters();
            p.Add("WipId", wipID);
            p.Add("StationId", stationID);
            return await _context.Database.DapperQueryAsync<dynamic>(querySql, p);
        }


        // PUT: api/BarcodeStation/5
        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://go.microsoft.com/fwlink/?linkid=2123754.
        [HttpPut]
        public async Task<ResultModel<BarcodeStation>> PutBarcodeStation([FromBody] BarcodeStation barcodeStation)
        {
            ResultModel<BarcodeStation> result = new ResultModel<BarcodeStation>();
            _context.Attach(barcodeStation);

            // 指定更新某個欄位
            _context.Entry(barcodeStation).Property(p => p.LineId).IsModified = true;

            try
            {
                await _context.SaveChangesAsync();
                result.Success = true;
                result.Msg = "OK";
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.Msg = ex.InnerException.Message;
            }
            return result;
        }

        // POST: api/BarcodeStation
        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://go.microsoft.com/fwlink/?linkid=2123754.
        [HttpPost]
        public async Task<ResultModel<BarcodeStation>> PostBarcodeStation([FromBody] BarcodeStation barcodeStation)
        {
            ResultModel<BarcodeStation> result = new ResultModel<BarcodeStation>();

            try
            {
                _context.BarcodeStation.Add(barcodeStation);
                await _context.SaveChangesAsync();
                result.Success = true;
                result.Msg = "OK";
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.Msg = ex.InnerException.Message;
            }
            return result;
        }

        // DELETE: api/BarcodeStation/5
        [HttpDelete("{id}")]
        public async Task<ActionResult<BarcodeStation>> DeleteBarcodeStation(decimal id)
        {
            var barcodeStation = await _context.BarcodeStation.FindAsync(id);
            if (barcodeStation == null)
            {
                return NotFound();
            }

            _context.BarcodeStation.Remove(barcodeStation);
            await _context.SaveChangesAsync();

            return barcodeStation;
        }

        private bool BarcodeStationExists(decimal id)
        {
            return _context.BarcodeStation.Any(e => e.BarcodeID == id);
        }
    }
}