<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use App\Mail\BillNotification;
use Illuminate\Support\Facades\Log;

class SendRentInvoiceEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $billId;
    protected $subject;
    protected $message;
    protected $includePdf;
    protected $companyId;
    protected $pdfPath;

    /**
     * The number of times the job may be attempted.
     *
     * @var int
     */
    public $tries = 3;

    /**
     * The number of seconds the job can run before timing out.
     *
     * @var int
     */
    public $timeout = 300; // 5 minutes per job

    /**
     * Create a new job instance.
     *
     * @param string $billId
     * @param string $subject
     * @param string $message
     * @param bool $includePdf
     * @param int $companyId
     * @return void
     */
    public function __construct($billId, $subject, $message, $includePdf, $companyId)
    {
        $this->billId = $billId;
        $this->subject = $subject;
        $this->message = $message;
        $this->includePdf = $includePdf;
        $this->companyId = $companyId;
        $this->pdfPath = null;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        try {
            // Get the bill with customer and lines
            $bill = DB::table('rentservicebill')
                ->where('BillID', $this->billId)
                ->where('CompanyID', $this->companyId)
                ->first();

            if (!$bill) {
                Log::error("Bill not found: {$this->billId}");
                return;
            }

            // Load customer data
            $customer = DB::table('customer')
                ->where('CustomerID', $bill->CustomerID)
                ->first();

            if (!$customer || !$customer->CustomerEmail) {
                Log::error("No email found for customer: {$bill->CustomerID} (Bill #{$bill->BillID})");
                return;
            }

            $bill->customer = $customer;
            
            // Load bill lines
            $bill->lines = DB::table('rentservicebillline')
                            ->where('BillID', $bill->BillID)
                            ->get();

            // Generate PDF if needed
            $pdfPath = null;
            if ($this->includePdf) {
                Log::info("Generating PDF for bill #{$bill->BillID}");
                $pdfPath = $this->generatePdf($bill);
                
                if ($pdfPath && file_exists($pdfPath)) {
                    Log::info("PDF generated successfully at: {$pdfPath} (" . filesize($pdfPath) . " bytes)");
                } else {
                    Log::error("Failed to generate PDF for bill #{$bill->BillID}");
                }
            } else {
                Log::info("PDF generation skipped for bill #{$bill->BillID} (includePdf is false)");
            }

            try {
                Log::info("Sending email to: {$customer->CustomerEmail} for bill #{$bill->BillID}");
                
                // Send email
                $mail = new BillNotification($bill, $this->subject, $this->message, $pdfPath);
                Mail::to($customer->CustomerEmail)->send($mail);
                
                Log::info("Email sent successfully for bill #{$bill->BillID}");
            } catch (\Exception $e) {
                Log::error("Failed to send email for bill #{$bill->BillID}: " . $e->getMessage());
                throw $e;
            } finally {
                // Clean up the temporary PDF file if it was created
                if ($pdfPath && file_exists($pdfPath)) {
                    if (unlink($pdfPath)) {
                        Log::info("Temporary PDF deleted: {$pdfPath}");
                    } else {
                        Log::warning("Failed to delete temporary PDF: {$pdfPath}");
                    }
                }
            }
            
        } catch (\Exception $e) {
            Log::error("Error processing bill #{$this->billId}: " . $e->getMessage());
            throw $e; // This will trigger a retry if attempts remain
        }
    }

    /**
     * Handle a job failure.
     *
     * @param  \Throwable  $exception
     * @return void
     */
    /**
     * Generate PDF for the bill
     * 
     * @param  object  $bill
     * @return string|null Path to the generated PDF or null if generation fails
     */
    protected function generatePdf($bill)
    {
        try {
            // Generate a unique filename with the bill's BillID
            $filename = 'bill_' . $bill->BillID . '_' . now()->format('YmdHis') . '.pdf';
            $path = storage_path('app/temp/' . $filename);
            
            // Ensure the temp directory exists
            $tempDir = dirname($path);
            if (!file_exists($tempDir)) {
                Log::info("Creating temp directory: {$tempDir}");
                if (!mkdir($tempDir, 0755, true)) {
                    throw new \Exception("Failed to create directory: {$tempDir}");
                }
            }

            // Verify directory is writable
            if (!is_writable($tempDir)) {
                throw new \Exception("Directory is not writable: {$tempDir}");
            }

            // Calculate total amount from bill lines
            $totalAmount = collect($bill->lines)->sum('LineAmount');
            Log::info("Generating PDF for bill #{$bill->BillID} with total amount: {$totalAmount}");

            // Verify view exists
            if (!view()->exists('pdf.rentbill')) {
                throw new \Exception("View [pdf.rentbill] not found.");
            }

            // Generate PDF using the rentbill view with the required data
            $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('pdf.rentbill', [
                'invoice' => $bill,
                'customer' => $bill->customer,
                'totalAmount' => $totalAmount,
                'lines' => $bill->lines
            ]);

            // Set paper size and orientation
            $pdf->setPaper('A4', 'portrait');
            
            // Save the PDF to a temporary file
            Log::info("Saving PDF to: {$path}");
            $pdf->save($path);
            
            // Verify the file was created
            if (!file_exists($path)) {
                throw new \Exception("Failed to save PDF to: {$path}");
            }
            
            if (filesize($path) === 0) {
                unlink($path); // Clean up empty file
                throw new \Exception("Generated PDF is empty");
            }

            Log::info("PDF generated successfully: {$path} (" . filesize($path) . " bytes)");
            return $path;
        } catch (\Exception $e) {
            Log::error("Error generating PDF for bill #{$bill->BillID}: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Handle a job failure.
     *
     * @param  \Throwable  $exception
     * @return void
     */
    public function failed(\Throwable $exception)
    {
        // Clean up any temporary PDF file if it exists
        if ($this->pdfPath && file_exists($this->pdfPath)) {
            try {
                unlink($this->pdfPath);
            } catch (\Exception $e) {
                Log::error("Failed to delete temporary PDF file {$this->pdfPath}: " . $e->getMessage());
            }
        }
        
        Log::error('SendRentInvoiceEmail job failed for bill #' . $this->billId . ': ' . $exception->getMessage());
    }
}
