<?php
declare(strict_types=1);

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

function redirect(string $url): never
{
    header('Location: ' . $url);
    exit;
}

function flash(string $type, string $message): void
{
    $_SESSION['flash'] = ['type' => $type, 'message' => $message];
}

function get_flash(): ?array
{
    if (!isset($_SESSION['flash'])) {
        return null;
    }
    $flash = $_SESSION['flash'];
    unset($_SESSION['flash']);
    return $flash;
}

function money(float|int|string $amount): string
{
    $n = (float) $amount;
    // Tam sayıysa 1.200 TL; kuruş varsa 1.200,50 TL
    if (abs($n - round($n)) < 0.001) {
        return number_format($n, 0, ',', '.') . ' TL';
    }
    return number_format($n, 2, ',', '.') . ' TL';
}

/**
 * TC Kimlik No algoritma kontrolü (NVI checksum).
 * Resmi kimlik sorgusu değildir; sahte ama kurallı numaraları ayırt etmez.
 */
function tc_kimlik_valid(string $tc): bool
{
    $tc = preg_replace('/\D+/', '', $tc) ?? '';
    if (!preg_match('/^[1-9][0-9]{10}$/', $tc)) {
        return false;
    }
    // Hepsi aynı rakam (11111111110 vb.) geçersiz sayılır
    if (preg_match('/^(\d)\1{10}$/', $tc)) {
        return false;
    }

    $d = array_map('intval', str_split($tc));
    $odd = $d[0] + $d[2] + $d[4] + $d[6] + $d[8];
    $even = $d[1] + $d[3] + $d[5] + $d[7];
    $d10 = (($odd * 7) - $even) % 10;
    if ($d10 < 0) {
        $d10 += 10;
    }
    if ($d[9] !== $d10) {
        return false;
    }
    $sum = array_sum(array_slice($d, 0, 10));
    return $d[10] === ($sum % 10);
}

function cart(): array
{
    return $_SESSION['cart'] ?? [];
}

function cart_count(): int
{
    $count = 0;
    foreach (cart() as $qty) {
        $count += (int) $qty;
    }
    return $count;
}

function cart_add(string $productId, int $qty = 1): void
{
    if (!isset($_SESSION['cart'])) {
        $_SESSION['cart'] = [];
    }
    $_SESSION['cart'][$productId] = ($_SESSION['cart'][$productId] ?? 0) + max(1, $qty);
}

function cart_set(string $productId, int $qty): void
{
    if ($qty <= 0) {
        unset($_SESSION['cart'][$productId]);
        return;
    }
    $_SESSION['cart'][$productId] = $qty;
}

function cart_clear(): void
{
    $_SESSION['cart'] = [];
}

function products_by_user(string $userId): array
{
    return array_values(array_filter(
        store_read('products'),
        static fn(array $p): bool => ($p['user_id'] ?? '') === $userId && ($p['status'] ?? 'active') === 'active'
    ));
}

function comments_for_product(string $productId): array
{
    $items = array_values(array_filter(
        store_read('comments'),
        static fn(array $c): bool => ($c['product_id'] ?? '') === $productId
    ));

    usort($items, static fn(array $a, array $b): int => strcmp($b['created_at'] ?? '', $a['created_at'] ?? ''));
    return $items;
}

function comments_count_for_product(string $productId): int
{
    return count(comments_for_product($productId));
}

/** Ürün beğeni sayısı — satıcıdan gelir (yoksa üründeki eski değer). */
function product_likes(array $product): int
{
    $id = trim((string) ($product['seller_id'] ?? ''));
    if ($id !== '') {
        $row = seller_find($id);
        if (is_array($row) && array_key_exists('likes', $row)) {
            return seller_likes($row);
        }
    }
    return max(0, (int) ($product['likes'] ?? 0));
}

