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.BAS;
using AMESCoreStudio.WebApi.Models.AMES;
using AMESCoreStudio.CommonTools.Result;
using Microsoft.Extensions.Configuration;
using System.Net;
using System.Net.Mail;

namespace AMESCoreStudio.WebApi.Controllers.AMES
{
    /// <summary>
    /// 測試不良零件資料檔
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class NgComponentsController : ControllerBase
    {
        private readonly AMESContext _context;
        private readonly IConfiguration _config;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public NgComponentsController(AMESContext context)
        {
            _config = new ConfigurationBuilder().SetBasePath(Environment.CurrentDirectory).AddJsonFile("appsettings.json").Build();
            _context = context;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        // GET: api/NgComponents
        [HttpGet]
        public async Task<ActionResult<IEnumerable<NgComponent>>> GetNgComponent()
        {
            return await _context.NgComponents.ToListAsync();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // GET: api/NgComponents/5
        [HttpGet("{id}")]
        public async Task<ActionResult<IEnumerable<NgComponent>>> GetNgComponent(int id)
        {
            IQueryable<NgComponent> q = _context.NgComponents;

            q = q.Where(p => p.ComponentID.Equals(id));

            var ngComponent = await q.ToListAsync();

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

            return ngComponent;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // GET: api/NgComponents/5
        [HttpGet("NGID/{id}")]
        public async Task<ActionResult<IEnumerable<NgComponent>>> GetNgComponentByNGID(int id)
        {
            IQueryable<NgComponent> q = _context.NgComponents;

            q = q.Where(p => p.NgID.Equals(id));

            try
            {
                var ngComponent = await q.ToListAsync();

                if (ngComponent.Count > 0)
                {
                    if (ngComponent[0].ErrorDesc == "" || ngComponent[0].ErrorDesc == null)
                    {
                        IQueryable<NGReason> q1 = _context.NGReasons;

                        q1 = q1.Where(p => p.NGReasonNo.Equals(ngComponent[0].NgNo));

                        var ng_reason = await q1.ToListAsync();

                        if (ng_reason.Count > 0)
                        {
                            ngComponent[0].ErrorDesc = ng_reason[0].NGReasonDesc;
                        }
                    }
                }

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

                return ngComponent;
            }
            catch
            {
                return NotFound();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ngComponent"></param>
        /// <returns></returns>
        // PUT: api/NgComponents/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<NgComponent>> PutNgComponent(int id, NgComponent ngComponent)
        {
            ResultModel<NgComponent> result = new ResultModel<NgComponent>();
            if (id != ngComponent.ComponentID)
            {
                result.Success = false;
                result.Msg = "不良零件ID錯誤";
                return result;
            }

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

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!NgComponentExists(id))
                {
                    result.Success = false;
                    result.Msg = "不良零件ID不存在";
                    return result;
                }
                else
                {
                    throw;
                }
            }

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

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ngComponent"></param>
        /// <returns></returns>
        // POST: api/NgComponents
        // 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<NgComponent>> PostNgComponent(NgComponent ngComponent)
        {
            ResultModel<NgComponent> result = new ResultModel<NgComponent>();
            Helper helper = new Helper(_context);
            ngComponent.ComponentID = helper.GetIDKey("COMPONENT_ID").Result;
            
            _context.NgComponents.Add(ngComponent);
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException ex)
            {
                if (NgComponentExists(ngComponent.ComponentID))
                {
                    result.Success = false;
                    result.Msg = "不良零件ID重複";
                    return result;
                }
                else
                {
                    result.Success = false;
                    result.Msg = ex.InnerException.Message;
                    return result;
                }
            }

            var q1 = from b in _context.NgInfos 
                     join c in _context.BarcodeInfoes on b.BarcodeID equals c.BarcodeID
                     join d in _context.WipInfos on c.WipID equals d.WipID
                     select new
                     {
                         b.NgID,
                         d.WipNO
                     };

            q1 = q1.Where(w => w.NgID.Equals(ngComponent.NgID));

            var data1 = await q1.ToListAsync();
            string wip_no = string.Empty;
            if (data1.Count != 0)
            {
                wip_no = data1[0].WipNO;
            }
             

            var q2 = from b in _context.NgInfos 
                     join c in _context.BarcodeInfoes on b.BarcodeID equals c.BarcodeID
                     join d in _context.WipInfos on c.WipID equals d.WipID
                     join e in _context.NgComponents on b.NgID equals e.NgID
                     join f in _context.WipAtts on d.WipNO equals f.WipNO
                     join g in _context.Stationses on b.StationId equals g.StationID
                     join h in _context.UserInfoes on b.CreateUserID equals h.UserID
                     select new
                     {
                         b.NgID,
                         d.WipNO,
                         d.UnitNO,
                         d.WerksNO,
                         c.BarcodeNo,
                         e.LocationNo,
                         e.CreateDate,
                         g.StationName,
                         h.UserName,
                         f.ItemNO,
                         f.ModelNO
                     };

            q2 = q2.Where(w => w.WipNO.Equals(wip_no));
            q2 = q2.Where(w => w.LocationNo.Equals(ngComponent.LocationNo));

            var data2 = await q2.ToListAsync();

            if (data2.Count > 3)
            {
                try
                {
                    string itemNo2 = data2[0].ItemNO;
                    string modelNo2 = data2[0].ModelNO;
                    string werksNo = data2[0].WerksNO;
                    string unitNo = data2[0].UnitNO;

                    //保存警报资料
                    string alarmDesc = string.Format("不良位置{0}累積超過{1}次", ngComponent.LocationNo, data2.Count);

                    WipAlarm wipAlarm = new WipAlarm();
                    wipAlarm.WipAlarmID = helper.GetIDKey("WIP_ALARMID").Result;
                    wipAlarm.AlarmTypeID = 3;
                    wipAlarm.WipNO = wip_no;
                    wipAlarm.AlarmParam = ngComponent.LocationNo;
                    wipAlarm.AlarmValue = data2.Count.ToString();
                    wipAlarm.AlarmDesc = alarmDesc;
                    wipAlarm.AlarmDateTime = DateTime.Now;

                    _context.WipAlarms.Add(wipAlarm);
                    await _context.SaveChangesAsync();

                    //发送警报资料
                    string webSiteUrl = _config["WebSiteUrl"].ToString();
                    string viewUrl = webSiteUrl + "/QRS/QRS018A/" + wip_no;

                    //2023-08-20 BB.Wang Modify
                    //工單號碼 + (工程編號) + - +  異常原因;
                    //string mailSubject = "警報持續郵件" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    string mailSubject = wip_no + " (" + itemNo2 + ")" + " - " + alarmDesc;

                    string mailBody = "";
                    //mailBody = mailBody + "警報工單:" + wip_no + "<br />";
                    mailBody = mailBody + "警報工單:" + wip_no + ",廠別:" + werksNo + ",工程編號:" + itemNo2 + ",機種:" + modelNo2 + "<br />";
                    mailBody = mailBody + "警報時間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "<br />";
                    mailBody = mailBody + "警報原因:" + alarmDesc + "<br />";
                    //mailBody = mailBody + "警報鏈接:" + webSiteUrl + "/QRS/QRS012/" + wip_no + "<br />";
                    mailBody = mailBody + "警報鏈接:<a href='" + viewUrl + "'>" + viewUrl + "</a><br />";

                    mailBody = mailBody + "詳細資訊:<br />";

                    string tableData = "";
                    tableData = tableData + "<table border = '1' width='100%' cellspacing='2px' cellpadding='10px'>";
                    tableData = tableData + "<tr bgcolor='#66CCFF' height='30'><td>生產序號</td><td>發生站別</td><td>零件位置</td><td>發生時間</td><td>作業人員</td></tr>";
                    for (int i = 0; i < data2.Count; i++)
                    {
                        string lineData = "<tr height='30'><td>" + data2[i].BarcodeNo + "</td><td>" + data2[i].StationName + "</td><td>" + data2[i].LocationNo + "</td><td>" + data2[i].CreateDate.ToString("yyyy-MM-dd HH:mm:ss") + "</td><td>" + data2[i].UserName + "</td></tr>";
                        tableData = tableData + lineData;

                    }
                    tableData = tableData + "</table>";

                    mailBody = mailBody + tableData;

                    string mailFrom = _config["MailFrom"].ToString();
                    //string mailTo = _config["MailTo"].ToString();
                    string mailSmtpServer = _config["MailSmtpServer"].ToString();
                    int mailSmtpPort = int.Parse(_config["MailSmtpPort"].ToString());
                    string mailUser = _config["MailUser"].ToString();
                    string mailPassword = _config["MailUserPassword"].ToString();

                    MailMessage mesMail = new MailMessage();
                    mesMail.From = new MailAddress(mailFrom);

                    IQueryable<MailGroup> q3 = _context.MailGroups;
                    if (unitNo == "T" || unitNo == "P")
                    {
                        q3 = q3.Where(p => p.GroupNo.Equals("WIP_ALARM"));
                    }
                    else
                    {
                        q3 = q3.Where(p => p.GroupNo.Equals("SFIS_ALARM(Appearance)"));
                    }
                    var mail1 = await q3.ToListAsync();

                    if (mail1.Count > 0)
                    {
                        var q4 = from a in _context.MailGroups
                                 join b in _context.MailGroupDetails on a.GroupID equals b.GroupID
                                 join c in _context.UserInfoes on b.UserID equals c.UserID
                                 select new
                                 {
                                     a.GroupID,
                                     b.UserID,
                                     c.UserEMail
                                 };

                        q4 = q4.Where(w => w.GroupID.Equals(mail1[0].GroupID));

                        var mail2 = await q4.ToListAsync();
                        if (mail2.Count > 0)
                        {
                            for (int i = 0; i < mail2.Count; i++)
                            {
                                mesMail.To.Add(new MailAddress(mail2[i].UserEMail));
                            }
                        }

                        //mesMail.To.Add(new MailAddress(mailTo));

                        mesMail.Subject = mailSubject;
                        mesMail.SubjectEncoding = System.Text.Encoding.UTF8;
                        mesMail.Body = mailBody;
                        mesMail.IsBodyHtml = true;
                        mesMail.BodyEncoding = System.Text.Encoding.UTF8;

                        SmtpClient mailClient = new SmtpClient(mailSmtpServer, mailSmtpPort);

                        //mailClient.EnableSsl = true;
                        NetworkCredential nc = new NetworkCredential();
                        nc.UserName = mailUser;
                        nc.Password = mailPassword;
                        mailClient.Credentials = nc;

                        mailClient.Send(mesMail);

                    }
                }
                catch { }

            }

            result.Success = true;
            result.Msg = "OK"+"-"+ngComponent.ComponentID;
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // DELETE: api/NgComponents/5
        [HttpDelete("{id}")]
        public async Task<ResultModel<NgComponent>> DeleteNgComponent(decimal id)
        {
            ResultModel<NgComponent> result = new ResultModel<NgComponent>();

            var ngComponent = await _context.NgComponents.FindAsync(id);
            if (ngComponent == null)
            {
                result.Success = false;
                result.Msg = "不良零件ID不存在";
                return result;
            }

            _context.NgComponents.Remove(ngComponent);
            await _context.SaveChangesAsync();

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

        private bool NgComponentExists(decimal id)
        {
            return _context.NgComponents.Any(e => e.ComponentID == id);
        }
    }
}