<?php
require_once __DIR__ . '/db.php';
require_once __DIR__ . '/i18n.php';

function e(?string $s): string {
    return htmlspecialchars($s ?? '', ENT_QUOTES, 'UTF-8');
}

function base_url(string $path = ''): string {
    return '/' . ltrim($path, '/');
}

/**
 * Returns the relative path to a user-supplied brand asset (assets/images/brand/*)
 * if it has been uploaded, or null so callers can fall back to a stock image.
 * Checks a couple of common extensions when only a base name is given.
 */
function brand_asset(string $filename): ?string {
    $dir = __DIR__ . '/../assets/images/brand/';
    if (file_exists($dir . $filename)) return 'assets/images/brand/' . $filename;
    $base = pathinfo($filename, PATHINFO_FILENAME);
    foreach (['png', 'jpg', 'jpeg', 'webp', 'svg'] as $ext) {
        if (file_exists($dir . $base . '.' . $ext)) return 'assets/images/brand/' . $base . '.' . $ext;
    }
    return null;
}

function current_path(): string {
    return parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';
}

function is_active(string $path): bool {
    $current = current_path();
    if ($path === '/') return $current === '/' || $current === '/index.php';
    return strpos($current, $path) === 0;
}

function money(float $amount): string {
    return number_format($amount, 0, '.', ',');
}

function format_price(float $amount, string $currency = 'RWF', string $period = ''): string {
    $out = $currency . ' ' . money($amount);
    if ($period === 'month') $out .= ' <span class="period">/ month</span>';
    if ($period === 'year') $out .= ' <span class="period">/ year</span>';
    return $out;
}

function initials(string $name): string {
    $parts = preg_split('/\s+/', trim($name));
    $letters = array_map(fn($p) => mb_strtoupper(mb_substr($p, 0, 1)), array_filter($parts));
    return implode('', array_slice($letters, 0, 2));
}

function avatar_html(string $name, string $size = 'md', string $photo = ''): string {
    $sizeClass = 'avatar-' . $size;
    if (!empty($photo) && file_exists(__DIR__ . '/../' . $photo)) {
        return '<img src="' . base_url($photo) . '" alt="' . e($name) . '" class="avatar ' . $sizeClass . '" style="object-fit:cover;">';
    }
    return '<span class="avatar ' . $sizeClass . '" aria-hidden="true">' . e(initials($name)) . '</span>';
}

function time_ago_or_date(string $datetime): string {
    return date('F j, Y', strtotime($datetime));
}

function truncate(string $text, int $len = 140): string {
    $text = trim(strip_tags($text));
    if (mb_strlen($text) <= $len) return $text;
    return rtrim(mb_substr($text, 0, $len)) . '…';
}

function whatsapp_link(string $message = ''): string {
    $msg = $message !== '' ? '?text=' . rawurlencode($message) : '';
    return 'https://wa.me/' . setting('whatsapp', SITE_WHATSAPP) . $msg;
}

function tel_link(): string {
    return 'tel:' . preg_replace('/[^0-9+]/', '', setting('phone', SITE_PHONE));
}

/**
 * Admin-editable scalar content (site_content table), cached per-request.
 * Falls back to $default so a missing/un-seeded key never breaks a page.
 */
function site_content(string $key, string $default = ''): string {
    static $cache = null;
    if ($cache === null) {
        $cache = [];
        foreach (db()->query('SELECT `key`, value FROM site_content')->fetchAll() as $row) {
            $cache[$row['key']] = $row['value'];
        }
    }
    return ($cache[$key] ?? '') !== '' ? $cache[$key] : $default;
}

/** Shorthand for the `settings.*` group used by tel_link()/whatsapp_link()/footer/contact. */
function setting(string $key, string $default = ''): string {
    return site_content('settings.' . $key, $default);
}

/** Returns the uploaded custom favicon path if one exists, else null (caller falls back to the default SVG mark). */
function favicon_asset(): ?string {
    $dir = __DIR__ . '/../assets/icons/';
    foreach (['png', 'svg', 'ico', 'jpg', 'jpeg'] as $ext) {
        if (file_exists($dir . 'custom-favicon.' . $ext)) return 'assets/icons/custom-favicon.' . $ext;
    }
    return null;
}