/** Ürüne bağlı satıcı (kayıt veya ürüne gömülü snapshot). */
function product_seller(array $product): ?array
{
    $id = trim((string) ($product['seller_id'] ?? ''));
    if ($id !== '') {
        $row = seller_find($id);
        if ($row) {
            return $row;
        }
    }
    $name = trim((string) ($product['seller_name'] ?? ''));
    $username = ltrim(trim((string) ($product['seller_username'] ?? '')), '@');
    if ($name === '' && $username === '') {
        return null;
    }
    return [
        'id' => $id,
        'name' => $name !== '' ? $name : $username,
        'username' => $username !== '' ? $username : seller_username(null, $name),
        'rating' => (float) ($product['seller_rating'] ?? 5),
        'review_count' => (int) ($product['seller_reviews'] ?? 0),
        'likes' => (int) ($product['likes'] ?? 0),
        'avatar' => (string) ($product['seller_avatar'] ?? ''),
        'avatar_seed' => (string) ($product['seller_avatar_seed'] ?? ''),
        'member_year' => (string) ($product['member_year'] ?? ''),
        'member_since' => (string) ($product['member_since'] ?? ''),
        'phone' => (string) ($product['seller_phone'] ?? ''),
    ];
}

function seller_stars_text(float $rating): string
{
    $full = (int) round(max(0, min(5, $rating)));
    return str_repeat('★', $full) . str_repeat('☆', 5 - $full);
}

/**
 * Kart altı: marka / alt kategori satırları.
 *
 * @return array{brand:string, sub:string}
 */
function product_card_labels(array $product): array
{
    $brand = trim((string) ($product['brand'] ?? ''));
    $tree = trim((string) ($product['category_tree'] ?? ''));
    $parts = $tree !== '' ? preg_split('/\s*>\s*/u', $tree) ?: [] : [];
    $parts = array_values(array_filter(array_map('trim', $parts)));

    if ($brand === '') {
        $brand = $parts[0] ?? category_label(product_category_root_slug($product));
    }
    if ($brand === '') {
        $brand = 'Diğer';
    }

    $sub = $parts[1] ?? '';
    if ($sub === '' || strcasecmp($sub, $brand) === 0) {
        $sub = trim((string) ($product['title'] ?? ''));
    }
    if (mb_strlen($sub) > 42) {
        $sub = mb_substr($sub, 0, 40) . '…';
    }

    return ['brand' => $brand, 'sub' => $sub];
}

function follow_icon_svg(int $size = 18): string
{
    return '<svg viewBox="0 0 24 24" width="' . $size . '" height="' . $size . '" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><line x1="19" y1="8" x2="19" y2="14"/><line x1="22" y1="11" x2="16" y2="11"/></svg>';
}

function heart_icon_svg(int $size = 14): string
{
    // İnce outline kalp (Dolap tarzı)
    return '<svg viewBox="0 0 24 24" width="' . $size . '" height="' . $size . '" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.55" stroke-linecap="round" stroke-linejoin="round"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>';
}

function comment_icon_svg(int $size = 14): string
{
    // İnce outline balon
    return '<svg viewBox="0 0 24 24" width="' . $size . '" height="' . $size . '" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.55" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.4 8.4 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.4 8.4 0 0 1-3.8-.9L3 21l1.9-5.7a8.4 8.4 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.4 8.4 0 0 1 3.8-.9h.5a8.5 8.5 0 0 1 8 8v.5z"/></svg>';
}

function user_name(string $userId): string
{
    $user = store_find('users', $userId);
    return $user['name'] ?? 'Üye';
}

function product_images(array $product): array
{
    $images = [];
    if (!empty($product['images']) && is_array($product['images'])) {
        foreach ($product['images'] as $img) {
            $img = trim((string) $img);
            if ($img !== '') {
                $images[] = $img;
            }
        }
    }
    if (!$images && !empty($product['image'])) {
        $images[] = (string) $product['image'];
    }
    return $images;
}

