<?php
require_once __DIR__ . '/../models/Lead.php';
require_once __DIR__ . '/../models/Project.php';
require_once __DIR__ . '/../models/Quotation.php';
require_once __DIR__ . '/../models/Invoice.php';
require_once __DIR__ . '/../models/Customer.php';
require_once __DIR__ . '/../models/Document.php';
require_once __DIR__ . '/../models/ProjectPhoto.php';
require_once __DIR__ . '/../models/User.php';
require_once __DIR__ . '/../models/Setting.php';
require_once __DIR__ . '/../models/CmsSlide.php';
require_once __DIR__ . '/../models/CmsService.php';
require_once __DIR__ . '/../models/Blog.php';
require_once __DIR__ . '/../models/Gallery.php';
require_once __DIR__ . '/../models/Testimonial.php';
require_once __DIR__ . '/../core/PdfGenerator.php';

class AdminController extends Controller
{
    public function index(): void
    {
        Auth::guard();
        $leadModel = new Lead();
        $projectModel = new Project();
        $quotationModel = new Quotation();
        $invoiceModel = new Invoice();
        $documentModel = new Document();
        $photoModel = new ProjectPhoto();

        $customerModel = new Customer();
        $stats = [
            'new_leads' => $leadModel->countByStatus('New'),
            'active_projects' => $projectModel->countByStatus('Execution'),
            'quotations_pending' => $quotationModel->countByStatus('Pending'),
            'customers' => $customerModel->count(),
            'invoices_due' => $invoiceModel->countByStatus('Outstanding'),
            'documents' => $documentModel->count(),
            'project_photos' => $photoModel->count(),
        ];

        $this->view('admin.dashboard', [
            'title' => 'Admin Dashboard | Balorp Ventures',
            'stats' => $stats,
        ]);
    }

    public function invoices(): void
    {
        Auth::guard();
        $invoiceModel = new Invoice();
        $invoices = $invoiceModel->all();
        $this->view('admin.invoices', ['title' => 'Invoices | Balorp Ventures', 'invoices' => $invoices]);
    }

    private function seedSampleInvoices(Invoice $invoiceModel, Customer $customerModel): void
    {
        $invoices = $invoiceModel->all();
        if (!empty($invoices)) {
            return;
        }

        $customers = $customerModel->all();
        if (empty($customers)) {
            $customerId = $customerModel->create([
                'name' => 'Balorp Ventures Sample Client',
                'email' => 'client@balorpfinishes.com',
                'phone' => '+233 24 123 4567',
                'company' => 'Balorp Sample Co',
                'address' => 'Accra, Ghana',
                'notes' => 'Sample customer for invoice demonstration.',
            ]);
        } else {
            $customerId = $customers[0]['id'];
        }

        if (!$customerId) {
            return;
        }

        $sampleInvoices = [
            [
                'invoice_number' => 'INV-2026-001',
                'customer_id' => $customerId,
                'total_amount' => 25000.00,
                'paid_amount' => 10000.00,
                'due_date' => date('Y-m-d', strtotime('+14 days')),
                'status' => 'Partial',
                'items' => [
                    ['description' => 'Premium wall finishing', 'quantity' => 1, 'unit_price' => 15000.00],
                    ['description' => 'Interior ceiling painting', 'quantity' => 1, 'unit_price' => 10000.00],
                ],
            ],
            [
                'invoice_number' => 'INV-2026-002',
                'customer_id' => $customerId,
                'total_amount' => 12000.00,
                'paid_amount' => 0.00,
                'due_date' => date('Y-m-d', strtotime('+30 days')),
                'status' => 'Outstanding',
                'items' => [
                    ['description' => 'Kitchen renovation materials', 'quantity' => 1, 'unit_price' => 8000.00],
                    ['description' => 'Project labour', 'quantity' => 1, 'unit_price' => 4000.00],
                ],
            ],
        ];

        foreach ($sampleInvoices as $sample) {
            $newInvoiceId = $invoiceModel->create([
                'invoice_number' => $sample['invoice_number'],
                'customer_id' => $sample['customer_id'],
                'total_amount' => $sample['total_amount'],
                'paid_amount' => $sample['paid_amount'],
                'due_date' => $sample['due_date'],
                'status' => $sample['status'],
            ]);
            if ($newInvoiceId) {
                $invoiceModel->saveItems((int)$newInvoiceId, array_map(function ($item) {
                    return [
                        'description' => $item['description'],
                        'quantity' => $item['quantity'],
                        'unit_price' => $item['unit_price'],
                        'total_price' => $item['quantity'] * $item['unit_price'],
                    ];
                }, $sample['items']));
            }
        }
    }

    public function leads(): void
    {
        Auth::guard();
        $leadModel = new Lead();
        $leads = $leadModel->all();
        
        $this->view('admin.leads', ['title' => 'Leads | Balorp Ventures', 'leads' => $leads]);
    }

    public function viewLead(): void
    {
        Auth::guard();
        $leadId = (int)($_GET['id'] ?? 0);
        $leadModel = new Lead();
        $lead = $leadModel->findById($leadId);
        
        if (!$lead) {
            $this->setFlash('error', 'Lead not found.');
            $this->redirect('/admin/leads');
            return;
        }
        
        $this->view('admin.lead_view', ['title' => 'View Lead | Balorp Ventures', 'lead' => $lead]);
    }

    public function downloadLeadPdf(): void
    {
        Auth::guard();
        $leadId = (int)($_GET['id'] ?? 0);
        $leadModel = new Lead();
        $lead = $leadModel->findById($leadId);
        
        if (!$lead) {
            $this->setFlash('error', 'Lead not found.');
            $this->redirect('/admin/leads');
            return;
        }
        
        $htmlContent = $this->generateLeadPdf($lead);
        $fileName = sprintf('Lead-%s-%s.html', preg_replace('/[^A-Za-z0-9]/', '', $lead['name'] ?? 'unknown'), $leadId);
        
        header('Content-Type: text/html; charset=utf-8');
        header('Content-Disposition: attachment; filename="' . $fileName . '"');
        header('Content-Length: ' . strlen($htmlContent));
        echo $htmlContent;
        exit;
    }

