<?php

namespace App\Modules\Bookings;

use Illuminate\Support\Facades\Mail;
use Exception;
use Illuminate\Support\Facades\Log;
use App\Models\User;
use App\Modules\Notifications\NotificationSetting;
use App\Modules\Notifications\Notification;
use App\Jobs\sendRepairCommentToMobile;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Support\Arr;


class CommentObserver
{
    use DispatchesJobs;
    /**
     * A reference to the eloquent model.
     *
     * @var App\Modules\Bookings\Comment
     */
    protected $model;

    /**
     * A list of all the templates available to email.
     *
     * @var array
     */
    protected static $templates = [
        'repair' => [
            'template' => 'new_comment_repairs',
        ],
        'support' => [
            'template' => 'new_comment_remote_support',
        ],
        'onsite' => [
            'template' => 'new_comment_onsite',
        ],
        'order' => [
            'template' => 'new_comment_orders',
        ],
    ];

    /**
     * Event triggered before a comment is created.
     *
     * @param  App\Modules\Bookings\Comment $model
     *
     * @return void
     */
    public function creating($model)
    {
        $this->model = $model;

        // Check to see if the send email tick was checked
        // and if so then mark this as a public comment
        // also update the emailed_to address

        if (request()->input('send_email') && $model->related_type == 'task') {
            $model->public = 1;
            $model->emailed_to = request()->input('email');
        }
    }

    /**
     * Event triggered after a comment has been created.
     *
     * @param  App\Modules\Bookings\Comment $model
     *
     * @return void
     */
    public function created($model)
    {
        $this->model = $model;

        // Check if the send mail option was ticked
        // and if so attempt to deliver the email

        if (request()->input('send_email') && $model->related_type == 'task') {
            $this->replyToCustomer();
        }
        // Notify the owner of the task
        $this->notifyUser();
        $this->notifyMobileUsers();

        // Send an email to all subscribers
        $this->notifySubscribers($model);
    }
    /**
     * Dispatch job to send notification to mobile users on new public comment
     *
     * @return void
     */
    private function notifyMobileUsers()
    {
        // if (! config('services.dynamics.username')) {
        //    return;
        //}
        $comment = $this->model;
        if ($comment->public == 1) {
            $this->dispatch(new sendRepairCommentToMobile($comment));
        }
    }


    /**
     * Get a list of all comments.
     *
     * @param  bool $hidePrivate
     *
     * @return App\Modules\Bookings\Comment
     */
    private function getComments($hidePrivate = false)
    {
        $query = Comment::where('related_id', $this->model->related_id)
            ->where('related_type', $this->model->related_type)
            ->orderBy('id', 'desc');

        if ($hidePrivate) {
            $query->where('public', 1);
        }

        return $query->get();
    }
    
    /**
     * Get only the current comment as a collection for email notification
     *
     * @return \Illuminate\Support\Collection
     */
    private function getCurrentCommentOnly()
    {
        // Return just the current comment that triggered the notification
        return collect([$this->model]);
    }

    /**
     * Send an email straight to the customer.
     *
     * @return void
     */
    private function replyToCustomer()
    {
        $cc = request()->input('cc') ? Arr::pluck(request()->input('cc', []), 'text') : [];
        
        // Get the logged-in user's email and name to use as from address
        $userEmail = null;
        $userName = null;
        if (auth()->check()) {
            $user = auth()->user();
            $userEmail = $user->email;
            $userName = trim($user->first_name . ' ' . $user->last_name) ?: $user->name;
            
            Log::info('Task email: Using user email: ' . $userEmail . ', name: ' . $userName);
        } else {
            Log::warning('Task email: No authenticated user found');
        }
        
        $this->sendMail($this->getComments(true), request()->input('email'), $cc, $userEmail, $userName);
    }