function product_image_url(array $product, int $index = 0): string
{
    $images = product_images($product);
    if (!$images || !isset($images[$index])) {
        return url('assets/img/placeholder.svg');
    }
    // url() ile kökten göreli yol: admin/ altında da kırılmaz
    return url(UPLOAD_URL . '/' . ltrim($images[$index], '/'));
}

function product_image_urls(array $product): array
{
    $images = product_images($product);
    if (!$images) {
        return [url('assets/img/placeholder.svg')];
    }
    return array_map(
        static fn(string $img): string => url(UPLOAD_URL . '/' . ltrim($img, '/')),
        $images
    );
}

function save_uploaded_image(array $file, string $dir = UPLOAD_PATH, string $prefix = 'p_'): string|false
{
    if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
        return false;
    }

    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime = $finfo->file($file['tmp_name']);
    $allowed = [
        'image/jpeg' => 'jpg',
        'image/png' => 'png',
        'image/webp' => 'webp',
        'image/gif' => 'gif',
    ];

    if (!isset($allowed[$mime])) {
        return false;
    }

    if (!is_dir($dir)) {
        mkdir($dir, 0775, true);
    }

    $name = $prefix . bin2hex(random_bytes(8)) . '.' . $allowed[$mime];
    $dest = $dir . '/' . $name;

    if (!move_uploaded_file($file['tmp_name'], $dest)) {
        return false;
    }

    return $name;
}

function save_receipt_image(array $file): string|false
{
    return save_receipt_upload($file);
}

/** Dekont: JPG/PNG/WEBP/GIF veya PDF. */
function save_receipt_upload(array $file): string|false
{
    if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
        return false;
    }

    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime = (string) $finfo->file($file['tmp_name']);
    $allowed = [
        'image/jpeg' => 'jpg',
        'image/png' => 'png',
        'image/webp' => 'webp',
        'image/gif' => 'gif',
        'application/pdf' => 'pdf',
        'application/x-pdf' => 'pdf',
    ];

    // Bazı sunucular PDF’i application/octet-stream der
    $extName = strtolower(pathinfo((string) ($file['name'] ?? ''), PATHINFO_EXTENSION));
    if (!isset($allowed[$mime]) && $mime === 'application/octet-stream' && $extName === 'pdf') {
        $mime = 'application/pdf';
    }

    if (!isset($allowed[$mime])) {
        return false;
    }

    $dir = RECEIPT_PATH;
    if (!is_dir($dir)) {
        mkdir($dir, 0775, true);
    }

    $name = 'd_' . bin2hex(random_bytes(8)) . '.' . $allowed[$mime];
    $dest = $dir . '/' . $name;

    if (!move_uploaded_file($file['tmp_name'], $dest)) {
        return false;
    }

    return $name;
}

function receipt_url(string $filename): string
{
    return url(RECEIPT_URL . '/' . ltrim($filename, '/'));
}

function receipt_is_pdf(string $filename): bool
{
    return str_ends_with(strtolower($filename), '.pdf');
}

function order_public_no(array $order): string
{
    $no = trim((string) ($order['order_no'] ?? ''));
    return $no !== '' ? $no : (string) ($order['id'] ?? '');
}

/** Ödeme için kalan süre (dakika). */
function order_pay_deadline_minutes(): int
{
    return 30;
}

function order_pay_deadline_iso(string $createdAt = ''): string
{
    $base = $createdAt !== '' ? strtotime($createdAt) : time();
    if ($base === false) {
        $base = time();
    }
    return date('c', $base + (order_pay_deadline_minutes() * 60));
}

function order_pay_deadline_ts(array $order): int
{
    $deadline = trim((string) ($order['pay_deadline'] ?? ''));
    if ($deadline !== '') {
        $ts = strtotime($deadline);
        if ($ts !== false) {
            return $ts;
        }
    }
    $created = trim((string) ($order['created_at'] ?? ''));
    $base = $created !== '' ? strtotime($created) : false;
    if ($base === false) {
        $base = time();
    }
    return $base + (order_pay_deadline_minutes() * 60);
}