function mime_for_favicon(string $path): string {
    $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
    return match ($ext) {
        'svg' => 'image/svg+xml',
        'ico' => 'image/x-icon',
        'jpg', 'jpeg' => 'image/jpeg',
        default => 'image/png',
    };
}

/**
 * Lightens (positive $percent, 0-1) or darkens (negative $percent) a hex color
 * toward white/black respectively. Used to derive hover/tint shades from a
 * single admin-picked brand color.
 */
function hex_adjust_brightness(string $hex, float $percent): string {
    $hex = ltrim(trim($hex), '#');
    if (strlen($hex) === 3) $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
    if (!preg_match('/^[0-9a-fA-F]{6}$/', $hex)) return '#' . $hex;
    $r = hexdec(substr($hex, 0, 2));
    $g = hexdec(substr($hex, 2, 2));
    $b = hexdec(substr($hex, 4, 2));
    foreach (['r', 'g', 'b'] as $c) {
        $$c = $percent >= 0 ? $$c + (255 - $$c) * $percent : $$c * (1 + $percent);
        $$c = (int)max(0, min(255, round($$c)));
    }
    return sprintf('#%02x%02x%02x', $r, $g, $b);
}

/** Admin-editable repeatable icon+title+description cards, ordered by sort_order. */
function content_blocks(string $page, string $section): array {
    $stmt = db()->prepare('SELECT * FROM content_blocks WHERE page = ? AND section = ? ORDER BY sort_order');
    $stmt->execute([$page, $section]);
    return $stmt->fetchAll();
}

/* ---------------------------------------------------------------
 * Data access helpers
 * ------------------------------------------------------------- */

function get_categories(): array {
    static $cache = null;
    if ($cache === null) {
        $cache = db()->query('SELECT * FROM property_categories ORDER BY sort_order')->fetchAll();
    }
    return $cache;
}

function get_category_by_slug(string $slug): ?array {
    foreach (get_categories() as $c) if ($c['slug'] === $slug) return $c;
    return null;
}

function get_districts(): array {
    static $cache = null;
    if ($cache === null) {
        $cache = db()->query('SELECT * FROM districts ORDER BY sort_order')->fetchAll();
    }
    return $cache;
}

function get_district_by_slug(string $slug): ?array {
    foreach (get_districts() as $d) if ($d['slug'] === $slug) return $d;
    return null;
}

function get_agents(): array {
    static $cache = null;
    if ($cache === null) {
        $cache = db()->query('SELECT * FROM agents ORDER BY sort_order')->fetchAll();
    }
    return $cache;
}

function get_agent(int $id): ?array {
    foreach (get_agents() as $a) if ((int)$a['id'] === $id) return $a;
    return null;
}

function get_property_primary_image(int $propertyId): ?string {
    $stmt = db()->prepare('SELECT image_path FROM property_images WHERE property_id = ? ORDER BY sort_order LIMIT 1');
    $stmt->execute([$propertyId]);
    $row = $stmt->fetch();
    return $row['image_path'] ?? null;
}

function get_property_images(int $propertyId): array {
    $stmt = db()->prepare('SELECT * FROM property_images WHERE property_id = ? ORDER BY sort_order');
    $stmt->execute([$propertyId]);
    return $stmt->fetchAll();
}

function get_property_full(array $property): array {
    $property['images'] = get_property_images((int)$property['id']);
    $property['category'] = get_category_by_slug_id((int)$property['category_id']);
    $property['district'] = get_district_by_id((int)$property['district_id']);
    $property['agent'] = $property['agent_id'] ? get_agent((int)$property['agent_id']) : null;
    $property['features'] = json_decode($property['features'] ?? '[]', true) ?: [];
    $property['amenities'] = json_decode($property['amenities'] ?? '[]', true) ?: [];
    return $property;
}

function get_category_by_slug_id(int $id): ?array {
    foreach (get_categories() as $c) if ((int)$c['id'] === $id) return $c;
    return null;
}

function get_district_by_id(int $id): ?array {
    foreach (get_districts() as $d) if ((int)$d['id'] === $id) return $d;
    return null;
}