    /**
     * Sends an email to the specified email address with all the public comments
     * for the given task...
     *
     * @param App\Modules\Bookings\Comment $comments
     * @param string $email_to
     * @param array $CC
     * @param string|null $from_email
     * @param string|null $from_name
     */
    private function sendMail($comments, $email_to, $CC = [], $from_email = null, $from_name = null)
    {
        try {
            // Fetch a list of comments
            $task = $this->model->related()->first();

            // Attempt to send the mail using global SMTP configuration
            \App\Seraph\Services\GlobalMailerService::send('emails.tasks.reply', ['comments' => $comments, 'task' => $task], function ($message) use ($task, $email_to, $CC) {
                // Configure the email options
                $message->to($email_to)->subject('RE: ' . $task->client->name . ': ' . $task->title . ' [' . $task->id . ']');
                if (count($CC)) {
                    $message->cc($CC);
                }
            }, $from_email, $from_name, false); // false = no CC/BCC from SMTP settings for notifications
        } catch (Exception $e) {
            Log::error($e);
        }
    }

    /**
     * Send an email to all subscribers..
     *
     * @return void
     */
    private function notifySubscribers()
    {
        if ($this->model->related_type == 'task' && $this->model->type != 'call') {
            try {
                $subscribers = $this->model->related->subscribers()->get();
            } catch (Exception $e) {
                Log::error($e);
                $subscribers = [];
            }

            // Compose a list of emails
            $CC = [];
            foreach ($subscribers as $subscriber) {
                $CC[] = $subscriber->email;
            }

            // Get the first email as the main recipient...
            $send_to = array_shift($CC);

            if ($send_to) {
                // For subscriber notifications, also only send the current comment
                Log::info('CommentObserver: Notifying subscribers about new comment #' . $this->model->id . ' on task #' . $this->model->related->id);
                $this->sendMail($this->getCurrentCommentOnly(), $send_to, $CC);
            }
        }
    }

    /**
     * Retrieve a single template.
     *
     * @param  string $type
     *
     * @return array
     */
    private function getTemplate($type)
    {
        return (isset(static::$templates[$type]))
            ? static::$templates[$type]
            : false;
    }

    /**
     * Prepare to send a notification to the owner.
     *
     * @return void
     */
    private function notifyUser()
    {
        try {
            // For auto-booked comments (from email collector), always notify the assigned user
            // For manual comments, only notify if the assigned user is different from current user
            $shouldNotify = $this->model->related->assigned_to && 
                           $this->model->related_type == 'task' && 
                           $this->model->type != 'call' &&
                           ($this->model->auto_booked || $this->model->related->assigned_to != getAuthUserId());
                           
            if ($shouldNotify) {
                if ($template = $this->getTemplate($this->model->related->type)) {
                    Log::info('CommentObserver: Sending notification for task #' . $this->model->related->id . ' to user #' . $this->model->related->assigned_to . ' (auto_booked: ' . ($this->model->auto_booked ? 'yes' : 'no') . ')');
                    $this->sendNotification($template);
                } else {
                    Log::warning('CommentObserver: No template found for task type: ' . $this->model->related->type);
                }
            } else {
                Log::info('CommentObserver: Not sending notification for task #' . $this->model->related->id . ' (assigned_to: ' . $this->model->related->assigned_to . ', current_user: ' . getAuthUserId() . ', auto_booked: ' . ($this->model->auto_booked ? 'yes' : 'no') . ')');
            }
        } catch (Exception $e) {
            Log::error($e);
        }
    }

    /**
     * Send a notification to the owner of the task.
     *
     * @param  array $template
     *
     * @return void
     */
    private function sendNotification($template)
    {
        try {
            $settings = NotificationSetting::notification($template['template'])->user($this->model->related->assigned_to)->first();

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

            // Email notification
            if ($settings && $settings->email) {
                $user = User::find($this->model->related->assigned_to);
                if ($user && $user->email) {
                    Log::info('CommentObserver: Sending email notification to: ' . $user->email . ' for task #' . $this->model->related->id . ' (comment #' . $this->model->id . ')');
                    // For notifications, only send the current/latest comment, not the full chain
                    $this->sendMail($this->getCurrentCommentOnly(), $user->email);
                } else {
                    Log::warning('CommentObserver: No valid email found for user #' . $this->model->related->assigned_to);
                }
            } else {
                Log::info('CommentObserver: Email notifications disabled for user #' . $this->model->related->assigned_to . ' (template: ' . $template['template'] . ')');
            }
        } catch (Exception $e) {
            Log::error($e);
        }
    }
}