function order_pay_expired(array $order): bool
{
    return time() >= order_pay_deadline_ts($order);
}

/** Ödeme bekleyen (dekontsuz) sipariş mi? */
function order_is_pending_payment(array $order): bool
{
    $status = (string) ($order['payment_status'] ?? 'bekliyor');
    if ($status === 'odendi' || $status === 'dekont_bekliyor') {
        return false;
    }
    return trim((string) ($order['receipt'] ?? '')) === '';
}

/**
 * Sipariş ilerleme çubuğu: Teslimat → Ödeme → Tamam
 *
 * @param 'form'|'pay'|'done' $current
 */
function checkout_steps_html(string $current): string
{
    $t = static fn(string $key, string $fallback): string => function_exists('theme_t') ? theme_t($key) : $fallback;
    $steps = [
        'form' => $t('chk_step_form', 'Teslimat'),
        'pay' => $t('chk_step_pay', 'Ödeme'),
        'done' => $t('chk_step_done', 'Tamam'),
    ];
    $keys = array_keys($steps);
    $curIdx = array_search($current, $keys, true);
    if ($curIdx === false) {
        $curIdx = 0;
        $current = 'form';
    }

    $html = '<nav class="checkout-steps" aria-label="Sipariş adımları">';
    foreach ($keys as $i => $key) {
        $label = $steps[$key];
        $state = 'is-todo';
        if ($i < $curIdx) {
            $state = 'is-done';
        } elseif ($i === $curIdx) {
            $state = 'is-current';
        }
        $num = (string) ($i + 1);
        $mark = $state === 'is-done' ? '✓' : $num;
        $aria = $state === 'is-current' ? ' aria-current="step"' : '';
        $html .= '<div class="checkout-step ' . $state . '"' . $aria . '>'
            . '<span class="checkout-step-num" aria-hidden="true">' . e($mark) . '</span>'
            . '<span class="checkout-step-label">' . e($label) . '</span>'
            . '</div>';
        if ($i < count($keys) - 1) {
            $lineClass = $i < $curIdx ? 'is-done' : '';
            $html .= '<span class="checkout-step-line ' . $lineClass . '" aria-hidden="true"></span>';
        }
    }
    $html .= '</nav>';
    return $html;
}

/** Ödeme adımı içi: Havale → Dekont */
function checkout_pay_substeps_html(string $focus = 'transfer'): string
{
    $t = static fn(string $key, string $fallback): string => function_exists('theme_t') ? theme_t($key) : $fallback;
    $items = [
        'transfer' => $t('pay_sub_transfer', 'Havale / EFT'),
        'receipt' => $t('pay_sub_receipt', 'Dekont yükle'),
    ];
    $keys = array_keys($items);
    $curIdx = array_search($focus, $keys, true);
    if ($curIdx === false) {
        $curIdx = 0;
    }
    $html = '<div class="pay-substeps" aria-label="Ödeme alt adımları">';
    foreach ($keys as $i => $key) {
        $state = $i < $curIdx ? 'is-done' : ($i === $curIdx ? 'is-current' : 'is-todo');
        $html .= '<div class="pay-substep ' . $state . '">'
            . '<span class="pay-substep-dot" aria-hidden="true"></span>'
            . '<span>' . e($items[$key]) . '</span>'
            . '</div>';
        if ($i < count($keys) - 1) {
            $html .= '<span class="pay-substep-line" aria-hidden="true"></span>';
        }
    }
    $html .= '</div>';
    return $html;
}

function checkout_cookie_path(): string
{
    $base = function_exists('app_base_path') ? app_base_path() : '';
    return ($base === '' || $base === '/') ? '/' : rtrim($base, '/') . '/';
}

function checkout_remember_order(string $orderId): void
{
    $orderId = trim($orderId);
    if ($orderId === '') {
        return;
    }
    $_SESSION['last_order_id'] = $orderId;
    if (!headers_sent()) {
        setcookie('checkout_order', $orderId, [
            'expires' => time() + (order_pay_deadline_minutes() * 60) + 86400,
            'path' => checkout_cookie_path(),
            'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
            'httponly' => true,
            'samesite' => 'Lax',
        ]);
    }
}