function get_similar_properties(array $property, int $limit = 3): array {
    $stmt = db()->prepare('SELECT * FROM properties WHERE id != ? AND (category_id = ? OR district_id = ?) ORDER BY is_featured DESC, created_at DESC LIMIT ?');
    $stmt->bindValue(1, $property['id'], PDO::PARAM_INT);
    $stmt->bindValue(2, $property['category_id'], PDO::PARAM_INT);
    $stmt->bindValue(3, $property['district_id'], PDO::PARAM_INT);
    $stmt->bindValue(4, $limit, PDO::PARAM_INT);
    $stmt->execute();
    return $stmt->fetchAll();
}

function count_properties_in_district(int $districtId): int {
    $stmt = db()->prepare('SELECT COUNT(*) FROM properties WHERE district_id = ?');
    $stmt->execute([$districtId]);
    return (int)$stmt->fetchColumn();
}

function count_properties_in_category(int $categoryId): int {
    $stmt = db()->prepare('SELECT COUNT(*) FROM properties WHERE category_id = ?');
    $stmt->execute([$categoryId]);
    return (int)$stmt->fetchColumn();
}

function get_faqs(?string $category = null): array {
    if ($category) {
        $stmt = db()->prepare('SELECT * FROM faqs WHERE category = ? ORDER BY sort_order');
        $stmt->execute([$category]);
        return $stmt->fetchAll();
    }
    return db()->query('SELECT * FROM faqs ORDER BY sort_order')->fetchAll();
}

function get_developments(): array {
    return db()->query('SELECT * FROM developments ORDER BY is_featured DESC, completion_date ASC')->fetchAll();
}

function get_development_by_slug(string $slug): ?array {
    $stmt = db()->prepare('SELECT * FROM developments WHERE slug = ? LIMIT 1');
    $stmt->execute([$slug]);
    return $stmt->fetch() ?: null;
}

function development_status_label(string $status): string {
    $map = ['off-plan' => 'Off-Plan', 'under-construction' => 'Under Construction', 'near-completion' => 'Near Completion'];
    return $map[$status] ?? ucfirst($status);
}

function get_testimonials(int $limit = 6): array {
    $stmt = db()->prepare('SELECT * FROM testimonials ORDER BY sort_order LIMIT ?');
    $stmt->bindValue(1, $limit, PDO::PARAM_INT);
    $stmt->execute();
    return $stmt->fetchAll();
}

/* ---------------------------------------------------------------
 * Icon set — original hand-authored line icons, 24x24, stroke-based
 * ------------------------------------------------------------- */
