<?php
namespace App\Controllers;

use Core\Controller;
use App\Helpers\Helper;

class BookingController extends Controller
{
    public function __construct()
    {
        parent::__construct();
    }

    public function form(string $unitId): void
    {
        // Must be logged in
        if (empty($_SESSION['user_id'])) {
            Helper::setFlash('warning', 'Please log in or register to book a unit.');
            $this->redirect(APP_URL . '/login?redirect=' . urlencode(APP_URL . '/book/' . $unitId));
            return;
        }
        // Must have verified email
        $user = $this->db->fetch("SELECT * FROM users WHERE id=?", [$_SESSION['user_id']]);
        if (!$user || $user['status'] !== 'active' || empty($user['email_verified_at'])) {
            Helper::setFlash('warning', 'You must verify your email before making a booking. Please check your inbox.');
            $this->redirect(APP_URL . '/tenant');
            return;
        }

        $unit = $this->db->fetch("SELECT u.*, b.name AS building_name, p.name AS property_name, p.id AS property_id, r.name AS region_name FROM units u JOIN buildings b ON b.id=u.building_id JOIN properties p ON p.id=u.property_id LEFT JOIN regions r ON r.id=p.region_id WHERE u.id=?", [$unitId]);
        if (!$unit || $unit['status'] !== 'available') { $this->abort(404); return; }
        $this->view('booking.form', compact('unit','user') + ['title' => 'Book Unit - '.$unit['unit_number']], 'main');
    }

    public function store(): void
    {
        $this->verifyCsrf();

        // Must be logged in with verified email
        if (empty($_SESSION['user_id'])) {
            Helper::setFlash('warning', 'Please log in to make a booking.');
            $this->redirect(APP_URL . '/login');
            return;
        }
        $user = $this->db->fetch("SELECT * FROM users WHERE id=?", [$_SESSION['user_id']]);
        if (!$user || $user['status'] !== 'active' || empty($user['email_verified_at'])) {
            Helper::setFlash('warning', 'Your email must be verified before booking.');
            $this->redirect(APP_URL . '/tenant');
            return;
        }

        $unitId = (int)$this->input('unit_id');
        $unit = $this->db->fetch("SELECT u.*, p.name AS property_name, p.address FROM units u JOIN properties p ON p.id=u.property_id WHERE u.id=? AND u.status='available'", [$unitId]);
        if (!$unit) {
            Helper::setFlash('danger', 'This unit is no longer available.');
            $this->redirect(APP_URL . '/residences');
            return;
        }

        $ref = Helper::generateRef('BKG');
        $data = [
            'booking_ref'         => $ref,
            'user_id'             => (int)$_SESSION['user_id'],
            'unit_id'             => $unitId,
            'property_id'         => (int)$this->input('property_id'),
            'visitor_name'        => Helper::sanitize($this->input('visitor_name', $user['first_name'].' '.$user['last_name'])),
            'visitor_email'       => filter_var($this->input('visitor_email', $user['email']), FILTER_SANITIZE_EMAIL) ?: $user['email'],
            'visitor_phone'       => Helper::sanitize($this->input('visitor_phone', $user['phone'] ?? '')),
            'desired_move_in'     => $this->input('desired_move_in') ?: null,
            'desired_lease_period'=> (int)$this->input('desired_lease_period', 1),
            'lease_period_unit'   => in_array($this->input('lease_period_unit'), ['day','week','month']) ? $this->input('lease_period_unit') : 'month',
            'booking_fee'         => (float)$this->input('booking_fee', 0),
            'payment_status'      => 'unpaid',
            'status'              => 'awaiting_payment',
            'notes'               => $this->input('notes','') ?: null,
            'created_at'          => date('Y-m-d H:i:s'),
            'updated_at'          => date('Y-m-d H:i:s'),
        ];

        if (!empty($_FILES['visitor_id_document']['name'])) {
            $path = Helper::uploadFile($_FILES['visitor_id_document'], 'documents', ALLOWED_DOC_TYPES);
            if ($path) $data['visitor_id_document'] = $path;
        }

        try {
            $this->db->insert('bookings', $data);
            // Send booking confirmation email
            $this->sendBookingEmail($user, $unit, $ref, $data);
            Helper::setFlash('info', 'Booking request received! Ref: <strong>'.$ref.'</strong>. Please complete payment to confirm your booking.');
            $this->redirect(APP_URL . '/booking/confirm/' . $ref);
        } catch (\Exception $e) {
            Helper::setFlash('danger', 'Booking failed. Please try again.');
            $this->back();
        }
    }