function checkout_clear_pending(): void
{
    unset($_SESSION['last_order_id']);
    if (!headers_sent()) {
        setcookie('checkout_order', '', [
            'expires' => time() - 3600,
            'path' => checkout_cookie_path(),
            'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
            'httponly' => true,
            'samesite' => 'Lax',
        ]);
    }
}

/** Yarım kalmış ödeme siparişi (session / cookie). */
function checkout_pending_order(): ?array
{
    $ids = [];
    $sid = trim((string) ($_SESSION['last_order_id'] ?? ''));
    if ($sid !== '') {
        $ids[] = $sid;
    }
    $cid = trim((string) ($_COOKIE['checkout_order'] ?? ''));
    if ($cid !== '' && $cid !== $sid) {
        $ids[] = $cid;
    }
    foreach ($ids as $id) {
        $order = store_find('orders', $id);
        if ($order && order_is_pending_payment($order)) {
            return $order;
        }
    }
    return null;
}

function order_product_image_url(array $order): string
{
    $img = (string) ($order['items'][0]['image'] ?? '');
    if ($img === '') {
        $pid = (string) ($order['items'][0]['product_id'] ?? '');
        $p = $pid !== '' ? store_find('products', $pid) : null;
        if ($p) {
            $urls = product_image_urls($p);
            return $urls[0] ?? '';
        }
        return '';
    }
    if (str_starts_with($img, 'http://') || str_starts_with($img, 'https://') || str_starts_with($img, '/')) {
        return $img;
    }
    return url(UPLOAD_URL . '/' . ltrim($img, '/'));
}

