<?php
/**
 * Input validation helpers.
 */

declare(strict_types=1);

class Validator
{
    public static function email(string $email): bool
    {
        $email = trim($email);
        if ($email === '' || strlen($email) > 190) return false;
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }

    /**
     * Password policy: min length + at least one letter + one number.
     */
    public static function password(string $pwd): bool
    {
        $min = (int)env('PASSWORD_MIN_LENGTH', 8);
        if (strlen($pwd) < $min) return false;
        if (!preg_match('/[A-Za-z]/', $pwd)) return false;
        if (!preg_match('/[0-9]/', $pwd)) return false;
        return true;
    }

    public static function passwordError(): string
    {
        $min = (int)env('PASSWORD_MIN_LENGTH', 8);
        return "Password must be at least {$min} characters and include letters and numbers.";
    }

    public static function name(string $name): bool
    {
        $name = trim($name);
        $len = mb_strlen($name);
        return $len >= 2 && $len <= 120 && preg_match('/^[\p{L}\s\.\-\']+$/u', $name) === 1;
    }

    public static function phone(string $phone): bool
    {
        $clean = preg_replace('/[\s\-\(\)]/', '', $phone);
        return $clean !== null && preg_match('/^\+?[0-9]{8,15}$/', $clean) === 1;
    }

    public static function playStoreUrl(string $url): bool
    {
        return preg_match('#^https://play\.google\.com/store/apps/details\?id=[a-zA-Z0-9._]+#', $url) === 1;
    }

    public static function packageId(string $pkg): bool
    {
        return preg_match('/^[a-zA-Z][a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9_]*)+$/', $pkg) === 1;
    }

    public static function planName(string $plan): bool
    {
        return in_array(strtolower($plan), ['silver', 'gold', 'platinum'], true);
    }

    public static function gateway(string $gw): bool
    {
        return in_array(strtolower($gw), ['cashfree', 'razorpay', 'phonepe', 'stripe', 'paypal'], true);
    }

    public static function otp(string $otp): bool
    {
        $len = (int)env('OTP_LENGTH', 6);
        return preg_match("/^[0-9]{{$len}}$/", $otp) === 1;
    }

    /**
     * Sanitize string — trim + strip control chars + length cap.
     */
    public static function clean(string $val, int $max = 1000): string
    {
        $val = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $val) ?? '';
        return mb_substr(trim($val), 0, $max);
    }

    /**
     * Validate uploaded file (icon).
     * Returns ['ok'=>bool, 'error'=>string, 'mime'=>string, 'ext'=>string]
     */
    public static function uploadedImage(array $file): array
    {
        if (!isset($file['error']) || $file['error'] !== UPLOAD_ERR_OK) {
            return ['ok' => false, 'error' => 'Upload failed (code ' . ($file['error'] ?? 'NA') . ')'];
        }
        $maxKb = (int)env('MAX_UPLOAD_SIZE_KB', 2048);
        if ($file['size'] > $maxKb * 1024) {
            return ['ok' => false, 'error' => "File exceeds {$maxKb}KB limit"];
        }
        $finfo = new finfo(FILEINFO_MIME_TYPE);
        $mime = $finfo->file($file['tmp_name']) ?: '';
        $allowed = explode(',', (string)env('UPLOAD_ALLOWED_MIMES', 'image/jpeg,image/png,image/webp'));
        if (!in_array($mime, $allowed, true)) {
            return ['ok' => false, 'error' => 'Only JPEG/PNG/WEBP allowed'];
        }
        $extMap = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp'];
        return ['ok' => true, 'mime' => $mime, 'ext' => $extMap[$mime] ?? 'bin'];
    }
}