    private function generateLeadPdf(array $lead): string
    {
        $details = $this->parseLeadDetails($lead['notes'] ?? '');
        
        $html = '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Lead Details</title>';
        $html .= '<style>body { font-family: Arial, sans-serif; margin: 30px; } h1 { color: #333; font-size: 24px; margin-bottom: 10px; }';
        $html .= '.section { margin-bottom: 20px; } .label { font-weight: bold; color: #555; margin-bottom: 5px; } .value { margin-top: 5px; } ';
        $html .= '.uploads { margin-top: 10px; } .upload-item { margin: 5px 0; } table { width: 100%; border-collapse: collapse; } td { padding: 8px 0; vertical-align: top; }';
        $html .= '</style></head><body>';
        $html .= '<h1>Lead Details: ' . htmlspecialchars($lead['name'] ?? 'Unknown') . '</h1>';
        $html .= '<table><tr><td><div class="label">Contact Information</div><div class="value">Email: ' . htmlspecialchars($lead['email'] ?? '') . '<br>Phone: ' . htmlspecialchars($lead['phone'] ?? '') . '<br>WhatsApp: ' . htmlspecialchars($lead['whatsapp'] ?? 'Not provided') . '</div></td></tr>';
        $html .= '<tr><td><div class="label">Project Type</div><div class="value">' . htmlspecialchars($lead['project_type'] ?? '') . '</div></td></tr>';
        $html .= '<tr><td><div class="label">Project Nature</div><div class="value">' . htmlspecialchars($lead['project_nature'] ?? 'Not specified') . '</div></td></tr>';
        $html .= '<tr><td><div class="label">Services</div><div class="value">' . htmlspecialchars($lead['services'] ?? 'Not specified') . '</div></td></tr>';
        $html .= '<tr><td><div class="label">Location</div><div class="value">' . htmlspecialchars($lead['location'] ?? '') . '</div></td></tr>';
        $html .= '<tr><td><div class="label">Project Stage</div><div class="value">' . htmlspecialchars($lead['project_stage'] ?? 'Not specified') . '</div></td></tr>';
        $html .= '<tr><td><div class="label">Timeline</div><div class="value">Start: ' . htmlspecialchars($lead['timeline_start'] ?? 'Not specified') . '<br>End: ' . htmlspecialchars($lead['timeline_end'] ?? 'Not specified') . '</div></td></tr>';
        $html .= '<tr><td><div class="label">Site Visit</div><div class="value">' . htmlspecialchars($lead['site_visit'] ?? 'No') . '</div></td></tr>';
        $html .= '<tr><td><div class="label">Additional Details</div><div class="value">' . nl2br(htmlspecialchars($details['additional_details'] ?? $lead['notes'] ?? 'None')) . '</div></td></tr>';
        $html .= '<tr><td><div class="label">Reference</div><div class="value">' . htmlspecialchars($details['reference'] ?? 'Not generated') . '</div></td></tr>';
        if (!empty($lead['uploads'])) {
            $html .= '<tr><td><div class="label">Attachments</div><div class="uploads">';
            foreach ($lead['uploads'] as $file) {
                $html .= '<div class="upload-item">' . htmlspecialchars($file) . '</div>';
            }
            $html .= '</div></td></tr>';
        }
        $html .= '</table></body></html>';
        
        return $html;
    }

    private function parseLeadDetails(string $notes): array
    {
        $result = ['additional_details' => $notes, 'reference' => ''];
        if (preg_match('/Reference:\s*(BV-EST-\d{4}-\d+)/', $notes, $m)) {
            $result['reference'] = $m[1];
        }
        return $result;
    }

    public function downloadLeadAttachment(): void
    {
        Auth::guard();
        $filePath = $_GET['file'] ?? '';
        if (empty($filePath) || str_starts_with($filePath, '..')) {
            $this->setFlash('error', 'Invalid file path.');
            $this->redirect('/admin/leads');
            return;
        }
        
        $fullPath = __DIR__ . '/../../' . $filePath;
        if (!file_exists($fullPath)) {
            $this->setFlash('error', 'File not found.');
            $this->redirect('/admin/leads');
            return;
        }
        
        $mimeType = mime_content_type($fullPath);
        header('Content-Type: ' . $mimeType);
        header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
        header('Content-Length: ' . filesize($fullPath));
        readfile($fullPath);
        exit;
    }

    public function quotations(): void
    {
        Auth::guard();
        $quotationModel = new Quotation();
        $quotations = $quotationModel->all();
        $this->view('admin.quotations', ['title' => 'Quotations | Balorp Ventures', 'quotations' => $quotations]);
    }

    public function customers(): void
    {
        Auth::guard();
        $customerModel = new Customer();
        $customers = $customerModel->allWithBillingSummary();
        $this->view('admin.customers', ['title' => 'Customers | Balorp Ventures', 'customers' => $customers]);
    }

    public function newCustomer(): void
    {
        Auth::guard();

        $this->view('admin.customer_form', [
            'title' => 'Create Customer | Balorp Ventures',
            'customer' => null,
            'formAction' => '/admin/customers/create',
            'pageTitle' => 'Create Customer',
        ]);
    }