function icon(string $name, int $size = 22): string {
    $common = 'width="' . $size . '" height="' . $size . '" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"';
    $paths = [
        'bed' => '<path d="M3 18v-7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v7"/><path d="M3 15h18"/><path d="M7 11V8a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1v3"/><path d="M3 18v2M21 18v2"/>',
        'bath' => '<path d="M4 12h16v3a4 4 0 0 1-4 4H8a4 4 0 0 1-4-4v-3Z"/><path d="M7 12V6a2 2 0 0 1 3.2-1.6"/><path d="M4 19v2M17 19v2"/>',
        'area' => '<path d="M4 4h6M4 4v6M20 4h-6M20 4v6M4 20h6M4 20v-6M20 20h-6M20 20v-6"/>',
        'map-pin' => '<path d="M12 21s7-6.2 7-11.5A7 7 0 0 0 5 9.5C5 14.8 12 21 12 21Z"/><circle cx="12" cy="9.5" r="2.3"/>',
        'search' => '<circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/>',
        'heart' => '<path d="M12 20s-7.5-4.6-9.6-9A5.4 5.4 0 0 1 12 6a5.4 5.4 0 0 1 9.6 5c-2.1 4.4-9.6 9-9.6 9Z"/>',
        'phone' => '<path d="M4 5c0 8.3 6.7 15 15 15l2-4-5-2-2 2a12 12 0 0 1-6-6l2-2-2-5Z"/>',
        'mail' => '<rect x="3" y="5" width="18" height="14" rx="2"/><path d="m4 6 8 7 8-7"/>',
        'whatsapp' => '<path d="M4 20l1.3-4A8 8 0 1 1 9 18.6L4 20Z"/><path d="M9 9.5c0 3 2.5 5.5 5.5 5.5.4 0 .8-.5.8-1l-.2-1-2-1-1 1c-1-.6-1.8-1.4-2.4-2.4l1-1-1-2-1-.2c-.5 0-1 .4-1 .8Z"/>',
        'check' => '<path d="M20 6 9 17l-5-5"/>',
        'chevron-down' => '<path d="m6 9 6 6 6-6"/>',
        'chevron-right' => '<path d="m9 6 6 6-6 6"/>',
        'close' => '<path d="M18 6 6 18M6 6l12 12"/>',
        'menu' => '<path d="M4 7h16M4 12h16M4 17h16"/>',
        'star' => '<path d="m12 3 2.6 5.9 6.4.6-4.8 4.3 1.4 6.2L12 16.9 6.4 20l1.4-6.2-4.8-4.3 6.4-.6L12 3Z"/>',
        'arrow-right' => '<path d="M5 12h14M13 6l6 6-6 6"/>',
        'play' => '<circle cx="12" cy="12" r="9"/><path d="M10 8.5 16 12l-6 3.5v-7Z"/>',
        'expand' => '<path d="M9 3H3v6M15 3h6v6M21 15v6h-6M3 15v6h6"/>',
        'calendar' => '<rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4"/>',
        'shield' => '<path d="M12 3 4 6v6c0 5 3.4 8.4 8 9 4.6-.6 8-4 8-9V6l-8-3Z"/>',
        'trending-up' => '<path d="m3 17 6-6 4 4 8-8"/><path d="M15 7h6v6"/>',
        'calculator' => '<rect x="4" y="3" width="16" height="18" rx="2"/><path d="M8 7h8M8 11h1M12 11h1M16 11h1M8 15h1M12 15h1M16 15h1M8 19h8"/>',
        'compass' => '<circle cx="12" cy="12" r="9"/><path d="m15 9-2 6-4-2 2-6 4 2Z"/>',
        'building' => '<rect x="5" y="3" width="14" height="18" rx="1"/><path d="M9 7h1M14 7h1M9 11h1M14 11h1M9 15h1M14 15h1"/><path d="M10 21v-3h4v3"/>',
        'land' => '<path d="M3 20 9 8l4 6 3-4 5 10Z"/>',
        'house-build' => '<path d="M4 20V10l8-6 8 6v10"/><path d="M9 20v-6h6v6"/><path d="M2 10h20" stroke-dasharray="1.5 2.5"/><path d="M16 4.5V2h2v1.2"/>',
        'document' => '<path d="M7 3h7l5 5v13H7Z"/><path d="M14 3v5h5"/><path d="M9 13h6M9 17h6"/>',
        'video' => '<rect x="3" y="6" width="13" height="12" rx="2"/><path d="m21 8-5 4 5 4Z"/>',
        'view360' => '<ellipse cx="12" cy="12" rx="9" ry="5"/><circle cx="12" cy="12" r="2.4"/>',
        'facebook' => '<path d="M14 21v-7h2.4l.4-3H14V9a1.5 1.5 0 0 1 1.5-1.7H17V4.4S15.9 4 14.8 4A4 4 0 0 0 10.5 8v3H8v3h2.5v7Z"/>',
        'instagram' => '<rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="3.6"/><circle cx="17.3" cy="6.7" r="1"/>',
        'linkedin' => '<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M7.5 10v7M7.5 7.2v.1M11.5 17v-4a2.2 2.2 0 0 1 4.4 0v4M11.5 10v7"/>',
        'twitter' => '<path d="M21 5.3a7.6 7.6 0 0 1-2.2.6A3.9 3.9 0 0 0 20.4 4a7.8 7.8 0 0 1-2.5 1 3.9 3.9 0 0 0-6.6 3.5A11 11 0 0 1 3.2 4.5a3.9 3.9 0 0 0 1.2 5.2 3.9 3.9 0 0 1-1.8-.5v.1a3.9 3.9 0 0 0 3.1 3.8 4 4 0 0 1-1.7.1 3.9 3.9 0 0 0 3.6 2.7A7.8 7.8 0 0 1 2 17.5a11 11 0 0 0 6 1.7c7.1 0 11-5.9 11-11v-.5A7.9 7.9 0 0 0 21 5.3Z"/>',
        'youtube' => '<rect x="2" y="5" width="20" height="14" rx="4"/><path d="m10 9 5 3-5 3Z"/>',
        'quote' => '<path d="M7 7c-2.2 1.3-3.5 3.3-3.5 6 0 2 1.3 3.5 3 3.5S9.5 15 9.5 13c0-1.6-1-2.8-2.5-3 .2-1.3 1-2.2 2.5-3Zm9 0c-2.2 1.3-3.5 3.3-3.5 6 0 2 1.3 3.5 3 3.5s3-1.5 3-3.5c0-1.6-1-2.8-2.5-3 .2-1.3 1-2.2 2.5-3Z" fill="currentColor" stroke="none"/>',
        'sun' => '<circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4 12H2M22 12h-2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/>',
        'layers' => '<path d="m12 3 9 5-9 5-9-5 9-5Z"/><path d="m3 13 9 5 9-5"/>',
        'filter' => '<path d="M4 5h16M7 12h10M10 19h4"/>',
        'lock' => '<rect x="4" y="10" width="16" height="10" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/>',
        'user' => '<circle cx="12" cy="8" r="4"/><path d="M4 20c0-3.9 3.6-6 8-6s8 2.1 8 6"/>',
        'grid' => '<rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/>',
        'list' => '<path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01"/>',
    ];
    $inner = $paths[$name] ?? $paths['check'];
    return "<svg {$common}>{$inner}</svg>";
}

