<?php

namespace App\Notifications;

use App\Models\EmployeeOvertime;
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\URL;

class Overtime extends Notification
{
    use Queueable;

    private string $message;

    /**
     * Create a new notification instance.
     */
    public function __construct(private EmployeeOvertime $overtime)
    {
        $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);
        
        $mail = (new MailMessage)
            ->subject('Overtime Notification - AUTOHUB GROUP')
            ->view('emails.overtime', [
                'notifiable' => $notifiable,
                'overtime' => $this->overtime,
                '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->overtime->attachment)
            ]);
        
        // Attach the file if it exists
        if ($this->overtime->attachment) {
            $attachmentPath = storage_path('app/employee-overtime/' . $this->overtime->attachment);
            if (file_exists($attachmentPath)) {
                $mail->attach($attachmentPath, [
                    'as' => $this->overtime->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);
        
        // Generate signed API URLs
        $approveApiUrl = URL::temporarySignedRoute(
            'api.overtime.public.approve',
            $expiration,
            ['overtime' => $this->overtime->id, 'approver' => $notifiable->id]
        );
        
        $denyApiUrl = URL::temporarySignedRoute(
            'api.overtime.public.deny',
            $expiration,
            ['overtime' => $this->overtime->id, 'approver' => $notifiable->id]
        );
        
        $viewApiUrl = URL::temporarySignedRoute(
            'api.overtime.public.view',
            $expiration,
            ['overtime' => $this->overtime->id, 'viewer' => $notifiable->id]
        );

        // Return frontend URLs with encoded API URLs as parameters
        return [
            'approve' => $frontendUrl . '/overtime-action?token=' . base64_encode($approveApiUrl) . '&action=approve',
            'deny' => $frontendUrl . '/overtime-action?token=' . base64_encode($denyApiUrl) . '&action=deny',
            'view' => $frontendUrl . '/overtime-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->overtime->status == 0 || $this->overtime->status == 1) && 
               $this->overtime->employee_id != $notifiable->id;
    }

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

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

    /**
     * Get readable status text
     */
    private function getStatusText(): string
    {
        if ($this->overtime->validated == 1) {
            return 'Validated by HR';
        } elseif ($this->overtime->validated == 99) {
            return 'Denied by HR';
        } elseif ($this->overtime->status == 2) {
            return 'Approved';
        } elseif ($this->overtime->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->overtime->validated == 1){
            $title = "Your overtime application has been received and validated by HR";
        }else if($this->overtime->validated == 99){
            $title = "Your overtime application has been denied by HR";
        }else if($this->overtime->status == 2){
           $title =  "Your overtime application has been approved";
        }else if($this->overtime->status == 99){
            $title = "Your overtime application has been denied";
        }else{
            $title = $this->overtime->employee->firstname . ' ' . $this->overtime->employee->lastname." Submitted Overtime Application";
            $isApprover = true;
        } 

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

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

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