    private function sendBookingEmail(array $user, array $unit, string $ref, array $data): void
    {
        $rows = $this->db->fetchAll("SELECT `key`, value FROM settings WHERE `group`='email'");
        $cfg  = [];
        foreach ($rows as $r) { $cfg[$r['key']] = $r['value']; }

        $host     = trim($cfg['smtp_host']        ?? '');
        $port     = (int)($cfg['smtp_port']        ?? 587);
        $smtpUser = trim($cfg['smtp_username']     ?? '');
        $pass     = $cfg['smtp_password']           ?? '';
        $from     = trim($cfg['mail_from_address']  ?? $smtpUser);
        $fromName = trim($cfg['mail_from_name']     ?? APP_NAME);
        $enc      = strtolower(trim($cfg['smtp_encryption'] ?? ($port == 465 ? 'ssl' : 'tls')));

        if (!$host || !$smtpUser || !$pass) return;

        $to       = $data['visitor_email'];
        $name     = $data['visitor_name'];
        $appName  = APP_NAME;
        $year     = date('Y');
        $unitNum  = $unit['unit_number'];
        $propName = $unit['property_name'];
        $moveIn   = $data['desired_move_in'] ? date('d M Y', strtotime($data['desired_move_in'])) : 'To be confirmed';
        $duration = $data['desired_lease_period'] . ' ' . $data['lease_period_unit'] . ($data['desired_lease_period'] > 1 ? 's' : '');
        $confirmUrl = APP_URL . '/booking/confirm/' . $ref;

        $html = <<<HTML
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"></head>
<body style="margin:0;padding:0;background:#f0f4f8;font-family:'Segoe UI',Arial,sans-serif">
<table width="100%" cellpadding="0" cellspacing="0" style="background:#f0f4f8;padding:40px 0">
<tr><td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background:#fff;border-radius:16px;overflow:hidden;box-shadow:0 4px 24px rgba(0,0,0,.10)">
  <tr><td style="background:linear-gradient(135deg,#1a3c5e,#2d6a9f);padding:40px;text-align:center">
    <h1 style="color:#fff;margin:0;font-size:28px;font-weight:800">{$appName}</h1>
    <p style="color:rgba(255,255,255,.8);margin:8px 0 0;font-size:14px">Booking Confirmation</p>
  </td></tr>
  <tr><td style="background:#e8f4fd;padding:20px 40px;text-align:center;border-bottom:1px solid #d0e8f7">
    <span style="font-size:48px">🏠</span>
    <h2 style="color:#1a3c5e;margin:8px 0 0;font-size:22px">Booking Received, {$name}!</h2>
  </td></tr>
  <tr><td style="padding:40px">
    <p style="color:#374151;font-size:16px;line-height:1.7;margin:0 0 20px">
      Your booking request has been successfully submitted. Our team will review it and contact you as soon as possible.
    </p>
    <div style="background:#f8fafc;border-radius:12px;padding:24px;margin:0 0 28px;border-left:4px solid #1a3c5e">
      <h3 style="color:#1a3c5e;margin:0 0 16px;font-size:16px">Booking Summary</h3>
      <table cellpadding="0" cellspacing="0" width="100%">
        <tr><td style="padding:6px 0;color:#6b7280;font-size:14px;width:140px">Booking Ref:</td><td style="padding:6px 0;color:#111827;font-weight:700;font-size:15px">{$ref}</td></tr>
        <tr><td style="padding:6px 0;color:#6b7280;font-size:14px">Property:</td><td style="padding:6px 0;color:#111827;font-size:14px">{$propName}</td></tr>
        <tr><td style="padding:6px 0;color:#6b7280;font-size:14px">Unit:</td><td style="padding:6px 0;color:#111827;font-size:14px">{$unitNum}</td></tr>
        <tr><td style="padding:6px 0;color:#6b7280;font-size:14px">Move-in Date:</td><td style="padding:6px 0;color:#111827;font-size:14px">{$moveIn}</td></tr>
        <tr><td style="padding:6px 0;color:#6b7280;font-size:14px">Duration:</td><td style="padding:6px 0;color:#111827;font-size:14px">{$duration}</td></tr>
        <tr><td style="padding:6px 0;color:#6b7280;font-size:14px">Status:</td><td style="padding:6px 0"><span style="background:#fef3c7;color:#92400e;padding:3px 10px;border-radius:20px;font-size:13px;font-weight:600">Pending Review</span></td></tr>
      </table>
    </div>
    <table width="100%" cellpadding="0" cellspacing="0">
    <tr><td align="center" style="padding:10px 0 30px">
      <a href="{$confirmUrl}" style="background:linear-gradient(135deg,#1a3c5e,#2d6a9f);color:#fff;text-decoration:none;padding:16px 48px;border-radius:50px;font-size:16px;font-weight:700;display:inline-block">
        📋 View Booking Details
      </a>
    </td></tr>
    </table>
    <p style="color:#9ca3af;font-size:13px;margin:0">
      Questions? Reply to this email or contact us via WhatsApp.<br>
      Keep your booking reference <strong>{$ref}</strong> safe.
    </p>
    <hr style="border:none;border-top:1px solid #e5e7eb;margin:24px 0">
    <p style="color:#9ca3af;font-size:12px;margin:0">&copy; {$year} {$appName}. All rights reserved.</p>
  </td></tr>
</table>
</td></tr>
</table>
</body>
</html>
HTML;
        $plain = "Booking Confirmed - {$appName}\n\nHello {$name},\n\nYour booking has been submitted.\n\nRef: {$ref}\nProperty: {$propName}\nUnit: {$unitNum}\nMove-in: {$moveIn}\nDuration: {$duration}\nStatus: Pending Review\n\nView: {$confirmUrl}\n\n-- {$appName}";

        try {
            $ctx = stream_context_create(['ssl' => ['verify_peer'=>false,'verify_peer_name'=>false,'allow_self_signed'=>true]]);
            $socketAddr = ($enc === 'ssl' ? 'ssl://' : '') . $host . ':' . $port;
            $sock = @stream_socket_client($socketAddr, $errno, $errstr, 15, STREAM_CLIENT_CONNECT, $ctx);
            if (!$sock) return;
            stream_set_timeout($sock, 15);
            $recv = function() use ($sock): string { $r=''; while($l=fgets($sock,515)){$r.=$l;if(substr($l,3,1)===' ')break;} return $r; };
            $send = fn(string $cmd) => fwrite($sock, $cmd."\r\n");
            $recv();
            $send('EHLO '.(gethostname()?:'localhost')); $recv();
            if ($enc === 'tls') {
                $send('STARTTLS'); $recv();
                stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
                $send('EHLO '.(gethostname()?:'localhost')); $recv();
            }
            $send('AUTH LOGIN'); $recv();
            $send(base64_encode($smtpUser)); $recv();
            $send(base64_encode($pass)); $recv();
            $send("MAIL FROM:<{$from}>"); $recv();
            $send("RCPT TO:<{$to}>"); $recv();
            $send('DATA'); $recv();
            $boundary = 'bk_'.md5($ref);
            $send(
                "Date: ".date('r')."\r\nMessage-ID: <booking.".time().'@'.str_replace('mail.','',$host).">\r\n".
                "From: {$fromName} <{$from}>\r\nTo: {$to}\r\n".
                "Subject: Booking Confirmed - {$ref} | {$appName}\r\nMIME-Version: 1.0\r\n".
                "Content-Type: multipart/alternative; boundary=\"{$boundary}\"\r\n\r\n".
                "--{$boundary}\r\nContent-Type: text/plain; charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n\r\n".
                chunk_split(base64_encode($plain)).
                "--{$boundary}\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n\r\n".
                chunk_split(base64_encode($html)).
                "--{$boundary}--\r\n."
            );
            $recv();
            $send('QUIT');
            fclose($sock);
        } catch (\Throwable $e) {
            // Silently fail — booking still saved
        }
    }

