<?php

namespace App\Services;

use PDF;
use Illuminate\Support\Facades\View;
use App\Modules\Invoices\Invoice;
use App\Modules\Invoices\Sale;
use Setting;

class InvoicePdfService
{
    /**
     * Generate PDF for an invoice
     *
     * @param Invoice|Sale $invoice
     * @param bool $download Whether to download or stream
     * @return \Illuminate\Http\Response
     */
    public function generatePdf($invoice, $download = false)
    {
        try {
            // Load relationships
            $invoice->load('items', 'client');
            
            // Load sites only for clients (not customers)
            if ($invoice->client && $invoice->client_type === 'client') {
                $invoice->client->load('sites');
            }
        
        // Get company settings
        $companySettings = $this->getCompanySettings();
        
        // Prepare data for the PDF template
        $data = [
            'invoice' => $invoice,
            'company' => $companySettings,
            'client' => $invoice->client,
            'items' => $invoice->items,
            'subtotal' => $this->calculateSubtotal($invoice),
            'vatAmount' => $this->calculateVatAmount($invoice),
            'finalTotal' => $this->calculateTotal($invoice),
            'accountCode' => $this->generateAccountCode($invoice),
        ];
        
        // Generate the PDF
        $pdf = PDF::loadView('pdf.invoice-simple', $data);
        $pdf->setPaper('A4', 'portrait');
        
        $filename = $this->generateFilename($invoice);
        
            if ($download) {
                return $pdf->download($filename);
            } else {
                return $pdf->stream($filename);
            }
        } catch (\Exception $e) {
            \Log::error('InvoicePdfService error: ' . $e->getMessage(), [
                'invoice_id' => $invoice->id ?? 'unknown',
                'invoice_number' => $invoice->invoice_number ?? 'unknown',
                'client_type' => $invoice->client_type ?? 'unknown',
                'client_id' => $invoice->client_id ?? 'unknown',
                'exception' => $e
            ]);
            throw $e;
        }
    }
    
    /**
     * Save PDF to storage and return path
     *
     * @param Invoice|Sale $invoice
     * @return string Path to saved PDF
     */
    public function savePdf($invoice)
    {
        // Load relationships
        $invoice->load('items', 'client');
        
        // Load sites only for clients (not customers)
        if ($invoice->client && $invoice->client_type === 'client') {
            $invoice->client->load('sites');
        }
        
        // Get company settings
        $companySettings = $this->getCompanySettings();
        
        // Prepare data for the PDF template
        $data = [
            'invoice' => $invoice,
            'company' => $companySettings,
            'client' => $invoice->client,
            'items' => $invoice->items,
            'subtotal' => $this->calculateSubtotal($invoice),
            'vatAmount' => $this->calculateVatAmount($invoice),
            'finalTotal' => $this->calculateTotal($invoice),
            'accountCode' => $this->generateAccountCode($invoice),
        ];
        
        // Generate the PDF
        $pdf = PDF::loadView('pdf.invoice-simple', $data);
        $pdf->setPaper('A4', 'portrait');
        
        $filename = $this->generateFilename($invoice);
        $path = storage_path('app/public/invoices/' . $filename);
        
        // Ensure directory exists
        $directory = dirname($path);
        if (!file_exists($directory)) {
            mkdir($directory, 0755, true);
        }
        
        // Save the PDF
        $pdf->save($path);
        
        return 'storage/invoices/' . $filename;
    }
    
    /**
     * Get company settings for the invoice
     *
     * @return array
     */
    private function getCompanySettings()
    {
        return [
            'name' => env('COMPANY_NAME', 'Your Company Name'),
            'subtitle' => env('COMPANY_SUBTITLE', ''),
            'address1' => env('COMPANY_ADDRESS1', ''),
            'address2' => env('COMPANY_ADDRESS2', ''),
            'address3' => env('COMPANY_ADDRESS3', ''),
            'postcode' => env('COMPANY_POSTCODE', ''),
            'country' => env('COMPANY_COUNTRY', 'United Kingdom'),
            'phone' => env('COMPANY_PHONE', ''),
            'email' => env('COMPANY_EMAIL', ''),
            'vat_number' => env('COMPANY_VAT_NUMBER', ''),
            'logo_path' => public_path('images/icons/logo.png'),
            'logo_url' => url('images/icons/logo.png'),
        ];
    }
    