/** @return list<string> */
function save_uploaded_images(array $filesField): array
{
    $saved = [];
    if (empty($filesField['name']) || !is_array($filesField['name'])) {
        // tek dosya alanı
        if (!empty($filesField['name'])) {
            $one = save_uploaded_image($filesField);
            if ($one !== false) {
                $saved[] = $one;
            }
        }
        return $saved;
    }

    $count = count($filesField['name']);
    for ($i = 0; $i < $count; $i++) {
        if (($filesField['error'][$i] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
            continue;
        }
        $file = [
            'name' => $filesField['name'][$i],
            'type' => $filesField['type'][$i] ?? '',
            'tmp_name' => $filesField['tmp_name'][$i],
            'error' => $filesField['error'][$i],
            'size' => $filesField['size'][$i] ?? 0,
        ];
        $name = save_uploaded_image($file);
        if ($name !== false) {
            $saved[] = $name;
        }
    }
    return $saved;
}


/**
 * Ürün renkleri (slug => [label, hex]).
 *
 * @return array<string, array{label:string, hex:string}>
 */
function product_colors(): array
{
    return [
        'bej' => ['label' => 'Bej', 'hex' => '#e8d9c0'],
        'beyaz' => ['label' => 'Beyaz', 'hex' => '#f5f5f5'],
        'siyah' => ['label' => 'Siyah', 'hex' => '#222222'],
        'gri' => ['label' => 'Gri', 'hex' => '#9aa0a6'],
        'kahverengi' => ['label' => 'Kahverengi', 'hex' => '#8b5a2b'],
        'krem' => ['label' => 'Krem', 'hex' => '#f3e9d2'],
        'kirmizi' => ['label' => 'Kırmızı', 'hex' => '#d64545'],
        'pembe' => ['label' => 'Pembe', 'hex' => '#e88bb0'],
        'turuncu' => ['label' => 'Turuncu', 'hex' => '#f0a04b'],
        'sari' => ['label' => 'Sarı', 'hex' => '#f5d56a'],
        'yesil' => ['label' => 'Yeşil', 'hex' => '#5a9a62'],
        'haki' => ['label' => 'Haki', 'hex' => '#7a8450'],
        'mavi' => ['label' => 'Mavi', 'hex' => '#4a90d9'],
        'lacivert' => ['label' => 'Lacivert', 'hex' => '#1e3a6e'],
        'mor' => ['label' => 'Mor', 'hex' => '#7b3fa0'],
        'bordo' => ['label' => 'Bordo', 'hex' => '#7a1f3d'],
        'altin' => ['label' => 'Altın', 'hex' => '#c6a15b'],
        'gumus' => ['label' => 'Gümüş', 'hex' => '#c0c4c8'],
        'cokrenk' => ['label' => 'Çok Renkli', 'hex' => 'linear-gradient(135deg,#e88bb0,#4a90d9,#f5d56a)'],
        'diger' => ['label' => 'Diğer', 'hex' => '#d0d4ce'],
    ];
}

function product_color_slug(array $product): string
{
    $slug = trim((string) ($product['color'] ?? ''));
    $colors = product_colors();
    return isset($colors[$slug]) ? $slug : '';
}

/** @return array{slug:string, label:string, hex:string}|null */
function product_color_meta(array $product): ?array
{
    $slug = product_color_slug($product);
    if ($slug === '') {
        return null;
    }
    $c = product_colors()[$slug];
    return ['slug' => $slug, 'label' => $c['label'], 'hex' => $c['hex']];
}

function product_color_swatch_html(array $product, string $class = 'color-swatch'): string
{
    $meta = product_color_meta($product);
    if (!$meta) {
        return '';
    }
    $style = str_starts_with($meta['hex'], 'linear')
        ? 'background:' . $meta['hex']
        : 'background-color:' . $meta['hex'];
    $border = in_array($meta['slug'], ['beyaz', 'krem', 'bej', 'gumus'], true)
        ? 'box-shadow:inset 0 0 0 1px rgba(0,0,0,0.12);'
        : '';
    return '<span class="' . e($class) . '" style="' . e($style . ';' . $border) . '" title="' . e($meta['label']) . '" aria-hidden="true"></span>';
}

function product_color_label_html(array $product): string
{
    $meta = product_color_meta($product);
    if (!$meta) {
        return '';
    }
    return '<span class="product-color-line">'
        . product_color_swatch_html($product, 'color-swatch sm')
        . '<span>' . e($meta['label']) . '</span></span>';
}

/** free | buyer */
function product_shipping(array $product): string
{
    $s = trim((string) ($product['shipping'] ?? 'free'));
    return $s === 'buyer' ? 'buyer' : 'free';
}

function product_shipping_is_free(array $product): bool
{
    return product_shipping($product) === 'free';
}

function product_shipping_label(array $product): string
{
    return product_shipping_is_free($product) ? 'Ücretsiz Kargo' : 'Alıcı Öder';
}

function product_shipping_line(array $product): string
{
    return product_shipping_is_free($product)
        ? 'Satıcı Öder · Ücretsiz Kargo'
        : 'Alıcı Öder · Kargo alıcıya ait';
}

function product_shipping_badge(array $product = []): string
{
    // Alıcı öderse rozet gösterme — kafa karıştırır
    if ($product !== [] && !product_shipping_is_free($product)) {
        return '';
    }
    return '<span class="cargo-badge" aria-label="Ücretsiz Kargo">'
        . '<span class="cargo-badge-text">Ücretsiz<br>Kargo</span>'
        . '<span class="cargo-badge-icon" aria-hidden="true">'
        . '<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="#222" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">'
        . '<path d="M3 7h11v10H3z"/><path d="M14 10h4l3 3v4h-7z"/><circle cx="7.5" cy="18.5" r="1.5"/><circle cx="17.5" cy="18.5" r="1.5"/>'
        . '<path d="M9 11.5l1.2 1.2L12.5 10"/>'
        . '</svg></span></span>';
}

/** @deprecated use product_shipping_badge */
function free_shipping_badge(): string
{
    return product_shipping_badge([]);
}