    public function createCustomer(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/customers');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/customers/create');
        }

        $name = trim($_POST['name'] ?? '');
        $email = trim($_POST['email'] ?? '');
        $phone = trim($_POST['phone'] ?? '');
        $company = trim($_POST['company'] ?? '');
        $address = trim($_POST['address'] ?? '');
        $notes = trim($_POST['notes'] ?? '');

        if ($name === '') {
            $this->setFlash('error', 'Customer name is required.');
            $this->redirect('/admin/customers/create');
        }

        $customerModel = new Customer();
        $created = $customerModel->create([
            'name' => $name,
            'email' => $email,
            'phone' => $phone,
            'company' => $company,
            'address' => $address,
            'notes' => $notes,
        ]);

        if ($created) {
            $this->setFlash('success', 'Customer added successfully.');
        } else {
            $this->setFlash('error', 'Unable to add customer.');
        }

        $this->redirect('/admin/customers');
    }

    public function editCustomer(): void
    {
        Auth::guard();

        $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            $this->redirect('/admin/customers');
        }

        $customerModel = new Customer();
        $customer = $customerModel->findById($id);
        if (!$customer) {
            $this->redirect('/admin/customers');
        }

        $this->view('admin.customer_form', [
            'title' => 'Edit Customer | Balorp Ventures',
            'customer' => $customer,
            'formAction' => '/admin/customers/update',
            'pageTitle' => 'Edit Customer',
        ]);
    }

    public function updateCustomer(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/customers');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/customers');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $name = trim($_POST['name'] ?? '');
        $email = trim($_POST['email'] ?? '');
        $phone = trim($_POST['phone'] ?? '');
        $company = trim($_POST['company'] ?? '');
        $address = trim($_POST['address'] ?? '');
        $notes = trim($_POST['notes'] ?? '');

        if (!$id || $name === '') {
            $this->setFlash('error', 'Customer name is required.');
            $this->redirect('/admin/customers');
        }

        $customerModel = new Customer();
        $updated = $customerModel->update($id, [
            'name' => $name,
            'email' => $email,
            'phone' => $phone,
            'company' => $company,
            'address' => $address,
            'notes' => $notes,
        ]);

        if ($updated) {
            $this->setFlash('success', 'Customer updated successfully.');
        } else {
            $this->setFlash('error', 'Unable to update customer.');
        }

        $this->redirect('/admin/customers');
    }

    public function portalUsers(): void
    {
        Auth::guard();
        $customerModel = new Customer();
        $customers = $customerModel->all();

        $portalUserModel = new CustomerPortalUser();
        $portalUserModel->createTableIfNotExists();
        $portalUsers = $portalUserModel->all();

        $this->view('admin.customers_portal', [
            'title' => 'Portal Users | Balorp Ventures',
            'customers' => $customers,
            'portalUsers' => $portalUsers,
        ]);
    }

    public function createPortalUser(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/customers/portal');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/customers/portal');
        }

        $customerId = filter_input(INPUT_POST, 'customer_id', FILTER_VALIDATE_INT);
        $username = trim($_POST['username'] ?? '');
        $password = $_POST['password'] ?? '';
        $status = in_array($_POST['status'] ?? 'Active', ['Active', 'Inactive'], true) ? $_POST['status'] : 'Active';

        if (!$customerId || $username === '' || $password === '') {
            $this->setFlash('error', 'Customer, username, and password are required.');
            $this->redirect('/admin/customers/portal');
        }

        $portalUserModel = new CustomerPortalUser();
        $existing = $portalUserModel->findByCustomerId((int)$customerId);
        if ($existing) {
            $this->setFlash('error', 'This customer already has portal access.');
            $this->redirect('/admin/customers/portal');
        }

        $created = $portalUserModel->create([
            'customer_id' => $customerId,
            'username' => $username,
            'password_hash' => password_hash($password, PASSWORD_DEFAULT),
            'status' => $status,
        ]);

        if ($created) {
            $this->setFlash('success', 'Portal user created successfully.');
        } else {
            $this->setFlash('error', 'Unable to create portal user.');
        }

        $this->redirect('/admin/customers/portal');
    }

    public function updateInvoiceStatus(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/invoices');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/invoices');
        }

        $invoiceId = filter_input(INPUT_POST, 'invoice_id', FILTER_VALIDATE_INT);
        $status = in_array($_POST['status'] ?? 'Outstanding', ['Paid', 'Partial', 'Outstanding'], true) ? $_POST['status'] : 'Outstanding';

        if ($invoiceId) {
            $invoiceModel = new Invoice();
            $invoiceModel->updateStatus($invoiceId, $status);
        }

        $this->redirect('/admin/invoices');
    }

    public function newInvoice(): void
    {
        Auth::guard();

        $customerModel = new Customer();
        $customers = $customerModel->all();

        $this->view('admin.invoice_form', [
            'title' => 'Create Invoice | Balorp Ventures',
            'invoice' => null,
            'items' => [],
            'customers' => $customers,
            'formAction' => '/admin/invoices/create',
            'pageTitle' => 'Create Invoice',
        ]);
    }

    public function createInvoice(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/invoices');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/invoices/create');
        }

        $customerId = filter_input(INPUT_POST, 'customer_id', FILTER_VALIDATE_INT);
        $customerId = $customerId ?: null;
        $invoiceNumber = trim($_POST['invoice_number'] ?? '');
        if ($invoiceNumber === '') {
            $invoiceNumber = 'INV-' . date('YmdHis');
        }
        $dueDate = trim($_POST['due_date'] ?? '');
        $status = in_array($_POST['status'] ?? 'Outstanding', ['Paid', 'Partial', 'Outstanding'], true) ? $_POST['status'] : 'Outstanding';
        $paidAmount = filter_input(INPUT_POST, 'paid_amount', FILTER_VALIDATE_FLOAT);
        $paidAmount = $paidAmount !== false ? $paidAmount : 0.00;

        $items = $this->parseInvoiceItems($_POST['items'] ?? []);
        $totalAmount = $this->calculateInvoiceTotal($items);

        $invoiceModel = new Invoice();
        $invoiceId = $invoiceModel->create([
            'invoice_number' => $invoiceNumber,
            'customer_id' => $customerId,
            'total_amount' => $totalAmount,
            'paid_amount' => $paidAmount,
            'due_date' => $dueDate,
            'status' => $status,
        ]);

        if ($invoiceId) {
            $invoiceModel->saveItems((int)$invoiceId, $items);
            $this->setFlash('success', 'Invoice created successfully.');
        } else {
            $this->setFlash('error', 'Unable to create invoice.');
        }

        $this->redirect('/admin/invoices');
    }

    public function editInvoice(): void
    {
        Auth::guard();

        $invoiceId = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$invoiceId) {
            $this->redirect('/admin/invoices');
        }

        $invoiceModel = new Invoice();
        $invoice = $invoiceModel->findWithCustomer($invoiceId);
        if (!$invoice) {
            $this->redirect('/admin/invoices');
        }

        $items = $invoiceModel->getItems($invoiceId);
        $customerModel = new Customer();
        $customers = $customerModel->all();

        $this->view('admin.invoice_form', [
            'title' => 'Edit Invoice | Balorp Ventures',
            'invoice' => $invoice,
            'items' => $items,
            'customers' => $customers,
            'formAction' => '/admin/invoices/update',
            'pageTitle' => 'Edit Invoice',
        ]);
    }

    public function updateInvoice(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/invoices');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/invoices');
        }

        $invoiceId = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if (!$invoiceId) {
            $this->redirect('/admin/invoices');
        }

        $customerId = filter_input(INPUT_POST, 'customer_id', FILTER_VALIDATE_INT);
        $customerId = $customerId ?: null;
        $invoiceNumber = trim($_POST['invoice_number'] ?? '');
        $dueDate = trim($_POST['due_date'] ?? '');
        $status = in_array($_POST['status'] ?? 'Outstanding', ['Paid', 'Partial', 'Outstanding'], true) ? $_POST['status'] : 'Outstanding';
        $paidAmount = filter_input(INPUT_POST, 'paid_amount', FILTER_VALIDATE_FLOAT);
        $paidAmount = $paidAmount !== false ? $paidAmount : 0.00;

        $items = $this->parseInvoiceItems($_POST['items'] ?? []);
        $totalAmount = $this->calculateInvoiceTotal($items);

        $invoiceModel = new Invoice();
        $updated = $invoiceModel->update($invoiceId, [
            'invoice_number' => $invoiceNumber,
            'customer_id' => $customerId,
            'total_amount' => $totalAmount,
            'paid_amount' => $paidAmount,
            'due_date' => $dueDate,
            'status' => $status,
        ]);

        if ($updated) {
            $invoiceModel->saveItems($invoiceId, $items);
            $this->setFlash('success', 'Invoice updated successfully.');
        } else {
            $this->setFlash('error', 'Unable to update invoice.');
        }

        $this->redirect('/admin/invoices');
    }

    public function deleteInvoice(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/invoices');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/invoices');
        }

        $invoiceId = filter_input(INPUT_POST, 'invoice_id', FILTER_VALIDATE_INT);
        if ($invoiceId) {
            $invoiceModel = new Invoice();
            $deleted = $invoiceModel->delete($invoiceId);
            if ($deleted) {
                $this->setFlash('success', 'Invoice deleted successfully.');
            } else {
                $this->setFlash('error', 'Unable to delete invoice.');
            }
        }

        $this->redirect('/admin/invoices');
    }

    public function downloadInvoicePdf(): void
    {
        Auth::guard();

        $invoiceId = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$invoiceId) {
            $this->redirect('/admin/invoices');
        }

        $invoiceModel = new Invoice();
        $invoice = $invoiceModel->findWithCustomer($invoiceId);
        if (!$invoice) {
            $this->redirect('/admin/invoices');
        }

        $items = $invoiceModel->getItems($invoiceId);
        $siteSettings = $this->loadSiteSettings();
        $logoPath = __DIR__ . '/../../images/balorplogo1.png';

        $pdfGenerator = new PdfGenerator();
        $pdfContent = $pdfGenerator->generateInvoicePdf($invoice, $items, $siteSettings, file_exists($logoPath) ? $logoPath : '');

        $documentDir = __DIR__ . '/../../storage/documents';
        if (!is_dir($documentDir)) {
            mkdir($documentDir, 0755, true);
        }

        $filename = 'invoice-' . preg_replace('/[^A-Za-z0-9_-]/', '-', $invoice['invoice_number']) . '.pdf';
        $relativePath = 'storage/documents/' . $filename;
        $absolutePath = $documentDir . '/' . $filename;
        file_put_contents($absolutePath, $pdfContent);

        $documentModel = new Document();
        $existingDocument = $documentModel->findByInvoiceId($invoiceId);
        if ($existingDocument) {
            $documentModel->updateById($existingDocument['id'], [
                'customer_id' => $invoice['customer_id'],
                'project_id' => null,
                'invoice_id' => $invoiceId,
                'title' => 'Invoice ' . $invoice['invoice_number'],
                'file_path' => $relativePath,
                'document_type' => 'Invoice',
            ]);
        } else {
            $documentModel->create([
                'customer_id' => $invoice['customer_id'],
                'project_id' => null,
                'invoice_id' => $invoiceId,
                'title' => 'Invoice ' . $invoice['invoice_number'],
                'file_path' => $relativePath,
                'document_type' => 'Invoice',
            ]);
        }

        // Clear output buffers to avoid corrupting binary PDF output
        while (ob_get_level() > 0) {
            ob_end_clean();
        }

        ini_set('zlib.output_compression', 'Off');

        if (file_exists($absolutePath)) {
            // Send strict download headers
            header_remove();
            header('Content-Description: File Transfer');
            header('Content-Type: application/pdf');
            header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
            header('Content-Transfer-Encoding: binary');
            header('Expires: 0');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header('Pragma: public');
            header('Content-Length: ' . filesize($absolutePath));
            header('Accept-Ranges: bytes');

            readfile($absolutePath);
            flush();
            exit;
        }

        // Fallback: output raw content
        header_remove();
        header('Content-Description: File Transfer');
        header('Content-Type: application/pdf');
        header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . strlen($pdfContent));
        echo $pdfContent;
        exit;
    }

    private function parseInvoiceItems(array $items): array
    {
        $descriptions = $items['description'] ?? [];
        $quantities = $items['quantity'] ?? [];
        $unitPrices = $items['unit_price'] ?? [];
        $result = [];

        foreach ($descriptions as $index => $description) {
            $description = trim($description);
            $quantity = isset($quantities[$index]) ? (int)$quantities[$index] : 0;
            $unitPrice = isset($unitPrices[$index]) ? (float)$unitPrices[$index] : 0.00;

            if ($description === '') {
                continue;
            }

            $result[] = [
                'description' => $description,
                'quantity' => $quantity,
                'unit_price' => $unitPrice,
                'total_price' => $quantity * $unitPrice,
            ];
        }

        return $result;
    }

    private function calculateInvoiceTotal(array $items): float
    {
        $total = 0.00;
        foreach ($items as $item) {
            $total += $item['total_price'];
        }

        return $total;
    }

    public function documents(): void
    {
        Auth::guard();
        $documentModel = new Document();
        $projectModel = new Project();
        $invoiceModel = new Invoice();

        $documents = $documentModel->all();
        $projects = $projectModel->all();
        $invoices = $invoiceModel->all();

        $this->view('admin.documents', [
            'title' => 'Documents | Balorp Ventures',
            'documents' => $documents,
            'projects' => $projects,
            'invoices' => $invoices,
        ]);
    }

    public function uploadDocument(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/documents');
        }

        $title = trim($_POST['title'] ?? '');
        $documentType = $_POST['document_type'] ?? 'Other';
        $projectId = filter_input(INPUT_POST, 'project_id', FILTER_VALIDATE_INT);
        $invoiceId = filter_input(INPUT_POST, 'invoice_id', FILTER_VALIDATE_INT);

        if (empty($title) || empty($_FILES['file']['name'])) {
            $this->setFlash('error', 'Please provide a title and select a PDF document.');
            $this->redirect('/admin/documents');
        }

        $config = require __DIR__ . '/../../config/config.php';
        $uploadDir = $config['admin']['document_dir'];
        $limits = $config['admin']['upload_limits']['document'];
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }

        $file = $_FILES['file'];
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $this->setFlash('error', 'Document upload failed. Please try again.');
            $this->redirect('/admin/documents');
        }

        if ($file['size'] > $limits['max_size']) {
            $this->setFlash('error', 'Document exceeds maximum file size of 5 MB.');
            $this->redirect('/admin/documents');
        }

        $finfo = new finfo(FILEINFO_MIME_TYPE);
        $mimeType = $finfo->file($file['tmp_name']);
        if (!in_array($mimeType, $limits['allowed_types'], true)) {
            $this->setFlash('error', 'Only PDF documents are allowed.');
            $this->redirect('/admin/documents');
        }

        $filename = time() . '-' . preg_replace('/[^A-Za-z0-9\.\-]/', '-', basename($file['name']));
        $filePath = $uploadDir . '/' . $filename;
        $relativePath = 'storage/documents/' . $filename;

        if (move_uploaded_file($file['tmp_name'], $filePath)) {
            $documentModel = new Document();
            $documentModel->create([
                'customer_id' => null,
                'project_id' => $projectId,
                'invoice_id' => $invoiceId,
                'title' => $title,
                'file_path' => $relativePath,
                'document_type' => $documentType,
            ]);
        }

        $this->setFlash('success', 'Document uploaded successfully.');
        $this->redirect('/admin/documents');
    }

    public function projectPhotos(): void
    {
        Auth::guard();
        $photoModel = new ProjectPhoto();
        $projectModel = new Project();

        $photos = $photoModel->all();
        $projects = $projectModel->all();

        $this->view('admin.project_photos', [
            'title' => 'Project Photos | Balorp Ventures',
            'photos' => $photos,
            'projects' => $projects,
        ]);
    }

    public function uploadProjectPhoto(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/project-photos');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/project-photos');
        }

        $projectId = filter_input(INPUT_POST, 'project_id', FILTER_VALIDATE_INT);
        $photoType = $_POST['photo_type'] ?? 'Progress';
        $caption = trim($_POST['caption'] ?? '');

        if (!$projectId || empty($_FILES['file']['name'])) {
            $this->setFlash('error', 'Please select a project and upload a photo file.');
            $this->redirect('/admin/project-photos');
        }

        $config = require __DIR__ . '/../../config/config.php';
        $uploadDir = $config['admin']['photo_dir'];
        $limits = $config['admin']['upload_limits']['photo'];
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }

        $file = $_FILES['file'];
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $this->setFlash('error', 'Photo upload failed. Please try again.');
            $this->redirect('/admin/project-photos');
        }

        if ($file['size'] > $limits['max_size']) {
            $this->setFlash('error', 'Photo exceeds maximum file size of 5 MB.');
            $this->redirect('/admin/project-photos');
        }

        $finfo = new finfo(FILEINFO_MIME_TYPE);
        $mimeType = $finfo->file($file['tmp_name']);
        if (!in_array($mimeType, $limits['allowed_types'], true)) {
            $this->setFlash('error', 'Only JPG, PNG, and WebP photos are allowed.');
            $this->redirect('/admin/project-photos');
        }

        $filename = time() . '-' . preg_replace('/[^A-Za-z0-9\.\-]/', '-', basename($file['name']));
        $filePath = $uploadDir . '/' . $filename;
        $relativePath = 'storage/photos/' . $filename;

        if (move_uploaded_file($file['tmp_name'], $filePath)) {
            $photoModel = new ProjectPhoto();
            $photoModel->create([
                'project_id' => $projectId,
                'photo_type' => $photoType,
                'file_path' => $relativePath,
                'caption' => $caption,
            ]);
        }

        $this->setFlash('success', 'Project photo uploaded successfully.');
        $this->redirect('/admin/project-photos');
    }

    public function settings(): void
    {
        Auth::guard();
        $settingModel = new Setting();
        $settingModel->createTableIfNotExists();

        $this->view('admin.settings', [
            'title' => 'Site Settings | Balorp Ventures',
            'siteSettings' => array_merge($this->loadSiteSettings(), []),
        ]);
    }

    public function updateSettings(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/settings');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/settings');
        }

        $allowedSettings = [
            'topbar_email',
            'topbar_phone',
            'topbar_location',
            'nav_home_label',
            'nav_about_label',
            'nav_services_label',
            'nav_portfolio_label',
            'nav_gallery_label',
            'nav_estimate_label',
            'services_page_title',
            'services_page_description',
            'gallery_page_title',
            'gallery_page_description',
            'wizard_page_title',
            'wizard_page_description',
            'footer_description',
            'footer_contact_email',
            'footer_contact_phone',
            'footer_contact_location',
            'facebook_url',
            'instagram_url',
            'linkedin_url',
            'twitter_url',
            'homepage_hero_badge',
            'homepage_hero_primary_cta',
            'homepage_hero_secondary_cta',
            'homepage_services_intro_title',
            'homepage_services_intro_description',
            'homepage_featured_services_title',
            'homepage_services_title',
            'homepage_services_description',
            'homepage_before_after_title',
            'homepage_before_after_subtitle',
            'homepage_view_all_projects_text',
            'homepage_wizard_section_title',
            'homepage_wizard_section_description',
            'homepage_wizard_button_text',
            'homepage_wizard_feature_preview_label',
            'homepage_wizard_card_1_title',
            'homepage_wizard_card_1_description',
            'homepage_wizard_card_2_title',
            'homepage_wizard_card_2_description',
            'homepage_statistic_projects',
            'homepage_statistic_satisfaction',
            'homepage_statistic_experience',
        ];

        $settings = [];
        foreach ($allowedSettings as $key) {
            $settings[$key] = trim($_POST[$key] ?? '');
        }

        $settingModel = new Setting();
        // Fetch current values to compare
        $before = $settingModel->getMultiple($allowedSettings);

        $changes = [];
        foreach ($settings as $k => $v) {
            $prev = isset($before[$k]) ? $before[$k] : null;
            // Normalize null and empty string for comparison
            $prevNorm = $prev === null ? '' : (string)$prev;
            $newNorm = $v === null ? '' : (string)$v;
            if ($prevNorm !== $newNorm) {
                $changes[$k] = ['before' => $prev, 'after' => $v];
            }
        }

        $success = $settingModel->updateMultiple($settings);
        if ($success) {
            $this->setFlash('success', 'Site settings updated successfully.');
            // Store changes in session for display on page load
            if (!empty($changes)) {
                $_SESSION['settings_changes'] = $changes;
            }
        } else {
            $this->setFlash('error', 'Unable to save site settings.');
        }

        $this->redirect('/admin/settings');
    }

    public function cmsSlides(): void
    {
        Auth::guard();
        $slideModel = new CmsSlide();
        $slideModel->createTableIfNotExists();

        $slides = $slideModel->all();

        // If no slides exist, populate with defaults
        if (empty($slides)) {
            $defaultSlides = [
                [
                    'title' => 'Transforming Structures Into Beautiful Spaces',
                    'subtitle' => 'Premium Building Finishes, Interior Design, Renovations, and Complete Finishing Solutions Delivered with Quality, Craftsmanship, and Attention to Detail.',
                    'image_path' => '/images/slider01.png',
                    'active' => 1,
                ],
                [
                    'title' => 'Balorp Ventures transforms ordinary structures into beautiful, functional, and inspiring spaces.',
                    'subtitle' => 'Whether you\'re building, renovating, or upgrading your property, we deliver exceptional craftsmanship, quality materials, and professional service that bring your vision to life.',
                    'image_path' => '/images/slider02.png',
                    'active' => 1,
                ],
                [
                    'title' => 'From Bare Walls To Elegant Living',
                    'subtitle' => 'Transform your space with premium materials and professional finishing expertise.',
                    'image_path' => '/images/slider03.png',
                    'active' => 1,
                ],
                [
                    'title' => 'Elegant Living Room Finishes',
                    'subtitle' => 'Beautiful finishes designed for comfort, style, and lasting quality.',
                    'image_path' => '/images/slider04.png',
                    'active' => 1,
                ],
                [
                    'title' => 'Modern Commercial Spaces Refined',
                    'subtitle' => 'Commercial fit-outs and finishes that elevate your business environment.',
                    'image_path' => '/images/slider05.png',
                    'active' => 1,
                ],
                [
                    'title' => 'Complete Renovation & Finishing Solutions',
                    'subtitle' => 'From planning to polish, we deliver exceptional finishing results.',
                    'image_path' => '/images/slider06.png',
                    'active' => 1,
                ],
            ];

            foreach ($defaultSlides as $slide) {
                $slideModel->create($slide);
            }

            $slides = $slideModel->all();
        }

        $this->view('admin.cms_slides', [
            'title' => 'Homepage Hero Slides | Balorp Ventures',
            'slides' => $slides,
        ]);
    }

    public function newCmsSlide(): void
    {
        Auth::guard();
        $this->view('admin.cms_slide_form', [
            'title' => 'Create Hero Slide | Balorp Ventures',
            'slide' => [],
            'formAction' => '/admin/cms-slides/create',
            'pageTitle' => 'Create Hero Slide',
        ]);
    }

    private function handleSlideImageUpload(): ?string
    {
        if (!isset($_FILES['slide_image']) || $_FILES['slide_image']['error'] === UPLOAD_ERR_NO_FILE) {
            return null;
        }

        if ($_FILES['slide_image']['error'] !== UPLOAD_ERR_OK) {
            $this->setFlash('error', 'Error uploading image. Please try again.');
            return null;
        }

        $config = require __DIR__ . '/../../config/config.php';
        $uploadDir = $config['admin']['photo_dir'];
        $limits = $config['admin']['upload_limits']['photo'];

        $file = $_FILES['slide_image'];
        $fileName = basename($file['name']);
        $fileSize = $file['size'];
        $fileType = mime_content_type($file['tmp_name']);

        // Validate file
        if ($fileSize > $limits['max_size']) {
            $this->setFlash('error', 'Image size exceeds 5MB limit.');
            return null;
        }

        if (!in_array($fileType, $limits['allowed_types'])) {
            $this->setFlash('error', 'Invalid image format. Use JPG, PNG, or WebP.');
            return null;
        }

        // Create upload directory if it doesn't exist
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }

        // Generate unique filename
        $ext = pathinfo($fileName, PATHINFO_EXTENSION);
        $uniqueName = 'slide_' . time() . '_' . bin2hex(random_bytes(4)) . '.' . $ext;
        $uploadPath = $uploadDir . '/' . $uniqueName;

        // Move uploaded file
        if (!move_uploaded_file($file['tmp_name'], $uploadPath)) {
            $this->setFlash('error', 'Failed to save image. Please try again.');
            return null;
        }

        // Return public path
        return '/storage/photos/' . $uniqueName;
    }

    public function createCmsSlide(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/cms-slides');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/cms-slides/create');
        }

        $title = trim($_POST['title'] ?? '');
        $subtitle = trim($_POST['subtitle'] ?? '');
        $imagePath = trim($_POST['image_path'] ?? '');
        $active = isset($_POST['active']) ? 1 : 0;

        // Handle image upload
        $uploadedPath = $this->handleSlideImageUpload();
        if ($uploadedPath) {
            $imagePath = $uploadedPath;
        }

        if ($title === '' || $imagePath === '') {
            $this->setFlash('error', 'Title and image are required.');
            $this->redirect('/admin/cms-slides/create');
        }

        $slideModel = new CmsSlide();
        $slideModel->create([
            'title' => $title,
            'subtitle' => $subtitle,
            'image_path' => $imagePath,
            'active' => $active,
        ]);

        $this->setFlash('success', 'Hero slide created successfully.');
        $this->redirect('/admin/cms-slides');
    }

    public function editCmsSlide(): void
    {
        Auth::guard();

        $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            $this->redirect('/admin/cms-slides');
        }

        $slideModel = new CmsSlide();
        $slide = $slideModel->find($id);
        if (!$slide) {
            $this->redirect('/admin/cms-slides');
        }

        $this->view('admin.cms_slide_form', [
            'title' => 'Edit Hero Slide | Balorp Ventures',
            'slide' => $slide,
            'formAction' => '/admin/cms-slides/update',
            'pageTitle' => 'Edit Hero Slide',
        ]);
    }

    public function updateCmsSlide(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/cms-slides');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/cms-slides');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $title = trim($_POST['title'] ?? '');
        $subtitle = trim($_POST['subtitle'] ?? '');
        $imagePath = trim($_POST['image_path'] ?? '');
        $active = isset($_POST['active']) ? 1 : 0;

        // Handle image upload
        $uploadedPath = $this->handleSlideImageUpload();
        if ($uploadedPath) {
            $imagePath = $uploadedPath;
        }

        if (!$id || $title === '' || $imagePath === '') {
            $this->setFlash('error', 'Title and image are required.');
            $this->redirect('/admin/cms-slides');
        }

        $slideModel = new CmsSlide();
        $slideModel->update($id, [
            'title' => $title,
            'subtitle' => $subtitle,
            'image_path' => $imagePath,
            'active' => $active,
        ]);

        $this->setFlash('success', 'Hero slide updated successfully.');
        $this->redirect('/admin/cms-slides');
    }

    public function deleteCmsSlide(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/cms-slides');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/cms-slides');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if ($id) {
            $slideModel = new CmsSlide();
            $slideModel->delete($id);
            $this->setFlash('success', 'Hero slide deleted successfully.');
        }

        $this->redirect('/admin/cms-slides');
    }

    public function cmsServices(): void
    {
        Auth::guard();
        $serviceModel = new CmsService();
        $serviceModel->createTableIfNotExists();

        $services = $serviceModel->all();

        // If no services exist, populate with defaults
        if (empty($services)) {
            $defaultServices = [
                [
                    'title' => 'Building Finishes',
                    'summary' => 'Professional painting, screeding, plastering, flooring, tiling, ceilings, and roofing finishes.',
                    'icon' => 'format_paint',
                    'active' => 1,
                ],
                [
                    'title' => 'Interior Décor',
                    'summary' => 'Interior design, wallpaper installation, curtains, lighting design, and wall panels.',
                    'icon' => 'chair',
                    'active' => 1,
                ],
                [
                    'title' => 'Renovations',
                    'summary' => 'Residential and commercial renovations, remodeling, space planning, and project management.',
                    'icon' => 'home_repair_service',
                    'active' => 1,
                ],
                [
                    'title' => 'External Works',
                    'summary' => 'Landscaping design, paving, pathways, and compound beautification services.',
                    'icon' => 'park',
                    'active' => 1,
                ],
            ];

            foreach ($defaultServices as $service) {
                $serviceModel->create($service);
            }

            $services = $serviceModel->all();
        }

        $this->view('admin.cms_services', [
            'title' => 'Homepage Service Cards | Balorp Ventures',
            'services' => $services,
        ]);
    }

    public function newCmsService(): void
    {
        Auth::guard();
        $this->view('admin.cms_service_form', [
            'title' => 'Create Service Card | Balorp Ventures',
            'service' => [],
            'formAction' => '/admin/cms-services/create',
            'pageTitle' => 'Create Service Card',
        ]);
    }

    public function createCmsService(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/cms-services');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/cms-services/create');
        }

        $title = trim($_POST['title'] ?? '');
        $summary = trim($_POST['summary'] ?? '');
        $icon = trim($_POST['icon'] ?? '');
        $active = isset($_POST['active']) ? 1 : 0;

        if ($title === '') {
            $this->setFlash('error', 'Service title is required.');
            $this->redirect('/admin/cms-services/create');
        }

        $serviceModel = new CmsService();
        $serviceModel->create([
            'title' => $title,
            'summary' => $summary,
            'icon' => $icon,
            'active' => $active,
        ]);

        $this->setFlash('success', 'Service card created successfully.');
        $this->redirect('/admin/cms-services');
    }

    public function editCmsService(): void
    {
        Auth::guard();

        $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            $this->redirect('/admin/cms-services');
        }

        $serviceModel = new CmsService();
        $service = $serviceModel->find($id);
        if (!$service) {
            $this->redirect('/admin/cms-services');
        }

        $this->view('admin.cms_service_form', [
            'title' => 'Edit Service Card | Balorp Ventures',
            'service' => $service,
            'formAction' => '/admin/cms-services/update',
            'pageTitle' => 'Edit Service Card',
        ]);
    }

    public function updateCmsService(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/cms-services');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/cms-services');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $title = trim($_POST['title'] ?? '');
        $summary = trim($_POST['summary'] ?? '');
        $icon = trim($_POST['icon'] ?? '');
        $active = isset($_POST['active']) ? 1 : 0;

        if (!$id || $title === '') {
            $this->setFlash('error', 'Service title is required.');
            $this->redirect('/admin/cms-services');
        }

        $serviceModel = new CmsService();
        $serviceModel->update($id, [
            'title' => $title,
            'summary' => $summary,
            'icon' => $icon,
            'active' => $active,
        ]);

        $this->setFlash('success', 'Service card updated successfully.');
        $this->redirect('/admin/cms-services');
    }

    public function deleteCmsService(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/cms-services');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/cms-services');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if ($id) {
            $serviceModel = new CmsService();
            $serviceModel->delete($id);
            $this->setFlash('success', 'Service card deleted successfully.');
        }

        $this->redirect('/admin/cms-services');
    }

    public function users(): void
    {
        Auth::guard();
        $userModel = new User();
        $users = $userModel->all();

        $this->view('admin.users', [
            'title' => 'Admin Users | Balorp Ventures',
            'users' => $users,
        ]);
    }

    public function newUser(): void
    {
        Auth::guard();

        $this->view('admin.user_form', [
            'title' => 'Create Admin User | Balorp Ventures',
            'user' => null,
            'formAction' => '/admin/users/create',
            'pageTitle' => 'Create Admin User',
        ]);
    }

    public function createUser(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/users');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/users/create');
        }

        $name = trim($_POST['name'] ?? '');
        $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
        $password = $_POST['password'] ?? '';
        $phone = trim($_POST['phone'] ?? '');
        $status = in_array($_POST['status'] ?? 'Active', ['Active', 'Inactive'], true) ? $_POST['status'] : 'Active';

        if (!$name || !$email || !$password) {
            $this->setFlash('error', 'Name, email, and password are required.');
            $this->redirect('/admin/users/create');
        }

        $userModel = new User();
        if ($userModel->findByEmail($email)) {
            $this->setFlash('error', 'A user with that email already exists.');
            $this->redirect('/admin/users/create');
        }

        $created = $userModel->create([
            'role_id' => 1,
            'name' => $name,
            'email' => $email,
            'password_hash' => password_hash($password, PASSWORD_DEFAULT),
            'phone' => $phone,
            'status' => $status,
        ]);

        if ($created) {
            $this->setFlash('success', 'Admin user created successfully.');
        } else {
            $this->setFlash('error', 'Unable to create admin user.');
        }

        $this->redirect('/admin/users');
    }

    public function editUser(): void
    {
        Auth::guard();
        $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            $this->redirect('/admin/users');
        }

        $userModel = new User();
        $user = $userModel->findById($id);
        if (!$user) {
            $this->redirect('/admin/users');
        }

        $this->view('admin.user_form', [
            'title' => 'Edit Admin User | Balorp Ventures',
            'user' => $user,
            'formAction' => '/admin/users/update',
            'pageTitle' => 'Edit Admin User',
        ]);
    }

    public function updateUser(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/users');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/users');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $name = trim($_POST['name'] ?? '');
        $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
        $password = $_POST['password'] ?? '';
        $phone = trim($_POST['phone'] ?? '');
        $status = in_array($_POST['status'] ?? 'Active', ['Active', 'Inactive'], true) ? $_POST['status'] : 'Active';

        if (!$id || !$name || !$email) {
            $this->setFlash('error', 'Name and email are required.');
            $this->redirect('/admin/users');
        }

        $userModel = new User();
        $user = $userModel->findById($id);
        if (!$user) {
            $this->setFlash('error', 'Admin user not found.');
            $this->redirect('/admin/users');
        }

        $existing = $userModel->findByEmail($email);
        if ($existing && $existing['id'] !== $id) {
            $this->setFlash('error', 'Another user already uses that email.');
            $this->redirect('/admin/users/edit?id=' . $id);
        }

        $updateData = [
            'name' => $name,
            'email' => $email,
            'phone' => $phone,
            'status' => $status,
        ];

        if ($password !== '') {
            $updateData['password_hash'] = password_hash($password, PASSWORD_DEFAULT);
        }

        $updated = $userModel->updateById($id, $updateData);
        if ($updated) {
            $this->setFlash('success', 'Admin user updated successfully.');
        } else {
            $this->setFlash('error', 'Unable to update admin user.');
        }

        $this->redirect('/admin/users');
    }

    /* ===================== BLOG MANAGEMENT ===================== */
    public function blog(): void
    {
        Auth::guard();
        $blogModel = new Blog();
        $blogModel->createTableIfNotExists();
        $posts = $blogModel->all();
        $this->view('admin.blog', [
            'title' => 'Blog Posts | Balorp Ventures',
            'posts' => $posts,
        ]);
    }

    public function newBlog(): void
    {
        Auth::guard();
        $this->view('admin.blog_form', [
            'title' => 'Create Blog Post | Balorp Ventures',
            'post' => [],
            'formAction' => '/admin/blog/create',
            'pageTitle' => 'Create Blog Post',
        ]);
    }

    public function createBlog(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/blog');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/blog/create');
        }

        $title = trim($_POST['title'] ?? '');
        $slug = trim($_POST['slug'] ?? '');
        $excerpt = trim($_POST['excerpt'] ?? '');
        $content = trim($_POST['content'] ?? '');
        $status = in_array($_POST['status'] ?? 'published', ['draft', 'published'], true) ? $_POST['status'] : 'published';

        if ($title === '' || $slug === '') {
            $this->setFlash('error', 'Title and slug are required.');
            $this->redirect('/admin/blog/create');
        }

        $blogModel = new Blog();
        $blogModel->create([
            'title' => $title,
            'slug' => $slug,
            'excerpt' => $excerpt,
            'content' => $content,
            'status' => $status,
            'published_at' => $status === 'published' ? date('Y-m-d H:i:s') : null,
        ]);

        $this->setFlash('success', 'Blog post created successfully.');
        $this->redirect('/admin/blog');
    }

    public function editBlog(): void
    {
        Auth::guard();
        $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            $this->redirect('/admin/blog');
        }

        $blogModel = new Blog();
        $post = $blogModel->find($id);
        if (!$post) {
            $this->redirect('/admin/blog');
        }

        $this->view('admin.blog_form', [
            'title' => 'Edit Blog Post | Balorp Ventures',
            'post' => $post,
            'formAction' => '/admin/blog/update',
            'pageTitle' => 'Edit Blog Post',
        ]);
    }

    public function updateBlog(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/blog');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/blog');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $title = trim($_POST['title'] ?? '');
        $slug = trim($_POST['slug'] ?? '');
        $excerpt = trim($_POST['excerpt'] ?? '');
        $content = trim($_POST['content'] ?? '');
        $status = in_array($_POST['status'] ?? 'published', ['draft', 'published'], true) ? $_POST['status'] : 'published';

        if (!$id || $title === '' || $slug === '') {
            $this->setFlash('error', 'Title and slug are required.');
            $this->redirect('/admin/blog');
        }

        $blogModel = new Blog();
        $blogModel->update($id, [
            'title' => $title,
            'slug' => $slug,
            'excerpt' => $excerpt,
            'content' => $content,
            'status' => $status,
        ]);

        $this->setFlash('success', 'Blog post updated successfully.');
        $this->redirect('/admin/blog');
    }

    public function deleteBlog(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/blog');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/blog');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if ($id) {
            $blogModel = new Blog();
            $blogModel->delete($id);
            $this->setFlash('success', 'Blog post deleted successfully.');
        }

        $this->redirect('/admin/blog');
    }

    /* ===================== GALLERY MANAGEMENT ===================== */
    public function gallery(): void
    {
        Auth::guard();
        $galleryModel = new Gallery();
        $galleryModel->createTableIfNotExists();
        $items = $galleryModel->all();
        $categories = $galleryModel->categories();
        $this->view('admin.gallery', [
            'title' => 'Gallery | Balorp Ventures',
            'items' => $items,
            'categories' => $categories,
        ]);
    }

    public function newGallery(): void
    {
        Auth::guard();
        $this->view('admin.gallery_form', [
            'title' => 'Add Gallery Image | Balorp Ventures',
            'item' => [],
            'formAction' => '/admin/gallery/create',
            'pageTitle' => 'Add Gallery Image',
        ]);
    }

    public function createGallery(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/gallery');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/gallery/create');
        }

        $title = trim($_POST['title'] ?? '');
        $category = trim($_POST['category'] ?? '');
        $description = trim($_POST['description'] ?? '');
        $imagePath = trim($_POST['image_path'] ?? '');
        $sortOrder = filter_input(INPUT_POST, 'sort_order', FILTER_VALIDATE_INT) ?: 0;
        $status = in_array($_POST['status'] ?? 'published', ['draft', 'published'], true) ? $_POST['status'] : 'published';

        if ($title === '' || $imagePath === '') {
            $this->setFlash('error', 'Title and image path are required.');
            $this->redirect('/admin/gallery/create');
        }

        $galleryModel = new Gallery();
        $galleryModel->create([
            'title' => $title,
            'category' => $category ?: null,
            'description' => $description ?: null,
            'image_path' => $imagePath,
            'sort_order' => $sortOrder,
            'status' => $status,
        ]);

        $this->setFlash('success', 'Gallery item added successfully.');
        $this->redirect('/admin/gallery');
    }

    public function editGallery(): void
    {
        Auth::guard();
        $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            $this->redirect('/admin/gallery');
        }

        $galleryModel = new Gallery();
        $item = $galleryModel->find($id);
        if (!$item) {
            $this->redirect('/admin/gallery');
        }

        $this->view('admin.gallery_form', [
            'title' => 'Edit Gallery Image | Balorp Ventures',
            'item' => $item,
            'formAction' => '/admin/gallery/update',
            'pageTitle' => 'Edit Gallery Image',
        ]);
    }

    public function updateGallery(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/gallery');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/gallery');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $title = trim($_POST['title'] ?? '');
        $category = trim($_POST['category'] ?? '');
        $description = trim($_POST['description'] ?? '');
        $imagePath = trim($_POST['image_path'] ?? '');
        $sortOrder = filter_input(INPUT_POST, 'sort_order', FILTER_VALIDATE_INT) ?: 0;
        $status = in_array($_POST['status'] ?? 'published', ['draft', 'published'], true) ? $_POST['status'] : 'published';

        if (!$id || $title === '' || $imagePath === '') {
            $this->setFlash('error', 'Title and image path are required.');
            $this->redirect('/admin/gallery');
        }

        $galleryModel = new Gallery();
        $galleryModel->update($id, [
            'title' => $title,
            'category' => $category ?: null,
            'description' => $description ?: null,
            'image_path' => $imagePath,
            'sort_order' => $sortOrder,
            'status' => $status,
        ]);

        $this->setFlash('success', 'Gallery item updated successfully.');
        $this->redirect('/admin/gallery');
    }

    public function deleteGallery(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/gallery');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/gallery');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if ($id) {
            $galleryModel = new Gallery();
            $galleryModel->delete($id);
            $this->setFlash('success', 'Gallery item deleted successfully.');
        }

        $this->redirect('/admin/gallery');
    }

    /* ===================== PROJECTS/PORTFOLIO MANAGEMENT ===================== */
    public function projects(): void
    {
        Auth::guard();
        $projectModel = new Project();
        $projects = $projectModel->all();
        $this->view('admin.projects', [
            'title' => 'Portfolio Projects | Balorp Ventures',
            'projects' => $projects,
        ]);
    }

    public function newProject(): void
    {
        Auth::guard();
        $this->view('admin.project_form', [
            'title' => 'Create Project | Balorp Ventures',
            'project' => [],
            'formAction' => '/admin/projects/create',
            'pageTitle' => 'Create Project',
        ]);
    }

    public function createProject(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/projects');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/projects/create');
        }

        $name = trim($_POST['name'] ?? '');
        $clientName = trim($_POST['client_name'] ?? '');
        $status = in_array($_POST['status'] ?? 'Planning', ['Planning', 'Procurement', 'Execution', 'Inspection', 'Completed'], true) ? $_POST['status'] : 'Planning';
        $progress = filter_input(INPUT_POST, 'progress', FILTER_VALIDATE_INT) ?: 0;
        $budget = filter_input(INPUT_POST, 'budget', FILTER_VALIDATE_FLOAT) ?: 0.00;
        $notes = trim($_POST['notes'] ?? '');
        $startDate = trim($_POST['start_date'] ?? '');
        $endDate = trim($_POST['end_date'] ?? '');

        if ($name === '') {
            $this->setFlash('error', 'Project name is required.');
            $this->redirect('/admin/projects/create');
        }

        $projectModel = new Project();
        $projectId = $projectModel->create([
            'name' => $name,
            'client_name' => $clientName,
            'status' => $status,
            'progress' => $progress,
            'budget' => $budget,
            'notes' => $notes,
            'start_date' => $startDate ?: null,
            'end_date' => $endDate ?: null,
        ]);

        if ($projectId) {
            $this->setFlash('success', 'Project created successfully.');
        } else {
            $this->setFlash('error', 'Unable to create project.');
        }

        $this->redirect('/admin/projects');
    }

    public function editProject(): void
    {
        Auth::guard();
        $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            $this->redirect('/admin/projects');
        }

        $projectModel = new Project();
        $project = $projectModel->find($id);
        if (!$project) {
            $this->redirect('/admin/projects');
        }

        $this->view('admin.project_form', [
            'title' => 'Edit Project | Balorp Ventures',
            'project' => $project,
            'formAction' => '/admin/projects/update',
            'pageTitle' => 'Edit Project',
        ]);
    }

    public function updateProject(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/projects');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/projects');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $name = trim($_POST['name'] ?? '');
        $clientName = trim($_POST['client_name'] ?? '');
        $status = in_array($_POST['status'] ?? 'Planning', ['Planning', 'Procurement', 'Execution', 'Inspection', 'Completed'], true) ? $_POST['status'] : 'Planning';
        $progress = filter_input(INPUT_POST, 'progress', FILTER_VALIDATE_INT) ?: 0;
        $budget = filter_input(INPUT_POST, 'budget', FILTER_VALIDATE_FLOAT) ?: 0.00;
        $notes = trim($_POST['notes'] ?? '');
        $startDate = trim($_POST['start_date'] ?? '');
        $endDate = trim($_POST['end_date'] ?? '');

        if (!$id || $name === '') {
            $this->setFlash('error', 'Project name is required.');
            $this->redirect('/admin/projects');
        }

        $projectModel = new Project();
        $projectModel->update($id, [
            'name' => $name,
            'client_name' => $clientName,
            'status' => $status,
            'progress' => $progress,
            'budget' => $budget,
            'notes' => $notes,
            'start_date' => $startDate ?: null,
            'end_date' => $endDate ?: null,
        ]);

        $this->setFlash('success', 'Project updated successfully.');
        $this->redirect('/admin/projects');
    }

    public function deleteProject(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/projects');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/projects');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if ($id) {
            $projectModel = new Project();
            $projectModel->delete($id);
            $this->setFlash('success', 'Project deleted successfully.');
        }

        $this->redirect('/admin/projects');
    }

    /* ===================== TESTIMONIALS MANAGEMENT ===================== */
    public function testimonials(): void
    {
        Auth::guard();
        $testimonialModel = new Testimonial();
        $testimonialModel->createTableIfNotExists();
        $items = $testimonialModel->all();
        $this->view('admin.testimonials', [
            'title' => 'Testimonials | Balorp Ventures',
            'items' => $items,
        ]);
    }

    public function newTestimonial(): void
    {
        Auth::guard();
        $this->view('admin.testimonial_form', [
            'title' => 'Create Testimonial | Balorp Ventures',
            'item' => [],
            'formAction' => '/admin/testimonials/create',
            'pageTitle' => 'Create Testimonial',
        ]);
    }

    public function createTestimonial(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/testimonials');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/testimonials/create');
        }

        $clientName = trim($_POST['client_name'] ?? '');
        $position = trim($_POST['position'] ?? '');
        $company = trim($_POST['company'] ?? '');
        $message = trim($_POST['message'] ?? '');
        $rating = filter_input(INPUT_POST, 'rating', FILTER_VALIDATE_INT) ?: 5;
        $sortOrder = filter_input(INPUT_POST, 'sort_order', FILTER_VALIDATE_INT) ?: 0;
        $status = in_array($_POST['status'] ?? 'published', ['draft', 'published'], true) ? $_POST['status'] : 'published';

        if ($clientName === '' || $message === '') {
            $this->setFlash('error', 'Client name and message are required.');
            $this->redirect('/admin/testimonials/create');
        }

        $testimonialModel = new Testimonial();
        $testimonialModel->create([
            'client_name' => $clientName,
            'position' => $position ?: null,
            'company' => $company ?: null,
            'message' => $message,
            'rating' => $rating,
            'sort_order' => $sortOrder,
            'status' => $status,
        ]);

        $this->setFlash('success', 'Testimonial created successfully.');
        $this->redirect('/admin/testimonials');
    }

    public function editTestimonial(): void
    {
        Auth::guard();
        $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            $this->redirect('/admin/testimonials');
        }

        $testimonialModel = new Testimonial();
        $item = $testimonialModel->find($id);
        if (!$item) {
            $this->redirect('/admin/testimonials');
        }

        $this->view('admin.testimonial_form', [
            'title' => 'Edit Testimonial | Balorp Ventures',
            'item' => $item,
            'formAction' => '/admin/testimonials/update',
            'pageTitle' => 'Edit Testimonial',
        ]);
    }

    public function updateTestimonial(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/testimonials');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/testimonials');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        $clientName = trim($_POST['client_name'] ?? '');
        $position = trim($_POST['position'] ?? '');
        $company = trim($_POST['company'] ?? '');
        $message = trim($_POST['message'] ?? '');
        $rating = filter_input(INPUT_POST, 'rating', FILTER_VALIDATE_INT) ?: 5;
        $sortOrder = filter_input(INPUT_POST, 'sort_order', FILTER_VALIDATE_INT) ?: 0;
        $status = in_array($_POST['status'] ?? 'published', ['draft', 'published'], true) ? $_POST['status'] : 'published';

        if (!$id || $clientName === '' || $message === '') {
            $this->setFlash('error', 'Client name and message are required.');
            $this->redirect('/admin/testimonials');
        }

        $testimonialModel = new Testimonial();
        $testimonialModel->update($id, [
            'client_name' => $clientName,
            'position' => $position ?: null,
            'company' => $company ?: null,
            'message' => $message,
            'rating' => $rating,
            'sort_order' => $sortOrder,
            'status' => $status,
        ]);

        $this->setFlash('success', 'Testimonial updated successfully.');
        $this->redirect('/admin/testimonials');
    }

    public function deleteTestimonial(): void
    {
        Auth::guard();
        if (!$this->isPost()) {
            $this->redirect('/admin/testimonials');
        }

        $token = $_POST['csrf_token'] ?? '';
        if (!CSRF::validate($token)) {
            $this->setFlash('error', 'Invalid CSRF token.');
            $this->redirect('/admin/testimonials');
        }

        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if ($id) {
            $testimonialModel = new Testimonial();
            $testimonialModel->delete($id);
            $this->setFlash('success', 'Testimonial deleted successfully.');
        }

        $this->redirect('/admin/testimonials');
    }
}