    /**
     * Calculate subtotal (excluding VAT)
     *
     * @param Invoice|Sale $invoice
     * @return float
     */
    private function calculateSubtotal($invoice)
    {
        $total = 0;
        foreach ($invoice->items as $item) {
            $total += $item->quantity * $item->price_sold_exc;
        }

        // If prices include VAT, calculate the net amount by removing VAT
        if ($invoice->include_vat) {
            // Net = Total / (1 + VAT rate)
            $vatRate = $invoice->vat / 100;
            $netAmount = $total / (1 + $vatRate);
            return $netAmount;
        }

        // If prices exclude VAT, the total is already the net amount
        return $total;
    }
    
    /**
     * Calculate VAT amount
     *
     * @param Invoice|Sale $invoice
     * @return float
     */
    private function calculateVatAmount($invoice)
    {
        $total = 0;
        foreach ($invoice->items as $item) {
            $total += $item->quantity * $item->price_sold_exc;
        }

        $vatRate = $invoice->vat / 100;

        // If prices include VAT, extract the VAT amount
        if ($invoice->include_vat) {
            $netAmount = $total / (1 + $vatRate);
            $vatAmount = $total - $netAmount;
            return $vatAmount;
        }

        // If prices exclude VAT, calculate VAT on top
        return $total * $vatRate;
    }
    
    /**
     * Calculate total including VAT
     *
     * @param Invoice|Sale $invoice
     * @return float
     */
    private function calculateTotal($invoice)
    {
        $total = 0;
        foreach ($invoice->items as $item) {
            $total += $item->quantity * $item->price_sold_exc;
        }

        // If prices include VAT, the total is already correct
        if ($invoice->include_vat) {
            return $total;
        }

        // If prices exclude VAT, add VAT to get final total
        $vatRate = $invoice->vat / 100;
        return $total * (1 + $vatRate);
    }
    
    /**
     * Generate filename for the PDF
     *
     * @param Invoice|Sale $invoice
     * @return string
     */
    private function generateFilename($invoice)
    {
        $type = $invoice->type == 'sale' ? 'Receipt' : 'Invoice';
        $number = $invoice->invoice_number ?? $invoice->id;
        return "{$type}_{$number}.pdf";
    }
    
    /**
     * Get URL for accessing saved PDF
     *
     * @param Invoice|Sale $invoice
     * @return string
     */
    public function getPdfUrl($invoice)
    {
        $filename = $this->generateFilename($invoice);
        return url('storage/invoices/' . $filename);
    }
    
    /**
     * Generate account code for customer/client
     * Based on KashFlow account code generation pattern
     *
     * @param Invoice|Sale $invoice
     * @return string
     */
    private function generateAccountCode($invoice)
    {
        if (!$invoice->client) {
            return '';
        }
        
        // If it's a client with account_code, use that
        if ($invoice->client_type === 'client' && !empty($invoice->client->account_code)) {
            return $invoice->client->account_code;
        }
        
        // For customers, generate code based on KashFlow pattern
        if ($invoice->client_type === 'customer') {
            $fullName = '';
            
            // Determine the name to use for code generation
            if (!empty($invoice->client->name)) {
                // Use business name if available
                $fullName = $invoice->client->name;
            } else {
                // Fall back to first + last name
                $firstName = $invoice->client->first_name ?? '';
                $lastName = $invoice->client->last_name ?? '';
                $fullName = trim($firstName . ' ' . $lastName);
            }
            
            if ($fullName) {
                // Remove special characters and spaces, keep only letters
                $cleanName = preg_replace('/[^A-Za-z]/', '', $fullName);
                
                // Take first 4 characters, uppercase
                $prefix = strtoupper(substr($cleanName, 0, 4));
                
                // Pad if less than 4 characters
                $prefix = str_pad($prefix, 4, 'X', STR_PAD_RIGHT);
                
                // Use client ID modulo to generate consistent 2-digit number (01-99)
                $number = str_pad(($invoice->client_id % 99) + 1, 2, '0', STR_PAD_LEFT);
                
                return $prefix . $number;
            }
        }
        
        return '';
    }
}