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;


namespace AMESCoreStudio.WebApi.Controllers.AMES
{
    /// <summary>
    /// 組件资料维护
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class BarcodeItemsController : ControllerBase
    {
        private readonly AMESContext _context;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public BarcodeItemsController(AMESContext context)
        {
            _context = context;
        }

        /// <summary>
        /// 获取全部條組件料
        /// </summary>
        /// <returns></returns>
        // GET: api/BarcodeItems
        [HttpGet]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItems()
        {
            IQueryable<BarcodeItem> q = _context.BarcodeItems;
            q = q.OrderBy(p => p.BarcodeID);



            var BarcodeItems = await q.ToListAsync();

            foreach (var data in BarcodeItems)
            {
                data.B = _context.BarcodeInfoes.Find(data.BarcodeID);
                data.I = _context.Items.Find(data.ItemNo);
                data.S = _context.Stationses.Find(data.StationID);
            }

            return BarcodeItems;
            //return await _context.BarcodeItems.ToListAsync();
        }

        /// <summary>
        /// 用ID获取该條碼资料
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // GET: api/BarcodeItems/5
        [HttpGet("{id}")]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItems(int id)
        {

            IQueryable<BarcodeItem> q = _context.BarcodeItems;
            q = q.Where(p => p.BarcodeItemID.Equals(id));
            var barcodeItem = await q.ToListAsync();

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

            return barcodeItem;
        }

        /// <summary>
        /// 用Unit获取该條碼资料
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // GET: api/BarcodeItems/5
        [HttpGet("Unit/{id}")]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItemByUnit(string id)
        {

            IQueryable<BarcodeItem> q = _context.BarcodeItems;
            if (id != "0")
                q = q.Where(p => p.I.ItemType.Equals(id));
            var barcodeItem = await q.ToListAsync();

            foreach (var data in barcodeItem)
            {
                data.B = _context.BarcodeInfoes.Find(data.BarcodeID);
                data.I = _context.Items.Find(data.ItemNo);
                data.S = _context.Stationses.Find(data.StationID);
            }

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

            return barcodeItem;
        }

        /// <summary>
        /// 查詢結轉條碼組件資料
        /// </summary>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetBarcodeItem4DataCarrier(int barcodeID)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.BarcodeItems
                    select new
                    {
                        q1.BarcodeID,
                        q1.ItemNo,
                        q1.PartNo,
                        q1.KpItemNo,
                        KpDateTime = q1.CreateDate.ToString("yyyyMMddHHmmss")
                    };

            q = q.Where(w => w.BarcodeID.Equals(barcodeID));


            //紀錄筆數
            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>
        /// 用Unit获取该條碼资料
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // GET: api/BarcodeItems/5
        [HttpGet("UnitStr/{id}")]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItemByUnitStr(string id)
        {
            var str = "";
            IQueryable<BarcodeItem> q = _context.BarcodeItems;
            if (id != "0")
            {
                q = q.Where(p => p.I.ItemType.Equals(id));
                q = q.Where(p => p.B.BarcodeNo.Equals(str));
            }
            var barcodeItem = await q.ToListAsync();
            //var i = 0;

            foreach (var data in barcodeItem)
            {
                //data.Serial = i + 1;
                data.B = _context.BarcodeInfoes.Find(data.BarcodeID);
                data.I = _context.Items.Find(data.ItemNo);
                data.S = _context.Stationses.Find(data.StationID);
            }

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

            return barcodeItem;
        }


        /// <summary>
        /// 用Unit获取该條碼资料
        /// </summary>
        /// <param name="id"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        // GET: api/BarcodeItems/5
        [HttpGet("Unit/{id}/Str/{str}")]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItemByUnitStr(string id, string str)
        {

            IQueryable<BarcodeItem> q = _context.BarcodeItems;
            if (id != "0")
            {
                //製程單位
                q = q.Where(p => p.S.UnitNo.Equals(id));
            }
            //內部條碼
            q = q.Where(p => p.B.BarcodeNo.Equals(str));
            var barcodeItem = await q.ToListAsync();

            foreach (var data in barcodeItem)
            {
                //data.Serial = i + 1;
                data.B = _context.BarcodeInfoes.Find(data.BarcodeID);
                data.I = _context.Items.Find(data.ItemNo);
                data.S = _context.Stationses.Find(data.StationID);
            }

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

            return barcodeItem;
        }

        /// <summary>
        /// 用Unit获取该條碼资料
        /// </summary>
        /// <param name="strO"></param>
        /// <returns></returns>
        // GET: api/BarcodeItems/5
        [HttpGet("Str/{str}")]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItemByStr(string strO)
        {
            string id, str;
            var strA = strO.Split(";");
            id = strA[0];
            str = strA[1];
            //WO0002A10001

            IQueryable<BarcodeItem> q = _context.BarcodeItems;
            if (id != "0")
                q = q.Where(p => p.I.ItemType.Equals(id));

            q = q.Where(p => p.B.BarcodeNo.Equals(str));
            var barcodeItem = await q.ToListAsync();

            foreach (var data in barcodeItem)
            {
                data.B = _context.BarcodeInfoes.Find(data.BarcodeID);
                data.I = _context.Items.Find(data.ItemNo);
            }

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

            return barcodeItem;
        }

        /// <summary>
        /// 用barcodeID獲取資料
        /// </summary>
        /// <param name="barcodeID">barcodeID</param>
        /// <returns></returns>
        [HttpGet("ByBarCodeID")]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItemByBarCodeID(int barcodeID)
        {
            IQueryable<BarcodeItem> q = _context.BarcodeItems;
            var barcodeItem = await q.Where(w => w.BarcodeID == barcodeID).ToListAsync();

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

            return barcodeItem;
        }

        /// <summary>
        /// 用barcodeID獲取資料 By生產履歷
        /// </summary>
        /// <param name="barcodeID">barcodeID</param>
        /// <returns></returns>
        [HttpGet("ByBarCodeIDPCS009")]
        public async Task<ActionResult<IEnumerable<BarcodeItemDTO>>> GetBarcodeItemByBarCodeIDPCS009(int barcodeID)
        {
            var q = from q1 in _context.BarcodeItems.Where(w => w.BarcodeID == barcodeID).OrderBy(o => o.BarcodeItemID)
                    join q2 in _context.Items on q1.ItemNo equals q2.ItemNo
                    join q3 in _context.Stationses on q1.StationID equals q3.StationID
                    join q4 in _context.UserInfoes on q1.CreateUserID equals q4.UserID
                    select new BarcodeItemDTO
                    {
                        BarcodeID = q1.BarcodeID,
                        WipID = q1.WipID,
                        PartNo = q1.PartNo,
                        KpItemNo = q1.KpItemNo,
                        ItemNoName = q2.ItemName,
                        StationName = q3.StationName,
                        StationID = q1.StationID,
                        CreateUser = q4.UserName,
                        CreateDate = q1.CreateDate,
                        SysType = q1.SysType
                    };

            return await q.ToListAsync();
        }

        /// <summary>
        ///  by 出貨序號
        /// </summary>
        /// <param name="id">出貨序號</param>
        /// <returns></returns>
        [HttpGet("ByExtraNo/{id}")]
        public async Task<ActionResult<IEnumerable<BarcodeItemDTO>>> GetBarcodeItemByByExtraNo(string id)
        {
            int barcodeID = 0;

            IQueryable<BarcodeInfo> qq = _context.BarcodeInfoes;
            qq = qq.Where(p => p.ExtraBarcodeNo == id);
            if (qq.Count() != 0)
            {
                barcodeID = qq.FirstOrDefault().BarcodeID;
            }

            var q = from q1 in _context.BarcodeItems.Where(w => w.BarcodeID == barcodeID).OrderBy(o => o.BarcodeItemID)
                    join q2 in _context.Items on q1.ItemNo equals q2.ItemNo
                    join q3 in _context.Stationses on q1.StationID equals q3.StationID
                    join q4 in _context.UserInfoes on q1.CreateUserID equals q4.UserID
                    select new BarcodeItemDTO
                    {
                        ItemNo = q1.ItemNo,
                        PartNo = q1.PartNo,
                        KpItemNo = q1.KpItemNo,
                        ItemNoName = q2.ItemName,
                        SysType = q1.SysType
                    };

            return await q.ToListAsync();

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="wipNO">工單號料</param>
        /// <param name="barCode">內部條碼</param>
        /// <param name="KPItemNo">組件編號</param>
        /// <param name="BarCodeItem">內部條碼List</param>
        /// <param name="page">頁數</param>
        /// <param name="limit">筆數</param>
        /// <returns></returns>
        [HttpGet("BarCodeByPCS027")]
        public async Task<ResultModel<BarcodeItemDTO>> GetBarcodeItemByPCS027(string wipNO, string barCode, string KPItemNo,
           string BarCodeItem, int page = 0, int limit = 10)
        {
            ResultModel<BarcodeItemDTO> result = new ResultModel<BarcodeItemDTO>();
            try
            {
                var barcodeItems = new List<BarcodeItem>();
                // 查詢工單號碼
                if (!string.IsNullOrWhiteSpace(wipNO))
                {
                    var wipID = _context.WipInfos.Where(w => w.WipNO == wipNO.Trim().ToUpper()).Select(s => s.WipID).ToList();
                    barcodeItems = await _context.BarcodeItems.Where(w => wipID.Contains(w.WipID)).ToListAsync();
                }
                // 查詢內部序號
                else if (!string.IsNullOrWhiteSpace(barCode))
                {
                    int barcodeID = 0;
                    var barcodes = _context.BarcodeInfoes.Where(w => w.BarcodeNo == barCode.Trim().ToUpper()).FirstOrDefault();
                    if (barcodes != null)
                        barcodeID = barcodes.BarcodeID;

                    barcodeItems = await _context.BarcodeItems.Where(w => barcodeID == w.BarcodeID).ToListAsync();
                }
                // 查詢多筆序號
                else if (!string.IsNullOrWhiteSpace(BarCodeItem))
                {
                    var barcodeList = BarCodeItem.Split(',').ToList();
                    var barcodeIDs = _context.BarcodeInfoes.Where(w => barcodeList.Contains(w.BarcodeNo)).Select(s => s.BarcodeID).ToList();
                    barcodeItems = await _context.BarcodeItems.Where(w => barcodeIDs.Contains(w.BarcodeID)).ToListAsync();
                }

                var q = from q1 in barcodeItems
                        join q2 in _context.Items on q1.ItemNo equals q2.ItemNo
                        join q3 in _context.Stationses on q1.StationID equals q3.StationID
                        join q4 in _context.UserInfoes on q1.CreateUserID equals q4.UserID
                        join q5 in _context.WipInfos on q1.WipID equals q5.WipID
                        join q6 in _context.BarcodeInfoes on q1.BarcodeID equals q6.BarcodeID
                        select new BarcodeItemDTO
                        {
                            BarcodeItemID = q1.BarcodeItemID,
                            BarcodeID = q1.BarcodeID,
                            Barcode = q6.BarcodeNo,
                            WipID = q1.WipID,
                            PartNo = q1.PartNo,
                            ItemNo = q1.ItemNo,
                            ItemNoName = q2.ItemName,
                            KpItemNo = q1.KpItemNo,
                            StationName = q3.StationName,
                            StationID = q1.StationID,
                            CreateUser = q4.UserName,
                            CreateDate = q1.CreateDate,
                            SysType = q1.SysType,
                            WipNo = q5.WipNO
                        };

                // 查詢組件代碼
                if (!string.IsNullOrWhiteSpace(KPItemNo))
                {
                    q = q.Where(w => w.ItemNo == KPItemNo).ToList();
                }

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

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

                result.Data = q.ToList();
                result.Success = true;
                return result;
            }
            catch (Exception ex)
            {
                result.Success = false;
                result.Msg = ex.Message;
                return result;
            }
        }

        /// <summary>
        /// 用barcode獲取資料
        /// </summary>
        /// <param name="barcode">barcodeID</param>
        /// <returns></returns>
        [HttpGet("ByBarCode")]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItemByBarCode(string barcode)
        {
            int barcodeID = 0;
            BarcodeInfoesController barcodeInfoesController = new BarcodeInfoesController(_context);
            var q1 = await barcodeInfoesController.GetBarcodeInfoesByNo(barcode);
            if (!q1.Value.Any())
                barcodeID = 0;
            else
                barcodeID = q1.Value.FirstOrDefault().BarcodeID;

            IQueryable<BarcodeItem> q = _context.BarcodeItems;
            var barcodeItem = await q.Where(w => w.BarcodeID == barcodeID).ToListAsync();

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

            return barcodeItem;
        }

        /// <summary>
        /// 查詢 By PartNo
        /// </summary>
        /// <param name="id">組件條碼</param>
        /// <returns></returns>
        [HttpGet("ByPartNo/{id}")]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItemByPartNo(string id)
        {
            IQueryable<BarcodeItem> q = _context.BarcodeItems.Where(w => w.PartNo == id);
            var barcodeItem = await q.ToListAsync();
            return barcodeItem;
        }

        /// <summary>
        /// 確認組件代碼是否重複
        /// </summary>
        /// <param name="itemNO">組件代碼</param>
        /// <param name="partNo">組件條碼</param>
        /// <returns></returns>
        [HttpGet("CheckDataRedundancy")]
        public async Task<ActionResult<IEnumerable<BarcodeItem>>> GetBarcodeItemByDataRedundancy(string itemNO, string partNo)
        {
            IQueryable<BarcodeItem> q = _context.BarcodeItems;
            var barcodeItem = await q.Where(w => w.ItemNo.ToUpper() == itemNO.ToUpper() && w.PartNo == partNo).ToListAsync();

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

            return barcodeItem;
        }


        /// <summary>
        /// 更新條碼资料
        /// </summary>
        /// <param name="id"></param>
        /// <param name="barcodeItem"></param>
        /// <returns></returns>
        // PUT: api/BarcodeItems/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("{id}")]
        public async Task<ResultModel<BarcodeItem>> PutBarcodeItems(int id, [FromBody] BarcodeItem barcodeItem)
        {
            ResultModel<BarcodeItem> result = new ResultModel<BarcodeItem>();
            if (id != barcodeItem.BarcodeItemID)
            {
                result.Success = false;
                result.Msg = "序號錯誤";
                return result;
            }

            //if (!string.IsNullOrEmpty(barcodeItem.KpItemNo))
            //{
            //    if (KPItemNoExists(barcodeItem.KpItemNo))
            //    {
            //        result.Success = false;
            //        result.Msg = "组件料號重複";
            //        return result;
            //    }
            //}

            var wip_data = await _context.WipInfos.Where(m => m.WipID == barcodeItem.WipID).FirstOrDefaultAsync();
            var kp_data = await _context.WipKps.Where(m => m.WipNo == wip_data.WipNO && m.KpNo == barcodeItem.ItemNo).FirstOrDefaultAsync();

            if (kp_data.IsRepeat == "Y")
            {
                
            }
            else
            {
                if (kp_data.IsRepeat == "N")
                {
                    if (PartNoExists(barcodeItem.PartNo))
                    {
                        result.Success = false;
                        result.Msg = "組件條碼重複";
                        return result;
                    }
                }

                if (kp_data.Title != "" && kp_data.Length != null)
                {
                    if (PartNoExists(barcodeItem.PartNo))
                    {
                        result.Success = false;
                        result.Msg = "組件條碼重複";
                        return result;
                    }
                }
            }

            _context.Entry(barcodeItem).State = EntityState.Modified;

            try
            {
                var barcodeInfo = await _context.BarcodeInfoes.Where(m => m.BarcodeID == barcodeItem.BarcodeID).FirstOrDefaultAsync();
                _context.Entry<BarcodeInfo>(barcodeInfo).Property("LocationID").IsModified = true;
                barcodeInfo.LocationID = -1;
            }
            catch { }

            try
            {

                await _context.SaveChangesAsync();
                result.Success = true;
                result.Msg = "OK";
                return result;

            }
            catch (Exception ex)
            {
                result.Success = false;
                result.Msg = ex.InnerException.Message;
                return result;
                //throw;

            }
        }

        /// <summary>
        /// 新增條碼资料
        /// </summary>
        /// <param name="barcodeItem"></param>
        /// <returns></returns>
        // POST: api/BarcodeItems
        // 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<BarcodeItem>> PostBarcodeItems(BarcodeItem barcodeItem)
        {
            ResultModel<BarcodeItem> result = new ResultModel<BarcodeItem>();
            Helper helper = new Helper(_context);
            barcodeItem.BarcodeItemID = helper.GetIDKey("BARCODEITEM_ID").Result;

            //if (PartNoExists(barcodeItem.PartNo))
            //{
            //    result.Success = false;
            //    result.Msg = "組件條碼重複";
            //    return result;
            //}

            try
            {
                //_context.Entry(barcodeItem.B).State = EntityState.Detached;
                //_context.BarcodeItems.Add(barcodeItem);
                _context.Set<BarcodeItem>().Add(barcodeItem);

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

        /// <summary>
        /// 新增條碼资料
        /// </summary>
        /// <param name="barcodeItem"></param>
        /// <returns></returns>
        // POST: api/BarcodeItems
        // 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("PCS024")]
        public async Task<ResultModel<BarcodeItem>> PostBarcodeItemsAddnew(BarcodeItem barcodeItem)
        {
            ResultModel<BarcodeItem> result = new ResultModel<BarcodeItem>();
            Helper helper = new Helper(_context);
            barcodeItem.BarcodeItemID = helper.GetIDKey("BARCODEITEM_ID").Result;
            barcodeItem.B.BarcodeID = barcodeItem.BarcodeID;

            var wip_data = await _context.WipInfos.Where(m => m.WipID == barcodeItem.WipID).FirstOrDefaultAsync();
            var kp_data = await _context.WipKps.Where(m => m.WipNo == wip_data.WipNO && m.KpNo == barcodeItem.ItemNo).FirstOrDefaultAsync();

            if (kp_data.IsRepeat == "N")
            {
                if (PartNoExists(barcodeItem.PartNo))
                {
                    result.Success = false;
                    result.Msg = "組件條碼重複";
                    return result;
                }
            }

            if (kp_data.Title != "" && kp_data.Length != null)
            {
                if (PartNoExists(barcodeItem.PartNo))
                {
                    result.Success = false;
                    result.Msg = "組件條碼重複";
                    return result;
                }
            }

            var wip_kp = await _context.WipKps.Where(m => m.WipNo == wip_data.WipNO && m.KpNo == barcodeItem.ItemNo).ToListAsync();
            var barcode_kp = await _context.BarcodeItems.Where(m => m.WipID == barcodeItem.WipID && m.BarcodeID == barcodeItem.BarcodeID && m.ItemNo == barcodeItem.ItemNo).ToListAsync();
            if (barcode_kp.Count >= wip_kp.Count)
            {
                result.Success = false;
                result.Msg = "組件條碼數量已超過工單設定數量";
                return result;
            }

            /*
            if (PartNoExists(barcodeItem.PartNo))
            {
                result.Success = false;
                result.Msg = "組件條碼重複";
                return result;
            }
            */

            try
            {
                _context.BarcodeItems.Add(barcodeItem);
                _context.Entry(barcodeItem.B).State = EntityState.Detached;
                _context.Entry(barcodeItem.B).Property(p => p.LocationID).IsModified = true;
                barcodeItem.B.LocationID = -1;

                _context.Entry(barcodeItem).State = EntityState.Added;
                //_context.Set<BarcodeItem>().Add(barcodeItem);

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

        /// <summary>
        /// 刪除條碼资料
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // DELETE: api/BarcodeItems/5
        [HttpDelete("{id}")]
        public async Task<ResultModel<BarcodeItem>> DeleteBarcodeItems(int id)
        {
            ResultModel<BarcodeItem> result = new ResultModel<BarcodeItem>();
            //var repairResponsibleUnits = await _context.BarcodeItems.FindAsync(id);
            var barcodeItem = await _context.BarcodeItems.Where(m => m.BarcodeItemID == id).FirstOrDefaultAsync();
            if (barcodeItem == null)
            {
                result.Success = false;
                result.Msg = "序號不存在";
                return result;
            }

            _context.BarcodeItems.Remove(barcodeItem);

            _context.Entry(barcodeItem.B).State = EntityState.Detached;
            _context.Entry(barcodeItem.B).Property(p => p.LocationID).IsModified = true;
            barcodeItem.B.LocationID = -1;

            await _context.SaveChangesAsync();

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

        private bool BarcodeItemsExists(int id)
        {
            return _context.BarcodeItems.Any(e => e.BarcodeID == id);
        }
        private bool KPItemNoExists(string id)
        {
            return _context.BarcodeItems.Any(e => e.KpItemNo == id);
        }
        private bool PartNoExists(string id)
        {
            return _context.BarcodeItems.Any(e => e.PartNo == id);
        }
    }
}