<?php

namespace App\Http\Controllers;

use App\Models\Client;
use App\Models\Payment;
use App\Models\LockerRegistration;
use App\Models\Company;
use App\Models\Invoice;
use App\Services\InvoicePdfGenerator;
use Illuminate\Http\Request;

class InvoiceController extends Controller
{
    public function index(Request $request)
    {
        $query = Invoice::with(['client', 'registration', 'payments'])
            ->orderBy('invoice_date', 'desc');

        // Search by invoice number, client name
        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('invoice_number', 'like', "%{$search}%")
                    ->orWhere('client_name', 'like', "%{$search}%")
                    ->orWhere('client_phone', 'like', "%{$search}%");
            });
        }

        // Filter by status
        if ($request->filled('status') && in_array($request->status, ['paid', 'pending'])) {
            $query->where('status', $request->status);
        }

        // Filter by payment type (create, add, renewal, change)
        if ($request->filled('payment_type') && in_array($request->payment_type, ['create', 'add', 'renewal', 'change'])) {
            $query->where('payment_type', $request->payment_type);
        }

        // Filter by date range
        if ($request->filled('from_date')) {
            $query->whereDate('invoice_date', '>=', $request->from_date);
        }
        if ($request->filled('to_date')) {
            $query->whereDate('invoice_date', '<=', $request->to_date);
        }

        $invoices = $query->paginate(15)->withQueryString();

        // Update invoice status based on payment existence
        foreach ($invoices as $invoice) {
            if ($invoice->payments()->exists()) {
                $invoice->status = 'paid';
            } else {
                $invoice->status = 'pending';
            }
        }

        // Summary statistics by payment type
        $totalInvoices = Invoice::count();
        $paidAmount = Invoice::where('status', 'paid')->sum('total_amount');
        $createCount = Invoice::where('payment_type', 'create')->count();
        $addCount = Invoice::where('payment_type', 'add')->count();
        $renewalCount = Invoice::where('payment_type', 'renewal')->count();
        $changeCount = Invoice::where('payment_type', 'change')->count();

        return view('invoices.index', compact(
            'invoices',
            'totalInvoices',
            'paidAmount',
            'createCount',
            'addCount',
            'renewalCount',
            'changeCount'
        ));
    }

    public function show($client, $registration)
    {
        // Try to find existing invoice first — get the latest one for this registration
        $invoice = Invoice::where('client_id', $client)
            ->where('registration_id', $registration)
            ->latest('id')
            ->first();

        if ($invoice) {
            // Use existing invoice
            $client = $invoice->client;
            $registration = $invoice->registration;

            // Load items filtered by invoice type:
            // For 'change' invoices, only show active items
            // For other types, show all items
            if ($invoice->payment_type === 'change') {
                $registration->setRelation('items', $registration->items()->where('status', 'active')->get());
            }

            $payments = $invoice->payments;
        } else {
            // Create invoice on-the-fly if not exists
            $registration = LockerRegistration::with(['client', 'items', 'locker', 'membershipPlan'])
                ->findOrFail($registration);

            $client = $registration->client;

            // Create invoice record first
            $invoice = $this->createInvoiceFromRegistration($registration);
            $payments = $invoice->payments;
        }

        return view('invoices.show', compact('client', 'payments', 'registration', 'invoice'));
    }

    // Download invoice as PDF using native PHP
    public function download($clientId, $registrationId)
    {
        $client = Client::findOrFail($clientId);
        $registration = LockerRegistration::with('items', 'locker', 'membershipPlan', 'payments')
            ->findOrFail($registrationId);

        // Get payment if exists, otherwise create a dummy payment object for display
        $payment = $registration->payments->first();
        if (!$payment) {
            // Create a dummy payment object for display purposes
            $invoice = new \stdClass();
            $invoice->id = 'INV-' . $registration->id;
            $invoice->payment_date = $registration->registration_date;
            $invoice->total_amount = $registration->items->sum('amount') + ($registration->tax_amount ?? 0) + ($registration->stamping_fee ?? 0) + ($registration->key_deposit ?? 0) + ($registration->insurance_charges ?? 0) - ($registration->discount_amount ?? 0);
            $invoice->status = 'generated';
        }

        // Get company information
        $company = Company::active()->first();
        if (!$company) {
            // Use static company information if no company record exists
            $companyData = [
                'name' => 'May Safe Box',
                'address' => '123 Business Street',
                'city' => 'Chennai',
                'state' => 'Tamil Nadu',
                'pincode' => '600001',
                'gst_number' => 'GSTIN1234567890',
                'phone_number' => '+91 98765 43210'
            ];
        } else {
            $companyData = [
                'name' => $company->name,
                'address' => $company->address,
                'city' => $company->city,
                'state' => $company->state,
                'pincode' => $company->pincode,
                'gst_number' => $company->gst_number,
                'phone_number' => '+91 98765 43210' // Static phone if not in company model
            ];
        }

        // Prepare data for PDF
        $data = [
            'company' => $companyData,
            'invoice_number' => $payment->id,
            'date' => $payment->payment_date ? \Carbon\Carbon::parse($payment->payment_date)->format('d-m-Y') : now()->format('d-m-Y'),
            'client_name' => $client->name,
            'client_phone' => $client->phone,
            'client_address' => $client->address . ', ' . $client->city . ', ' . $client->state . ', ' . $client->country,
            'registration_id' => $registration->id,
            'membership_plan' => $registration->membershipPlan->name ?? 'N/A',
            'contract_period' => $registration->contract_start_date . ' to ' . $registration->contract_end_date,
            'items' => $registration->items->map(function ($item) {
                return [
                    'locker_number' => $item->locker_number,
                    'size' => $item->size,
                    'type' => $item->type,
                    'amount' => $item->amount
                ];
            })->toArray(),
            'total_amount' => $payment->total_amount
        ];

        // Generate PDF using InvoicePdfGenerator
        $pdfGenerator = new InvoicePdfGenerator();
        $pdfContent = $pdfGenerator->generate($client, $payment, $registration);

        $fileName = 'invoice_'
            . preg_replace('/[^A-Za-z0-9\-]/', '_', $client->name)
            . '_'
            . ($payment->payment_date ? \Carbon\Carbon::parse($payment->payment_date)->format('d-m-Y') : now()->format('d-m-Y'))
            . '.pdf';

        // Return PDF as download
        return response($pdfContent)
            ->header('Content-Type', 'application/pdf')
            ->header('Content-Disposition', 'attachment; filename="' . $fileName . '"')
            ->header('Content-Length', strlen($pdfContent));
    }

    /**
     * Create invoice from registration data
     */
    private function createInvoiceFromRegistration($registration)
    {
        // Get company information
        $company = Company::active()->first();
        $companyData = [
            'name' => $company ? $company->name : 'May Safe Box',
            'address' => $company ? $company->address : '123 Business Street',
            'city' => $company ? $company->city : 'Chennai',
            'state' => $company ? $company->state : 'Tamil Nadu',
            'pincode' => $company ? $company->pincode : '600001',
            'gst_number' => $company ? $company->gst_number : 'GSTIN1234567890',
        ];

        // Calculate subtotal from items
        $subtotal = $registration->items->sum('amount');

        // Prepare locker items data
        $itemsData = $registration->items->map(function ($item) {
            return [
                'locker_number' => $item->locker_number,
                'size' => $item->size,
                'type' => $item->type,
                'amount' => $item->amount
            ];
        })->toArray();

        // Calculate total amount
        $totalAmount = $subtotal + ($registration->tax_amount ?? 0) + ($registration->stamping_fee ?? 0) + ($registration->key_deposit ?? 0) + ($registration->insurance_charges ?? 0) - ($registration->discount_amount ?? 0);

        // Create invoice
        return Invoice::create([
            'invoice_number' => Invoice::generateInvoiceNumber(),
            'client_id' => $registration->client_id,
            'registration_id' => $registration->id,
            'invoice_date' => $registration->registration_date,
            'subtotal' => $subtotal,
            'tax_amount' => $registration->tax_amount ?? 0,
            'stamping_fee' => $registration->stamping_fee ?? 0,
            'key_deposit' => $registration->key_deposit ?? 0,
            'insurance_charges' => $registration->insurance_charges ?? 0,
            'discount_amount' => $registration->discount_amount ?? 0,
            'total_amount' => $totalAmount,
            'status' => 'draft',
            'payment_mode' => $registration->payment_mode,
            'payment_type' => 'create',
            'client_name' => $registration->client->name,
            'client_phone' => $registration->client->phone,
            'client_address' => $registration->client->address . ', ' . $registration->client->city . ', ' . $registration->client->state . ', ' . $registration->client->country,
            'notes' => 'Auto-generated from registration',
            'items_data' => $itemsData,
            'membership_plan' => $registration->membershipPlan->name ?? 'N/A',
            'contract_start_date' => $registration->contract_start_date,
            'contract_end_date' => $registration->contract_end_date,
            // New database columns
            'account_type_id' => $registration->account_type_id,
            'email' => $registration->client->email ?? '',
            'safebox' => $registration->client->safebox ?? '',
            'postal_code' => $registration->client->postal_code ?? 0,
            'city' => $registration->client->city ?? '',
            'state' => $registration->client->state ?? '',
            'country' => $registration->client->country ?? '',
            'registration_number' => $registration->registration_number ?? '',
            'tax_type' => $registration->tax_type ?? 'gst',
            'safebox_count' => $registration->safebox_count ?? 1,
            'payment_terms' => $registration->payment_terms ?? 30,
            'referred_member_by' => $registration->referred_member_by,
            'referred_commission' => $registration->referred_commission ?? 0,
            'commission_used' => $registration->commission_used ?? 0,
            'registration_date' => $registration->registration_date ?? now(),
            'locker_id' => $registration->locker_id,
            'locker_number' => $registration->items->pluck('locker_number')->implode(', '),
            'size' => $registration->size ?? '',
            'type' => $registration->type ?? '',
            'locker_group' => $registration->locker_group ?? '',
            'locker_position' => $registration->locker_position ?? '',
            'start_date' => $registration->start_date ?? now(),
            'end_date' => $registration->end_date ?? now()->addYear(),
            'amount' => $registration->amount ?? 0,
        ]);
    }

    public function saveInvoice(Request $request)
    {
        $validatedData = $request->validate([
            'invoice_number' => 'required',
            'client_id' => 'required',
            'status' => 'required|in:create,add,renewal,change',
            // Add other validation rules as needed
        ]);

        // Check if an invoice with the same invoice_number exists
        $existingInvoice = Invoice::where('invoice_number', $request->invoice_number)->first();

        if ($existingInvoice) {
            // Create a new record instead of updating the existing one
            $newInvoice = $existingInvoice->replicate();
            $newInvoice->status = 'new'; // Set the new status
            $newInvoice->save();

            return response()->json(['message' => 'New invoice created successfully.']);
        } else {
            // Create a new invoice
            $invoice = new Invoice($validatedData);
            $invoice->save();

            return response()->json(['message' => 'Invoice created successfully.']);
        }
    }

    /**
     * Map payment status to invoice status
     */
    private function mapPaymentStatus($paymentStatus): string
    {
        return match ($paymentStatus) {
            'paid' => 'paid',
            'pending' => 'pending',
        };
    }
}
