<?php

namespace App\Http\Controllers;

use App\Models\RentServiceBill;
use App\Models\Customer;
use App\Models\ProUnit;
use App\Models\Property;
use Illuminate\Http\Request;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class RentBillingInvoiceController extends Controller
{
    /**
     * Display a listing of invoices.
     */
    public function index(Request $request)
    {
        $companyId = session('CompanyID');
        
        $billingPeriod = $request->input('billing_period');
        $selectedProperty = $request->input('property');
        
        $query = RentServiceBill::with(['customer', 'unit.property'])
            ->where('CompanyID', $companyId);
            
        // Get distinct billing periods for the dropdown
        $billingPeriods = RentServiceBill::where('CompanyID', $companyId)
            ->select('BillingPeriod')
            ->distinct()
            ->orderBy('BillingPeriod', 'desc')
            ->pluck('BillingPeriod')
            ->filter()
            ->map(function($period) {
                // Convert YYYYMM to YYYY-MM for display
                if (preg_match('/^(\d{4})(\d{2})$/', $period, $matches)) {
                    return $matches[1] . '-' . $matches[2];
                }
                return $period;
            });
            
        // Get all properties for the filter dropdown
        $properties = Property::where('CompanyID', $companyId)
            ->orderBy('PropName')
            ->pluck('PropName', 'PropID');
            
        // If no billing period is selected, use the latest one
        if (!$billingPeriod && $billingPeriods->isNotEmpty()) {
            $billingPeriod = $billingPeriods->first();
        }
            
        // Apply billing period filter if provided
        if ($billingPeriod) {
            // Convert YYYY-MM to YYYYMM format for database query
            $dbBillingPeriod = str_replace('-', '', $billingPeriod);
            $query->where('BillingPeriod', 'LIKE', $dbBillingPeriod . '%');
        }

        // Apply property filter if provided
        if ($selectedProperty) {
            $query->whereHas('unit', function($unitQuery) use ($selectedProperty) {
                $unitQuery->where('PropID', $selectedProperty);
            });
        }
      
            
        $invoices = $query->orderBy('BillingDate', 'desc')
            ->paginate(15)
            ->appends(['billing_period' => $billingPeriod, 'property' => $selectedProperty]);

        return view('invoices.rent.index', [
            'invoices' => $invoices,
            'billingPeriods' => $billingPeriods,
            'billingPeriod' => $billingPeriod,
            'properties' => $properties,
            'selectedProperty' => $selectedProperty
        ]);
    }
    
  
    /**
     * Store bulk invoices.
     */
    public function bulkStore(Request $request)
    {
        $validated = $request->validate([
            'billing_period' => 'required|date_format:Y-m',
            'billing_date' => 'required|date',
            'due_date' => 'required|date|after_or_equal:billing_date',
            'unit_ids' => 'required|array',
            'unit_ids.*' => 'exists:ProUnits,UnitID',
        ]);
        
        $companyId = session('CompanyID');
        $createdCount = 0;
        $billingPeriod = str_replace('-', '', $validated['billing_period']);
        
        // Check if invoices already exist for this period
        $existingInvoices = RentServiceBill::where('CompanyID', $companyId)
            ->where('BillingPeriod', $billingPeriod)
            ->whereIn('UnitID', $validated['unit_ids'])
            ->pluck('UnitID')
            ->toArray();
        
        foreach ($validated['unit_ids'] as $unitId) {
            // Skip if invoice already exists for this unit and period
            if (in_array($unitId, $existingInvoices)) {
                continue;
            }
            
            $unit = ProUnit::with('customers')->find($unitId);
            
            if (!$unit || $unit->customers->isEmpty()) {
                continue; // Skip if unit has no customers
            }
            
            // Get the first customer (assuming one customer per unit for now)
            $customer = $unit->customers->first();
            
            // Calculate previous balance (sum of unpaid invoices for this unit)
            $previousBalance = RentServiceBill::where('CompanyID', $companyId)
                ->where('UnitID', $unitId)
                ->whereIn('BillStatus', ['unpaid', 'overdue'])
                ->sum('TotalPayable');
            
            $currentCharges = $unit->MonthlyRent ?? 0;
            $totalAmount = $previousBalance + $currentCharges;
            
            // Create the invoice
            $invoice = new RentServiceBill();
            $invoice->CompanyID = $companyId;
            $invoice->CustomerID = $customer->CustomerID;
            $invoice->UnitID = $unitId;
            $invoice->BillingPeriod = $billingPeriod;
            $invoice->BillingDate = $validated['billing_date'];
            $invoice->DueDate = $validated['due_date'];
            $invoice->CurrentCharges = $currentCharges;
            $invoice->PreviousBalance = $previousBalance;
            $invoice->TotalAmount = $totalAmount;
            $invoice->TotalPayable = $totalAmount;
            $invoice->BillStatus = 'unpaid';
            $invoice->CreatedBy = $this->user()->id;
            $invoice->CreatedAt = now();
            
            $invoice->save();
            $createdCount++;
        }
        
        $message = $createdCount > 0 
            ? "Successfully created $createdCount invoices." 
            : 'No new invoices were created. Invoices may already exist for the selected units and period.';
        
        if ($skipped = (count($validated['unit_ids']) - $createdCount - count($existingInvoices))) {
            $message .= " $skipped units were skipped (no customer or invalid data).";
        }
        
        return redirect()->route('invoices.rent.index')
            ->with('success', $message);
    }

    /**
     * Show the form for creating a new invoice.
     */
    public function create()
    {
        $companyId = session('CompanyID');
        
        $customers = Customer::where('CompanyID', $companyId)
            ->orderBy('CustomerName', 'asc')
            ->get();
            
        // Get units and order by UnitIdentity
        $units = ProUnit::with('property')
            ->orderBy('UnitIdentity', 'asc')
            ->get();
            
        $billingPeriod = Carbon::now()->format('Ym');
        
        return view('invoices.rent.create', compact('customers', 'units', 'billingPeriod'));
    }
    
    /**
     * Store a newly created invoice in storage.
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'CustomerID' => 'required|exists:customer,CustomerID',
            'UnitID' => 'required|exists:ProUnits,UnitID',
            'BillingPeriod' => 'required|date_format:Ym',
            'BillingDate' => 'required|date',
            'DueDate' => 'required|date|after_or_equal:BillingDate',
            'CurrentCharges' => 'required|numeric|min:0',
            'PreviousBalance' => 'required|numeric|min:0',
            'TotalAmount' => 'required|numeric|min:0',
            'BillStatus' => 'required|in:unpaid,paid,overdue',
        ]);
        
        $invoice = new RentServiceBill();
        $invoice->CompanyID = session('CompanyID');
        $invoice->CustomerID = $validated['CustomerID'];
        $invoice->UnitID = $validated['UnitID'];
        $invoice->BillingPeriod = $validated['BillingPeriod'];
        $invoice->BillingDate = $validated['BillingDate'];
        $invoice->DueDate = $validated['DueDate'];
        $invoice->CurrentCharges = $validated['CurrentCharges'];
        $invoice->PreviousBalance = $validated['PreviousBalance'];
        $invoice->TotalAmount = $validated['TotalAmount'];
        $invoice->TotalPayable = $validated['TotalAmount'];
        $invoice->BillStatus = $validated['BillStatus'];
        $invoice->CreatedBy = Auth::id();
        $invoice->CreatedAt = now();
        
        $invoice->save();
        
        return redirect()->route('invoices.rent.show', $invoice->BillID)
            ->with('success', 'Invoice created successfully!');
    }

    /**
     * Display the specified invoice.
     */
    public function show($id)
    {
        $invoice = RentServiceBill::with(['customer', 'unit.property', 'lines', 'payments.receivedBy'])
            ->where('CompanyID', session('CompanyID'))
            ->findOrFail($id);

        // Debug: Log the invoice lines
        Log::info('Invoice Lines:', $invoice->lines->toArray());
        Log::info('Invoice TotalAmount:', ['TotalAmount' => $invoice->TotalAmount]);
        
        $subtotal = $invoice->lines->sum('LineAmount');
        $total = $invoice->TotalAmount;
        
        // Debug: Log calculated values
        Log::info('Calculated Values:', [
            'subtotal' => $subtotal,
            'total' => $total,
            'lines_count' => $invoice->lines->count()
        ]);
        
        // Calculate total payments
        $totalPaid = $invoice->payments->sum('TotalPayment');
        $balance = $total - $totalPaid;

        return view('invoices.rent.show', [
            'invoice' => $invoice,
            'subtotal' => $subtotal,
            'total' => $total,
            'totalPaid' => $totalPaid,
            'balance' => $balance,
            'payments' => $invoice->payments
        ]);
    }

    /**
     * Print the specified invoice.
     */
    public function print($id)
    {
        $invoice = RentServiceBill::with(['customer', 'unit.property', 'lines'])
            ->where('CompanyID', session('CompanyID'))
            ->findOrFail($id);

        $customer = $invoice->customer;
        $totalAmount = $invoice->TotalAmount ?? 0;
        $totalBillAmount = $totalAmount;

        $pdf = PDF::loadView('invoices.rent.print', compact('invoice', 'customer', 'totalAmount', 'totalBillAmount'));
        
        return $pdf->stream("invoice-{$invoice->BillID}.pdf");
    }

    /**
     * Mark an invoice as paid.
     */
    public function markAsPaid($id)
    {
        $invoice = RentServiceBill::where('CompanyID', session('CompanyID'))
            ->findOrFail($id);

        $invoice->update([
            'Status' => 'paid',
            'PaidDate' => now(),
        ]);

        return redirect()->route('invoices.rent.show', $id)
            ->with('success', 'Invoice marked as paid successfully.');
    }

    /**
     * Add adjustment to an invoice.
     */
    public function addAdjustment(Request $request, $id)
    {
        $validated = $request->validate([
            'type' => 'required|in:discount,surcharge,penalty,other',
            'amount' => 'required|numeric|min:0',
            'reason' => 'required|string|max:255',
            'notes' => 'nullable|string',
        ]);

        $invoice = RentServiceBill::where('CompanyID', session('CompanyID'))
            ->findOrFail($id);

        // For now, we'll just update the total amount
        // In a real implementation, you might want to create adjustment records
        $adjustmentAmount = $validated['amount'];
        
        if (in_array($validated['type'], ['discount', 'other'])) {
            $adjustmentAmount = -$adjustmentAmount;
        }

        $newTotal = $invoice->TotalAmount + $adjustmentAmount;
        
        $invoice->update([
            'TotalAmount' => max(0, $newTotal),
            'TotalPayable' => max(0, $newTotal),
        ]);

        return redirect()->route('invoices.rent.show', $id)
            ->with('success', 'Adjustment added successfully.');
    }
}
