<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class BillNotification extends Mailable
{
    use Queueable, SerializesModels;

    public $bill;
    public $customMessage;
    public $subject;
    public $pdfPath;

    /**
     * Create a new message instance.
     *
     * @param  mixed  $bill  The bill data (can be an object or array)
     * @param  string|null  $subject  Optional email subject
     * @param  string|null  $customMessage  Optional custom message
     * @param  string|null  $pdfPath  Optional path to PDF attachment
     * @return void
     */
    public function __construct($bill, $subject = null, $customMessage = null, $pdfPath = null)
    {
        // Log what we received
        \Log::info('BillNotification constructor called', [
            'bill_type' => gettype($bill),
            'bill_class' => is_object($bill) ? get_class($bill) : 'N/A',
            'bill_data' => is_object($bill) ? json_encode($bill) : $bill
        ]);
        
        // If it's a stdClass, it's likely from a DB query, use it as-is
        if (is_object($bill) && get_class($bill) === 'stdClass') {
            // stdClass is fine, we'll use it directly
            $this->bill = $bill;
        }
        // If it's an array, convert to stdClass
        elseif (is_array($bill)) {
            $this->bill = (object) $bill;
        }
        // If it's already a model, use it
        elseif (is_object($bill)) {
            $this->bill = $bill;
        }
        else {
            throw new \InvalidArgumentException('Invalid bill data provided. Expected array, stdClass, or object.');
        }
        
        // Get company ID from bill
        $companyId = $this->bill->CompanyID ?? null;
        
        // Always prepare template variables - load customer data if not already loaded
        $variables = [];
        if (!isset($this->bill->customer) && isset($this->bill->CustomerID)) {
            // Load customer data if not already attached
            $this->bill->customer = \Illuminate\Support\Facades\DB::table('customer')
                ->where('CustomerID', $this->bill->CustomerID)
                ->first();
        }
        
        if (isset($this->bill->CustomerID)) {
            $customer = $this->bill->customer ?? null;
            $company = \Illuminate\Support\Facades\DB::table('company')->where('CompanyID', $companyId)->first();
            
            $variables = [
                'customer_name' => $customer->CustomerName ?? 'Valued Customer',
                'bill_id' => $this->bill->BillID,
                'billing_period' => $this->bill->BillingPeriod,
                'account_number' => $customer->AccountNo ?? 'N/A',
                'total_amount' => 'KES ' . number_format($this->bill->TotalAmount, 2),
                'company_name' => $company->CompanyName ?? config('app.name')
            ];
            
            \Log::info('BillNotification variables prepared', [
                'bill_id' => $this->bill->BillID,
                'customer_id' => $this->bill->CustomerID,
                'variables' => $variables
            ]);
        } else {
            \Log::error('No CustomerID found in bill data', ['bill' => $this->bill]);
        }
        
        // Fetch company templates if subject/message not provided
        if ($companyId && ($subject === null || $customMessage === null)) {
            try {
                if ($subject === null) {
                    $subject = \App\Http\Controllers\CompanySettingsController::getSubjectTemplate($companyId, $variables);
                }
                if ($customMessage === null) {
                    $customMessage = \App\Http\Controllers\CompanySettingsController::getEmailTemplate($companyId, $variables);
                }
                \Log::info('Using company templates in BillNotification', [
                    'company_id' => $companyId,
                    'subject' => $subject,
                    'message_preview' => substr($customMessage, 0, 100) . '...'
                ]);
            } catch (\Exception $e) {
                \Log::error('Failed to fetch company templates in BillNotification', ['error' => $e->getMessage()]);
            }
        }
        
        // Set the other properties with defaults if still null
        $this->subject = $subject ?? 'Invoice Notification';
        $this->customMessage = $customMessage ?? 'Please find your invoice attached.';
        $this->pdfPath = $pdfPath;
        
        // Set the subject if provided
        if ($subject) {
            $this->subject($subject);
        }
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        try {
            // Set the email subject if not already set
            if (!empty($this->subject)) {
                $this->subject($this->subject);
            }

            // Get customer email from bill or attached customer data
            $customerEmail = null;
            if (isset($this->bill->CustomerEmail)) {
                $customerEmail = $this->bill->CustomerEmail;
            }
            elseif (isset($this->bill->customer->CustomerEmail)) {
                $customerEmail = $this->bill->customer->CustomerEmail;
            }

            if (!$customerEmail) {
                throw new \InvalidArgumentException('No customer email address found for this bill.');
            }

            \Log::info('Building email for customer', ['email' => $customerEmail, 'bill_id' => $this->bill->BillID]);

            // Set the recipient and view
            $email = $this->to($customerEmail)
                         ->view('emails.bill-notification')
                         ->with([
                             'bill' => $this->bill,
                             'customMessage' => $this->customMessage,
                         ]);

            // Attach PDF if path is provided and exists
            if ($this->pdfPath && file_exists($this->pdfPath)) {
                $fileSize = filesize($this->pdfPath);
                $fileName = 'Invoice_' . $this->bill->BillID . '.pdf';
                
                \Log::info("Attaching PDF to email - File: {$this->pdfPath}, Size: {$fileSize} bytes, Name: {$fileName}");
                
                try {
                    $email->attach($this->pdfPath, [
                        'as' => $fileName,
                        'mime' => 'application/pdf',
                    ]);
                    \Log::info("Successfully attached PDF to email for bill #{$this->bill->BillID}");
                } catch (\Exception $e) {
                    \Log::error('Failed to attach PDF to email: ' . $e->getMessage());
                    // Re-throw the exception to ensure the job fails and can be retried
                    throw $e;
                }
            } else {
                $errorMsg = $this->pdfPath 
                    ? (file_exists($this->pdfPath) ? 'File exists but cannot be read' : 'File does not exist')
                    : 'No PDF path provided';
                \Log::warning("Cannot attach PDF to email for bill #{$this->bill->BillID}: {$errorMsg}");
            }

            return $email;
            
        } catch (\Exception $e) {
            \Log::error("Error in BillNotification::build() for bill #{$this->bill->BillID}: " . $e->getMessage());
            throw $e; // Re-throw to ensure the job fails and can be retried
        }
    }
}
