<?php

namespace App\Http\Controllers;

use App\Models\Block;
use App\Models\Property;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class BlockController extends Controller
{
    /**
     * Display a listing of blocks for a property.
     */
    public function index(Property $property)
    {
        // Get the authenticated user's CompanyID
        $companyId = $this->user()->CompanyID;

        $blocks = $property->blocks()
            ->select('BlockID', 'BlockName', 'BlockCode', 'Floors', 'UnitsPerFloor', 'BlockStatus')
            ->orderBy('BlockName')
            ->paginate(10);
            
        return view('blocks.index', compact('property', 'blocks'));
    }

    /**
     * Show the form for creating a new block.
     */
    public function create(Property $property)
    {
        return view('blocks.create', compact('property'));
    }

    /**
     * Store a newly created block in storage.
     */
    public function store(Request $request, Property $property)
    {
        // Get the authenticated user's CompanyID
        $companyId = $this->user()->CompanyID;
        $validated = $request->validate([
            'BlockName' => 'required|string|max:50',
            'BlockCode' => 'required|string|max:20|unique:blocks,BlockCode',
            'Description' => 'nullable|string',
            'Floors' => 'required|integer|min:1|max:100',
            'UnitsPerFloor' => 'required|integer|min:1|max:100',
            'HasLift' => 'boolean',
            'BlockStatus' => 'required|in:Active,Inactive',
        ]);
        
        // Add the CompanyID to the validated data
        $validated['CompanyID'] = $companyId;

        try {
            DB::beginTransaction();
            
            $block = new Block($validated);
            $block->PropID = $property->PropID;
            $block->save();
            
            DB::commit();
            
            return redirect()
                ->route('properties.blocks.show', ['property' => $property->PropID, 'block' => $block->BlockID])
                ->with('success', 'Block created successfully.');
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'Failed to create block: ' . $e->getMessage())->withInput();
        }
    }

    /**
     * Display the specified block with financial data.
     */
    public function show(Property $property, Block $block)
    {
        $block->loadCount('units');
        
        // Get recent bills for the block
        $recentBills = DB::table('rentservicebill')
            ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
            ->where('prounits.BlockID', $block->BlockID)
            ->select('rentservicebill.*', 'prounits.UnitIdentity')
            ->orderBy('rentservicebill.BillingDate', 'desc')
            ->take(5)
            ->get();
            
        // Get upcoming rent dues for units in this block
        $upcomingRentDues = DB::table('rentservicebill')
            ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
            ->where('prounits.BlockID', $block->BlockID)
            ->whereIn('rentservicebill.BillStatus', ['Unpaid', 'Partially Paid'])
            ->where('rentservicebill.BillingDate', '>=', now()->subDays(30))
            ->select(
                'rentservicebill.*', 
                'prounits.UnitIdentity',
                'prounits.UnitID',
                'prounits.BlockID'
            )
            ->orderBy('rentservicebill.BillingDate', 'asc')
            ->limit(5) // Limit to next 5 upcoming dues
            ->get()
            ->map(function ($bill) {
                $dueDate = \Carbon\Carbon::parse($bill->BillingDate);
                $now = now();
                $diffInDays = $now->diffInDays($dueDate, false);
                
                // Determine status and badge class
                if ($diffInDays < 0) {
                    $status = 'Overdue';
                    $badgeClass = 'bg-danger';
                    $dueText = 'Due ' . abs($diffInDays) . ' days ago';
                } elseif ($diffInDays <= 2) {
                    $status = 'Due Soon';
                    $badgeClass = 'bg-warning';
                    $dueText = $diffInDays == 0 ? 'Due today' : "Due in $diffInDays days";
                } else {
                    $status = 'Upcoming';
                    $badgeClass = 'bg-info';
                    $dueText = "Due in $diffInDays days";
                }

                return (object)[
                    'unit' => $bill->UnitIdentity,
                    'dueDate' => $dueDate->format('Y-m-d'),
                    'dueText' => $dueText,
                    'amount' => number_format($bill->TotalPayable, 2),
                    'status' => $status,
                    'badgeClass' => $badgeClass,
                    'billId' => $bill->BillID,
                    'unitId' => $bill->UnitID
                ];
            });
            
        // Get payment summary for the block
        $paymentSummary = [
            'total_billed' => DB::table('rentservicebill')
                ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
                ->where('prounits.BlockID', $block->BlockID)
                ->sum('rentservicebill.TotalAmount'),
                
            'total_paid' => DB::table('payment')
                ->join('rentservicebill', 'payment.CustomerID', '=', 'rentservicebill.CustomerID')
                ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
                ->where('prounits.BlockID', $block->BlockID)
                ->sum('payment.TotalPayment'),
                
            'pending_payments' => DB::table('rentservicebill')
                ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
                ->where('prounits.BlockID', $block->BlockID)
                ->where('rentservicebill.BillStatus', '!=', 'Paid')
                ->count(),
        ];
        
        // Get recent payments for the block
        $recentPayments = DB::table('payment')
            ->join('rentservicebill', 'payment.CustomerID', '=', 'rentservicebill.CustomerID')
            ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
            ->where('prounits.BlockID', $block->BlockID)
            ->select(
                'payment.PaymentID as id',
                'payment.TotalPayment as amount',
                'payment.PaymentDate as payment_date',
                'rentservicebill.BillID as bill_number',
                'prounits.UnitIdentity'
            )
            ->orderBy('payment.PaymentDate', 'desc')
            ->take(5)
            ->get();
            
        // Get occupancy rate
        $totalUnits = $block->units_count;
        $occupiedUnits = DB::table('prounits')
            ->where('BlockID', $block->BlockID)
            ->where('OccupationStatus', 'occupied')
            ->count();
            
        $occupancyRate = $totalUnits > 0 ? round(($occupiedUnits / $totalUnits) * 100, 2) : 0;
        
        // Get recent maintenance requests for the block
        $recentMaintenanceRequests = \App\Models\MaintenanceRequest::with(['unit', 'technician'])
            ->where('block_id', $block->BlockID)
            ->orderBy('created_at', 'desc')
            ->take(5)
            ->get();
        
        return view('blocks.show', compact(
            'property', 
            'block', 
            'recentBills', 
            'recentPayments', 
            'paymentSummary',
            'occupancyRate',
            'recentMaintenanceRequests',
            'upcomingRentDues'
        ));
    }

    /**
     * Show the form for editing the specified block.
     */
    public function edit(Property $property, Block $block)
    {
        return view('blocks.edit', compact('property', 'block'));
    }

    /**
     * Update the specified block in storage.
     */
    public function update(Request $request, Property $property, Block $block)
    {
        $validated = $request->validate([
            'BlockName' => 'required|string|max:50',
            'BlockCode' => 'required|string|max:20|unique:blocks,BlockCode,' . $block->BlockID . ',BlockID',
            'Description' => 'nullable|string',
            'Floors' => 'required|integer|min:1|max:100',
            'UnitsPerFloor' => 'required|integer|min:1|max:100',
            'HasLift' => 'boolean',
            'BlockStatus' => 'required|in:Active,Inactive',
        ]);

        try {
            DB::beginTransaction();
            
            $block->update($validated);
            
            DB::commit();
            
            return redirect()
                ->route('properties.blocks.show', ['property' => $property->PropID, 'block' => $block->BlockID])
                ->with('success', 'Block updated successfully.');
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'Failed to update block: ' . $e->getMessage())->withInput();
        }
    }

    /**
     * Remove the specified block from storage.
     */
    public function destroy(Property $property, Block $block)
    {
        // Don't allow deletion if there are units in the block
        if ($block->units()->exists()) {
            return back()->with('error', 'Cannot delete block with existing units. Please remove all units first.');
        }

        try {
            DB::beginTransaction();
            
            $block->delete();
            
            DB::commit();
            
            return redirect()
                ->route('properties.blocks.index', $property->PropID)
                ->with('success', 'Block deleted successfully.');
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'Failed to delete block: ' . $e->getMessage());
        }
    }

    /**
     * Display the block dashboard with key metrics.
     */
    public function dashboard(Property $property, Block $block)
    {
        $block->loadCount(['units as total_units']);
        
        $occupancyStats = [
            'total' => $block->total_units,
            'occupied' => $block->units()->where('OccupationStatus', 'Occupied')->count(),
            'vacant' => $block->units()->where('OccupationStatus', 'Vacant')->count(),
            'under_maintenance' => $block->units()->where('OccupationStatus', 'Under Maintenance')->count(),
        ];

        $recentUnits = $block->units()
            ->orderBy('UnitID', 'desc')
            ->take(5)
            ->get(['UnitID', 'UnitIdentity', 'FloorNo', 'OccupationStatus', 'MonthlyRent']);

        return view('blocks.dashboard', [
            'property' => $property,
            'block' => $block,
            'occupancyStats' => $occupancyStats,
            'recentUnits' => $recentUnits,
        ]);
    }

    /**
     * Generate a block report.
     */
    /**
     * Generate a block report.
     */
    public function report(Property $property, Block $block)
    {
        // Get paginated units with 10 per page, ordered by unit ID and identity
        $units = $block->units()
            ->orderBy('UnitID', 'asc')
            ->orderBy('UnitIdentity', 'asc')
            ->paginate(10);

        // Get all units for statistics (unpaginated)
        $allUnits = $block->units;

        $reportData = [
            'property' => $property,
            'block' => $block,
            'units' => $units,
            'total_units' => $allUnits->count(),
            'occupancy_rate' => $allUnits->where('OccupationStatus', 'Occupied')->count() / max($allUnits->count(), 1) * 100,
            'units_by_floor' => $allUnits->groupBy('FloorNo')->map->count(),
        ];
        
        return view('blocks.report', $reportData);
    }
    
    /**
     * Export block report as PDF
     */
    public function exportPdf(Property $property, Block $block)
    {
        try {
            // Get all units (no pagination for PDF export)
            $units = $block->units()
                ->orderBy('UnitID', 'asc')
                ->orderBy('UnitIdentity', 'asc')
                ->get();

            // Get payment summary data
            $totalBilled = DB::table('rentservicebill')
                ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
                ->where('prounits.BlockID', $block->BlockID)
                ->sum('rentservicebill.TotalAmount');
                
            $totalPaid = DB::table('payment')
                ->join('rentservicebill', 'payment.CustomerID', '=', 'rentservicebill.CustomerID')
                ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
                ->where('prounits.BlockID', $block->BlockID)
                ->sum('payment.TotalPayment');
                
            $pendingPayments = DB::table('rentservicebill')
                ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
                ->where('prounits.BlockID', $block->BlockID)
                ->where('rentservicebill.BillStatus', '!=', 'Paid')
                ->count();
                
            // Get recent payments
            $recentPayments = DB::table('payment')
                ->join('rentservicebill', 'payment.CustomerID', '=', 'rentservicebill.CustomerID')
                ->join('prounits', 'rentservicebill.UnitID', '=', 'prounits.UnitID')
                ->where('prounits.BlockID', $block->BlockID)
                ->select('payment.*', 'rentservicebill.BillID', 'prounits.UnitIdentity')
                ->orderBy('payment.PaymentDate', 'desc')
                ->take(5)
                ->get();
                
            // Calculate occupancy
            $occupiedUnits = $units->where('OccupationStatus', 'Occupied')->count();
            $totalUnits = $units->count();
            $occupancyRate = $totalUnits > 0 ? ($occupiedUnits / $totalUnits) * 100 : 0;
            
            $reportData = [
                'property' => $property,
                'block' => $block,
                'units' => $units,
                'total_units' => $totalUnits,
                'occupiedUnits' => $occupiedUnits,
                'occupancyRate' => $occupancyRate,
                'units_by_floor' => $units->groupBy('FloorNo')->map->count(),
                'paymentSummary' => [
                    'total_billed' => $totalBilled,
                    'total_paid' => $totalPaid,
                    'pending_payments' => $pendingPayments,
                ],
                'recentPayments' => $recentPayments,
            ];

            // Configure PDF options
            $pdf = PDF::loadView('blocks.report-pdf', $reportData);
            
            // Set paper size and orientation
            $pdf->setPaper('A4', 'portrait');
            
            // Set options for better rendering
            $pdf->setOptions([
                'isHtml5ParserEnabled' => true,
                'isRemoteEnabled' => true,
                'dpi' => 96,
                'defaultFont' => 'DejaVu Sans',
            ]);
            
            // Return the PDF to be displayed in the browser
            return $pdf->stream('block-report-' . $block->BlockCode . '-' . now()->format('Y-m-d') . '.pdf');
            
        } catch (\Exception $e) {
            // Log the error
            Log::error('PDF Generation Error: ' . $e->getMessage());
            
            // Return back with error message
            return back()->with('error', 'Failed to generate PDF: ' . $e->getMessage());
        }
    }
}