    public function confirm(string $ref): void
    {
        $booking = $this->db->fetch("SELECT b.*, u.unit_number, p.name AS property_name, p.address FROM bookings b JOIN units u ON u.id=b.unit_id JOIN properties p ON p.id=b.property_id WHERE b.booking_ref=?", [$ref]);
        if (!$booking) { $this->abort(404); return; }
        $settingRows = $this->db->fetchAll("SELECT s.key, s.value FROM settings s WHERE s.group IN ('general','payment')");
        $settings = array_column($settingRows, 'value', 'key');
        $this->view('booking.confirm', compact('booking','settings') + ['title' => 'Complete Payment - '.$ref], 'main');
    }

    // Admin methods
    public function index(): void
    {
        $this->requireRole(['super_admin','property_owner','property_manager','receptionist']);
        $status = $_GET['status'] ?? '';
        $conditions = ['1=1']; $params = [];
        if ($status) { $conditions[] = 'b.status=?'; $params[] = $status; }
        $where = implode(' AND ', $conditions);
        $bookings = $this->db->fetchAll(
            "SELECT b.*, p.name AS property_name, u.unit_number
             FROM bookings b
             JOIN properties p ON p.id=b.property_id
             JOIN units u ON u.id=b.unit_id
             WHERE $where ORDER BY b.created_at DESC",
            $params
        );
        $counts = $this->db->fetchAll("SELECT status, COUNT(*) AS cnt FROM bookings GROUP BY status");
        $statusCounts = array_column($counts, 'cnt', 'status');
        $this->adminView('booking.index', compact('bookings','status','statusCounts') + ['title'=>'Bookings']);
    }

