<?php

namespace App\Modules\Bookings;

use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Log;
use App\Models\User;
use App\Seraph\Services\GlobalMailerService;
use Illuminate\Support\Facades\URL;
use App\Modules\Notifications\Notification;
use App\Modules\Notifications\NotificationSetting;
use Exception;

class TaskNotificationsObserver
{
    /**
     * Executed after a task is created.
     *
     * @param  App\Modules\Bookings\Task $model
     *
     * @return void
     */
    public function created($model)
    {
        // Send a notification if a new task has been created
        // and the person who is assigned to is not the logged in user
        if (! $this->isCurrentUser($model)) {
            $this->sendAssignedNotifications($model);
        }

        // Send notifications to a hipchat channel
        // $this->sendHipChatNotification($model);
    }

    /**
     * Executed before a task is updated.
     *
     * @param  App\Modules\Bookings\Task $model
     *
     * @return void
     */
    public function updating($model)
    {
        // If the task has been updated and reassigned to another user
        // email the new user about it
        if ($this->isReassigned($model) && ! $this->isCurrentUser($model)) {
            $this->sendAssignedNotifications($model);
        }

        // If the task has been updated and not reassigned
        // we send a message to the user letting him know
        if (! $this->isCurrentUser($model) && ! $this->isReassigned($model)) {
            $this->sendUpdatedNotifications($model);
        }
    }

    /**
     * Return a list of posible templates for emails
     * and their subject.
     *
     * @return array
     */
    private function getTemplates()
    {
        return [
            'assigned' => [
                'repair' => [
                    'template' => 'assigned_new_repair',
                    'subject'  => 'New repair assigned to you',
                ],
                'support' => [
                    'template' => 'assigned_new_remote_support',
                    'subject'  => 'Support job assigned to you',
                ],
                'onsite' => [
                    'template' => 'assigned_new_onsite',
                    'subject'  => 'Onsite job assigned to you',
                ],
                'qa' => [
                    'template' => 'assigned_new_qa',
                    'subject'  => 'QA job assigned to you',
                ],
            ],

            'updated' => [
                'repair' => [
                    'template' => 'change_status_repairs',
                    'subject'  => 'Your repair has been updated',
                ],
                'support' => [
                    'template' => 'change_status_support',
                    'subject'  => 'Your remote support job has been updated',
                ],
                'onsite' => [
                    'template' => 'change_status_onsite',
                    'subject'  => 'Your onsite job has been updated',
                ],
                'order' => [
                    'template' => 'change_status_orders',
                    'subject'  => 'Your order has been updated',
                ],
            ],
        ];
    }

    /**
     * Retrieve a single template.
     *
     * @param  string $event
     * @param  string $type
     *
     * @return array
     */
    private function getTemplate($event, $type)
    {
        $templates = $this->getTemplates();

        if (! isset($templates[$event])) {
            return false;
        }

        $templates = $templates[$event];

        return (isset($templates[$type]))
                ? $templates[$type]
                : false;
    }

    /**
     * Determine if the task is assigned to the currently logged in user.
     *
     * @param  App\Modules\Bookings\Task  $model
     *
     * @return bool
     */
    private function isCurrentUser($model)
    {
        return $model->assigned_to == getAuthUserId();
    }

    /**
     * Determine if the task has been reassigned from a user to another.
     *
     * @param  App\Modules\Bookings\Task  $model
     *
     * @return bool
     */
    private function isReassigned($model)
    {
        return ($model->assigned_to && $model->isDirty('assigned_to') && $model->getOriginal('assigned_to') != $model->assigned_to);
    }

    /**
     * Checks to see weather a user has enabled his notifications,
     * and if it matches any of the rules it sends the notification.
     *
     * @param App\Modules\Bookings\Task $model
     * @param string $notification
     * @param string $subject
     *
     * @return null
     */
    private function sendNotification($model, $notification, $subject)
    {
        $settings = NotificationSetting::notification($notification)->user($model->assigned_to)->first();

        // On page alert notification
        if ($settings && $settings->alert) {
            Notification::create([
                'user_id'      => $model->assigned_to,
                'related_type' => $model->type,
                'related_id'   => $model->id,
                'message'      => $subject.': "'.$model->title.'"',
            ]);
        }

        // Email notification
        if ($settings && $settings->email) {
            try {
                GlobalMailerService::send('emails.notifications.'.$notification, [$model->type => $model], function ($message) use ($model, $subject) {
                    $message->to(User::find($model->assigned_to)->email)->subject($subject);
                });

                Log::info('Emailed user '.$model->assigned_to.' with template '.$notification.' for task #'.$model->id);
            } catch (Exception $e) {
                Log::error($e);
            }
        }
    }

    /**
     * Sends alert & email notifications to users if the rules applies to them.
     *
     * @return null
     */
    private function sendAssignedNotifications($model)
    {
        if ($template = $this->getTemplate('assigned', $model->type)) {
            $this->sendNotification($model, $template['template'], $template['subject']);
        }
    }

    /**
     * Send alerts on update.
     *
     * @param  Eloquent $model
     *
     * @return void
     */
    private function sendUpdatedNotifications($model)
    {
        if ($template = $this->getTemplate('updated', $model->type)) {
            $this->sendNotification($model, $template['template'], $template['subject']);
        }
    }

    /**
     * Send a notification to a hipchat channel.
     *
     * @param  App\Modules\Bookings\Task $model
     *
     * @return void
     */
    private function sendHipChatNotification($model)
    {
        if ($model->type != 'support') {
            return;
        }

        try {
            $hc = App::make('HipChat');

            switch ($model->severity_id) {
                case 3  : $color = 'purple'; $notify = true; break;
                case 4  : $color = 'red';    $notify = true; break;
                default : $color = 'yellow'; $notify = true;
            }

            // Format the message
            $message = sprintf("New job <a href='%s'>#%d</a> - %s, booked in by %s. Priority: %s. Customer: %s",
                            URL::to('tasks/'.$model->id),
                            $model->id,
                            $model->title,
                            trim($model->creator->name),
                            $model->severity->name,
                            $model->client->name);

            $hc->message_room('Remote Support', 'Seraph', $message, $notify, $color);
        } catch (Exception $e) {
            Log::error($e);
        }
    }
}
