<?php

namespace App\Notifications;

use App\Models\EmployeeLeave;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\URL;
use Swift_Message;

class Leave extends Notification
{
    use Queueable;

    private string $message;

    /**
     * Create a new notification instance.
     */
    public function __construct(private EmployeeLeave $leave)
    {
        $this->message = $this->generateMessage();
    }

    /**
     * Get the notification's delivery channels.
     *
     * @return array<int, string>
     */
    public function via(object $notifiable): array
    {
        return ['mail', 'database'];
    }

    /**
     * Get the mail representation of the notification.
     */
    public function toMail(object $notifiable): MailMessage
    {
        $frontendUrl = config('app.frontend_url');
        $urls = $this->generateActionUrls($notifiable, $frontendUrl);
        
        // Load the leave reason relationship if not already loaded
        if (!$this->leave->relationLoaded('reason')) {
            $this->leave->load('reason');
        }
        
        $mail = (new MailMessage)
            ->subject('Leave Notification - AUTOHUB GROUP')
            ->view('emails.leave', [
                'notifiable' => $notifiable,
                'leave' => $this->leave,
                'msg' => $this->message,
                'statusBadge' => $this->getStatusBadge(),
                'statusColor' => $this->getStatusColor(),
                'statusText' => $this->getStatusText(),
                'approveUrl' => $urls['approve'],
                'denyUrl' => $urls['deny'],
                'viewUrl' => $urls['view'],
                'showActionButtons' => $this->shouldShowActionButtons($notifiable),
                'hasAttachment' => !empty($this->leave->attachment)
            ]);
        
        // Attach the file if it exists
        if ($this->leave->attachment) {
            $attachmentPath = storage_path('app/employee-leave/' . $this->leave->attachment);
            if (file_exists($attachmentPath)) {
                $mail->attach($attachmentPath, [
                    'as' => $this->leave->attachment,
                    'mime' => mime_content_type($attachmentPath)
                ]);
            }
        }
        
        return $mail;
    }

    /**
     * Generate frontend URLs that will handle the signed API calls
     */
    private function generateActionUrls($notifiable, $frontendUrl): array
    {
        $expiration = now()->addDays(7);
        
        $approveApiUrl = URL::temporarySignedRoute(
            'api.leave.public.approve',
            $expiration,
            ['leave' => $this->leave->id, 'approver' => $notifiable->id]
        );

        // Generate signed API URLs
        $approveApiUrl = URL::temporarySignedRoute(
            'api.leave.public.approve',
            $expiration,
            ['leave' => $this->leave->id, 'approver' => $notifiable->id]
        );
        
        $denyApiUrl = URL::temporarySignedRoute(
            'api.leave.public.deny',
            $expiration,
            ['leave' => $this->leave->id, 'approver' => $notifiable->id]
        );
        
        $viewApiUrl = URL::temporarySignedRoute(
            'api.leave.public.view',
            $expiration,
            ['leave' => $this->leave->id, 'viewer' => $notifiable->id]
        );

        // Return frontend URLs with encoded API URLs as parameters
        // dd($frontendUrl);
        
        return [
            'approve' => $frontendUrl . '/leave-action?token=' . base64_encode($approveApiUrl) . '&action=approve',
            'deny' => $frontendUrl . '/leave-action?token=' . base64_encode($denyApiUrl) . '&action=deny',
            'view' => $frontendUrl . '/leave-action?token=' . base64_encode($viewApiUrl) . '&action=view',
        ];
    }

    /**
     * Determine if action buttons should be shown
     */
    private function shouldShowActionButtons($notifiable): bool
    {
        // Show buttons only for pending applications and if user is not the applicant
        return ($this->leave->status == 0 || $this->leave->status == 1) && 
               $this->leave->employee_id != $notifiable->id;
    }

    /**
     * Get status badge text
     */
    private function getStatusBadge(): string
    {
        if ($this->leave->validated == 1) {
            return 'HR Validated';
        } elseif ($this->leave->validated == 99) {
            return 'HR Denied';
        } elseif ($this->leave->status == 2) {
            return 'Approved';
        } elseif ($this->leave->status == 99) {
            return 'Denied';
        } else {
            return 'Pending Review';
        }
    }

    /**
     * Get status color
     */
    private function getStatusColor(): string
    {
        if ($this->leave->validated == 1 || $this->leave->status == 2) {
            return '#28a745'; // Green for approved/validated
        } elseif ($this->leave->validated == 99 || $this->leave->status == 99) {
            return '#dc3545'; // Red for denied
        } else {
            return '#ffc107'; // Yellow for pending
        }
    }

    /**
     * Get readable status text
     */
    private function getStatusText(): string
    {
        if ($this->leave->validated == 1) {
            return 'Validated by HR';
        } elseif ($this->leave->validated == 99) {
            return 'Denied by HR';
        } elseif ($this->leave->status == 2) {
            return 'Approved';
        } elseif ($this->leave->status == 99) {
            return 'Denied';
        } else {
            return 'Pending Review';
        }
    }

    /**
     * Get the array representation of the notification.
     *
     * @return array<string, mixed>
     */
    public function toArray(object $notifiable): array
    {
        $title = null;
        $isApprover = false;

        if($this->leave->validated == 1){
            $title = "Your leave application has been received and validated by HR";
        }else if($this->leave->validated == 99){
            $title = "Your leave application has been denied by HR";
        }else if($this->leave->status == 2){
           $title =  "Your leave application has been approved";
        }else if($this->leave->status == 99){
            $title = "Your leave application has been denied";
        }else{
            $title = $this->leave->employee->firstname . ' ' . $this->leave->employee->lastname." Submitted Leave Application";
            $isApprover = true;
        }  

        return [
            'leave_id' => $this->leave->id,
            'status' => $this->leave->status,
            'approved_at' => $this->leave->approved_at,
            'message' => $this->message,
            'title' => $title,
            'url' => $isApprover ? 'attendance/leave-approval' : 'attendance/leave',
            'created_by' => $this->leave->employee_id
        ];
    }

    /**
     * Generate the message based on leave status.
     */
    private function generateMessage(): string
    {
        $fullname = $this->leave->employee->firstname . ' ' . $this->leave->employee->lastname;
        $date_from = $this->leave->date_from;
        $date_to = $this->leave->date_to;
        $leave_type = $this->leave->leave_type->name;
        $created_at = Carbon::parse($this->leave->created_at)->setTimezone('Asia/Shanghai');

        switch ($this->leave->status) {
            case 1:
            case 0:
                return "$fullname filed a $leave_type application dated \"$date_from\" to \"$date_to\" for your validation.";
            case 2:
                if($this->leave->validated == 1){
                    return "Your application for $leave_type dated \"$date_from\" to \"$date_to\" has been received and validated by HR.";
                }else if($this->leave->validated == 99){
                    return "Your application for $leave_type dated \"$date_from\" to \"$date_to\" has been denied by HR.";
                }else{
                    return "Your application for $leave_type dated \"$date_from\" to \"$date_to\" has been approved.";
                }
                
            case 99:
                return "Your application for $leave_type dated \"$date_from\" to \"$date_to\" has been denied.";
            default:
                return 'Unknown status.';
        }
    }
}