    public function show(string $id): void
    {
        $this->requireRole(['super_admin','property_owner','property_manager','receptionist']);
        $booking = $this->db->fetch("SELECT b.*, p.name AS property_name, p.address, u.unit_number, u.monthly_rent, u.bedrooms, u.bathrooms FROM bookings b JOIN properties p ON p.id=b.property_id JOIN units u ON u.id=b.unit_id WHERE b.id=?", [$id]);
        if (!$booking) { $this->abort(404); return; }
        $this->adminView('booking.show', compact('booking') + ['title' => 'Booking #'.$booking['booking_ref']]);
    }

    public function updateStatus(string $id): void
    {
        $this->requireRole(['super_admin','property_owner','property_manager','receptionist']);
        $this->verifyCsrf();
        $status = $this->input('status');
        $allowed = ['awaiting_payment','pending','approved','rejected','cancelled','checked_in','checked_out'];
        if (!in_array($status, $allowed)) {
            Helper::setFlash('danger', 'Invalid status.'); $this->back(); return;
        }
        $update = ['status' => $status, 'processed_by' => (int)$_SESSION['user_id'], 'processed_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s')];
        if ($status === 'checked_in')  $update['check_in_at']  = date('Y-m-d H:i:s');
        if ($status === 'checked_out') $update['check_out_at'] = date('Y-m-d H:i:s');
        $this->db->update('bookings', $update, 'id=?', [$id]);
        Helper::setFlash('success', 'Booking status updated to: '.ucfirst(str_replace('_',' ',$status)));
        $this->redirect(APP_URL . '/admin/bookings/' . $id);
    }
}