/* ---------------------------------------------------------------
 * Category icon mapping (property_categories.icon -> icon())
 * ------------------------------------------------------------- */
function category_icon(string $iconKey): string {
    $map = [
        'villa' => 'building', 'house' => 'building', 'townhouse' => 'building',
        'apartment' => 'building', 'penthouse' => 'building', 'duplex' => 'building',
        'office' => 'building', 'retail' => 'building', 'hotel' => 'building',
        'warehouse' => 'building', 'land' => 'land', 'development' => 'land',
        'agriculture' => 'land', 'commercial' => 'building',
    ];
    return icon($map[$iconKey] ?? 'building', 26);
}

/* ---------------------------------------------------------------
 * Simple pagination helper
 * ------------------------------------------------------------- */
function paginate_query(string $baseUrl, array $queryParams, int $page, int $totalPages): string {
    if ($totalPages <= 1) return '';
    $mk = function (int $p) use ($baseUrl, $queryParams) {
        $qp = $queryParams; $qp['page'] = $p;
        return $baseUrl . '?' . http_build_query($qp);
    };
    $html = '<nav class="pagination" aria-label="Pagination">';
    if ($page > 1) $html .= '<a href="' . e($mk($page - 1)) . '" aria-label="Previous page">' . icon('chevron-right', 16) . '</a>';
    $start = max(1, $page - 2);
    $end = min($totalPages, $page + 2);
    if ($start > 1) $html .= '<a href="' . e($mk(1)) . '">1</a>' . ($start > 2 ? '<span>…</span>' : '');
    for ($i = $start; $i <= $end; $i++) {
        $html .= $i === $page ? '<span class="current" aria-current="page">' . $i . '</span>' : '<a href="' . e($mk($i)) . '">' . $i . '</a>';
    }
    if ($end < $totalPages) $html .= ($end < $totalPages - 1 ? '<span>…</span>' : '') . '<a href="' . e($mk($totalPages)) . '">' . $totalPages . '</a>';
    if ($page < $totalPages) $html .= '<a href="' . e($mk($page + 1)) . '" aria-label="Next page">' . icon('chevron-right', 16) . '</a>';
    $html .= '</nav>';
    return $html;
}

function flash_set(string $key, string $message): void {
    if (session_status() !== PHP_SESSION_ACTIVE) session_start();
    $_SESSION['flash'][$key] = $message;
}

function flash_get(string $key): ?string {
    if (session_status() !== PHP_SESSION_ACTIVE) session_start();
    if (!empty($_SESSION['flash'][$key])) {
        $msg = $_SESSION['flash'][$key];
        unset($_SESSION['flash'][$key]);
        return $msg;
    }
    return null;
}
