using Backend.Models;
using BackendWorkerService.Services.Interface;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Quartz;
using Repository.BackendRepository.Interface;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace BackendWorkerService.Quartz.Jobs
{
    [DisallowConcurrentExecution]
    class MessageNotificationJob : IJob
    {
        private readonly ILogger<MessageNotificationJob> logger;
        private readonly IBackgroundServiceRepository backgroundServiceRepository;

        private readonly ISendEmailService sendEmailService;
        private readonly ISendSMSService sendSMSService;
        private readonly ISendLineNotifyService sendLineNotifyService;


        public MessageNotificationJob(
            ILogger<MessageNotificationJob> logger,
            IBackgroundServiceRepository backgroundServiceRepository,
            ISendEmailService sendEmailService,
            ISendSMSService sendSMSService,
            ISendLineNotifyService sendLineNotifyService)
        {
            this.logger = logger;
            this.backgroundServiceRepository = backgroundServiceRepository;
            this.sendEmailService = sendEmailService;
            this.sendSMSService = sendSMSService;
            this.sendLineNotifyService = sendLineNotifyService;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            Dictionary<string, object> insertLog = new Dictionary<string, object>()
            {
                { "@task_id", 0 },
                { "@log_level", "" },
                { "@log_content", "" }
            };

            try
            {
                logger.LogInformation("【MessageNotificationJob】【任務開始】");
                insertLog["@log_level"] = $@"INFO";
                insertLog["@log_content"] = $@"任務開始";
                await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");

                //找出所有要通知的清單
                string sWhere = @"is_complete = 0";
                var messageNotificationTasks = await backgroundServiceRepository.GetAllAsync<BackgroundServiceMessageNotificationTask>("background_service_message_notification_task", sWhere);

                if(messageNotificationTasks.Count == 0)
                {
                    logger.LogInformation("【MessageNotificationJob】【查無任務列表】");

                    insertLog["@log_level"] = $@"INFO";
                    insertLog["@log_content"] = $@"查無任務列表";
                    await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");
                }
                else
                {
                    List<Dictionary<string, object>> updateObjs = new List<Dictionary<string, object>>();
                    foreach (var task in messageNotificationTasks)
                    {
                        var DateTimeNow = DateTime.Now;
                        Dictionary<string, object> updateObj = new Dictionary<string, object>()
                        {
                            { "Id", task.Id },
                            { "@updated_at", DateTimeNow }
                        };

                        try
                        {
                            switch (task.Task_type)
                            {
                                case (byte)MessageNotificationTaskType.email:
                                    List<string> recipientEmails = new List<string>()
                                    {
                                        task.Recipient_email
                                    };

                                    if (sendEmailService.Send(task.Id, recipientEmails, task.Email_subject, task.Message_content))
                                    {
                                        updateObj.Add("@is_complete", 1);
                                        updateObj.Add("@complete_at", DateTimeNow);
                                    }
                                    else
                                    {
                                        updateObj.Add("@repeat_times", task.Repeat_times + 1);
                                    }

                                    updateObjs.Add(updateObj);
                                    break;
                                case (byte)MessageNotificationTaskType.sms:
                                    if (sendSMSService.Send(task.Id, task.Recipient_phone, task.Message_content))
                                    {
                                        updateObj.Add("@is_complete", 1);
                                        updateObj.Add("@complete_at", DateTimeNow);
                                    }
                                    else
                                    {
                                        updateObj.Add("@repeat_times", task.Repeat_times + 1);
                                    }

                                    updateObjs.Add(updateObj);
                                    break;
                                case (byte)MessageNotificationTaskType.line_notify:
                                    if (sendLineNotifyService.Send(task.Id, task.Line_token, task.Message_content))
                                    {
                                        updateObj.Add("@is_complete", 1);
                                        updateObj.Add("@complete_at", DateTimeNow);
                                    }
                                    else
                                    {
                                        updateObj.Add("@repeat_times", task.Repeat_times + 1);
                                    }

                                    updateObjs.Add(updateObj);
                                    break;
                            }
                        }
                        catch(Exception exception)
                        {
                            logger.LogError("【MessageNotificationJob】【通知失敗】[任務id]:{0}", task.Id);
                            logger.LogError("【MessageNotificationJob】【通知失敗】[Exception]:{0}", exception.ToString());

                            insertLog["@log_level"] = $@"ERR";
                            insertLog["@log_content"] = $@"通知失敗 - [失敗原因(Exception)]:{exception.ToString()}";
                            await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");
                        }
                        
                    }

                    await backgroundServiceRepository.UpdateListByCustomTable(updateObjs, "background_service_message_notification_task", "id = @Id");
                    logger.LogInformation("【MessageNotificationJob】【任務完成】");

                    insertLog["@task_id"] = 0;
                    insertLog["@log_level"] = $@"INFO";
                    insertLog["@log_content"] = $@"任務完成";
                    await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");
                }
            }
            catch (Exception exception)
            {
                logger.LogError("【MessageNotificationJob】【任務失敗】");
                logger.LogError("【MessageNotificationJob】【任務失敗】[Exception]:{0}", exception.ToString());

                insertLog["@task_id"] = 0;
                insertLog["@log_level"] = $@"ERR";
                insertLog["@log_content"] = $@"任務失敗";
                await backgroundServiceRepository.AddOneByCustomTable(insertLog, "background_service_message_notification_task_log");
            }

        }
    }
}