<?php
// classes/Search.php
class Search {
    private $pdo;   // PDO connection
    private $user;  // User class

    public function __construct($db, $user) {
        $this->pdo = method_exists($db, 'getConnection') ? $db->getConnection() : $db;
        $this->user = $user;
    }

    /* --------------------------------------------------------------
        MOBILE SEARCH
    -------------------------------------------------------------- */
    public function mobileSearch($userId, $mobileNumber) {
        if (!$this->validateMobileNumber($mobileNumber)) {
            return ['success' => false, 'message' => 'Invalid mobile number'];
        }

        $cost = $this->getSearchCost('mobile');
        $balance = $this->user->getWalletBalance($userId);

        if ($balance < $cost) {
            return ['success' => false, 'message' => 'Insufficient wallet balance'];
        }

        // Deduct wallet first
        $this->user->updateWalletBalance($userId, -$cost);

        // Load last cached data
        $cached = $this->pdo->prepare(
            "SELECT response_json FROM search_logs 
             WHERE type='mobile' AND query=? AND status='success'
             ORDER BY id DESC LIMIT 1"
        );
        $cached->execute([$mobileNumber]);
        $cachedRow = $cached->fetch(PDO::FETCH_ASSOC);
        $cachedData = $cachedRow ? json_decode($cachedRow['response_json'], true) : null;

        // API CALL
        $apiResponse = $this->callMobileAPI($mobileNumber);

        $invalid = (
            !$apiResponse ||
            (is_array($apiResponse) && empty($apiResponse)) ||
            isset($apiResponse['error'])
        );

        // FALLBACK TO DB
        if ($invalid && $cachedData) {
            $masked = $this->applyMobileVisibility($cachedData);

            $this->logSearch($userId, 'mobile', $mobileNumber, $cachedData, $cost, 'fallback');

            return [
                'success' => true,
                'data' => $masked,
                'fallback' => true,
                'message' => 'API down — showing last saved result.'
            ];
        }

        // NO API + NO CACHE → refund
        if ($invalid && !$cachedData) {
            $this->user->updateWalletBalance($userId, $cost);
            return ['success' => false, 'message' => 'API error & no backup found'];
        }

        // VALID API RESPONSE
        $masked = $this->applyMobileVisibility($apiResponse);

        // LOG API RESULT
        $this->logSearch($userId, 'mobile', $mobileNumber, $apiResponse, $cost, 'success');

        return ['success' => true, 'data' => $masked, 'fallback' => false];
    }


    /* --------------------------------------------------------------
        AADHAAR SEARCH
    -------------------------------------------------------------- */
    public function aadhaarSearch($userId, $aadhaarNumber) {
        if (!$this->validateAadhaarNumber($aadhaarNumber)) {
            return ['success' => false, 'message' => 'Invalid Aadhaar number'];
        }

        $cost = $this->getSearchCost('aadhaar');
        $balance = $this->user->getWalletBalance($userId);

        if ($balance < $cost) {
            return ['success' => false, 'message' => 'Insufficient wallet balance'];
        }

        // Deduct wallet
        $this->user->updateWalletBalance($userId, -$cost);

        // LOAD cached
        $cached = $this->pdo->prepare(
            "SELECT response_json FROM search_logs 
             WHERE type='aadhaar' AND query=? AND status='success'
             ORDER BY id DESC LIMIT 1"
        );
        $cached->execute([$aadhaarNumber]);
        $cachedRow = $cached->fetch(PDO::FETCH_ASSOC);
        $cachedData = $cachedRow ? json_decode($cachedRow['response_json'], true) : null;

        // API CALL
        $apiResponse = $this->callAadhaarAPI($aadhaarNumber);

        $invalid = (
            !$apiResponse ||
            (is_array($apiResponse) && empty($apiResponse)) ||
            isset($apiResponse['error'])
        );

        // FALLBACK TO DB
        if ($invalid && $cachedData) {
            $masked = $this->applyAadhaarVisibility($cachedData);

            $this->logSearch($userId, 'aadhaar', $aadhaarNumber, $cachedData, $cost, 'fallback');

            return [
                'success' => true,
                'data' => $masked,
                'fallback' => true,
                'message' => 'API down — showing last saved result.'
            ];
        }

        // No cache & API failed → refund
        if ($invalid && !$cachedData) {
            $this->user->updateWalletBalance($userId, $cost);
            return ['success' => false, 'message' => 'API error & no backup found'];
        }

        // SUCCESS → Mask + log
        $masked = $this->applyAadhaarVisibility($apiResponse);

        $this->logSearch($userId, 'aadhaar', $aadhaarNumber, $apiResponse, $cost);

        return ['success' => true, 'data' => $masked, 'fallback' => false];
    }



    /* --------------------------------------------------------------
       DYNAMIC MOBILE API (ADMIN CONTROLLED)
    -------------------------------------------------------------- */
    private function callMobileAPI($mobileNumber) {
        $settings = $this->getAdminSettings();
        $baseUrl = $settings['mobile_api_url'] ?? '';

        if ($baseUrl === '') {
            return ['error' => true, 'message' => 'Mobile API URL not set'];
        }

        // Placeholder format support
        if (strpos($baseUrl, '{mobile}') !== false) {
            $url = str_replace('{mobile}', urlencode($mobileNumber), $baseUrl);
        } else {
            $url = $baseUrl . urlencode($mobileNumber);
        }

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 20,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_USERAGENT => 'Mozilla/5.0'
        ]);
        $response = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) return ['error' => true, 'message' => "API Error: $error"];

        $decoded = json_decode($response, true);
        if (!$decoded) return ['error' => true, 'message' => 'Invalid API response'];

        return isset($decoded['data']) ? $decoded['data'] : $decoded;
    }


    /* --------------------------------------------------------------
       DYNAMIC AADHAAR API (ADMIN CONTROLLED)
    -------------------------------------------------------------- */
    private function callAadhaarAPI($aadhaarNumber) {
        $settings = $this->getAdminSettings();
        $baseUrl = $settings['aadhaar_api_url'] ?? '';

        if ($baseUrl === '') {
            return ['error' => true, 'message' => 'Aadhaar API URL not set'];
        }

        if (strpos($baseUrl, '{aadhaar}') !== false) {
            $url = str_replace('{aadhaar}', urlencode($aadhaarNumber), $baseUrl);
        } else {
            $url = $baseUrl . urlencode($aadhaarNumber);
        }

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 25,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_USERAGENT => 'Mozilla/5.0'
        ]);
        $response = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) return ['error' => true, 'message' => "API Error: $error"];

        $decoded = json_decode($response, true);
        if (!$decoded) return ['error' => true, 'message' => 'Invalid API response'];

        return $decoded;
    }



    /* --------------------------------------------------------------
       HELPERS + LOGGING
    -------------------------------------------------------------- */
    private function validateMobileNumber($num) {
        return preg_match('/^[6-9]\d{9}$/', $num);
    }

    private function validateAadhaarNumber($num) {
        return preg_match('/^\d{12}$/', $num);
    }

    private function getSearchCost($type) {
        $stmt = $this->pdo->prepare("SELECT setting_value FROM admin_settings WHERE setting_key=:key");
        $stmt->execute([':key' => $type . '_search_cost']);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row ? (float)$row['setting_value'] : 1.0;
    }

    private function logSearch($userId, $type, $query, $response, $cost, $status='success') {
        $stmt = $this->pdo->prepare(
            "INSERT INTO search_logs (user_id, type, query, response_json, cost, status, created_at)
             VALUES (:uid, :type, :query, :resp, :cost, :status, NOW())"
        );
        $stmt->execute([
            ':uid' => $userId,
            ':type' => $type,
            ':query' => $query,
            ':resp' => json_encode($response),
            ':cost' => $cost,
            ':status' => $status
        ]);
    }

    public function getAdminSettings() {
        $stmt = $this->pdo->query("SELECT setting_key, setting_value FROM admin_settings");
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        $res = [];
        foreach ($rows as $r) $res[$r['setting_key']] = $r['setting_value'];
        return $res;
    }


    /* --------------------------------------------------------------
       MASKING + VISIBILITY (AS-IS)
    -------------------------------------------------------------- */
    private function maskMobileNumber($num) {
        $digits = preg_replace('/\D/', '', $num);
        if (strlen($digits) < 6) return $num;
        return substr($digits, 0, 2) . str_repeat('x', strlen($digits)-4) . substr($digits, -2);
    }

    private function applyMobileVisibility($apiData) {
        $settings = $this->getAdminSettings();

        if (is_array($apiData) && array_values($apiData) === $apiData) {
            $out = [];
            foreach ($apiData as $i) $out[] = $this->maskMobileRecord($i, $settings);
            return $out;
        }

        if (is_array($apiData)) return $this->maskMobileRecord($apiData, $settings);

        return $apiData;
    }

    private function maskMobileRecord($r, $settings) {
        if (($settings['show_name_field'] ?? '1') !== '1') $r['name'] = 'Hidden';
        if (($settings['show_mobile_field'] ?? '1') !== '1') $r['mobile'] = $this->maskMobileNumber($r['mobile'] ?? '');
        if (($settings['show_fname_field'] ?? '1') !== '1') $r['fname'] = 'Hidden';
        if (($settings['show_circle_field'] ?? '1') !== '1') $r['circle'] = 'Hidden';
        if (($settings['show_id_field'] ?? '1') !== '1') $r['id'] = 'Hidden';
        if (($settings['show_credit_field'] ?? '1') !== '1') $r['credit'] = 'Hidden';
        if (($settings['show_developer_field'] ?? '1') !== '1') $r['developer'] = 'Hidden';
        if (($settings['show_address_field'] ?? '1') !== '1') $r['address'] = 'Hidden';
        return $r;
    }

    private function applyAadhaarVisibility($apiData) {
        $settings = $this->getAdminSettings();
        $d = $apiData;

        if (isset($d['data'])) $d = $d['data'];

        if (is_array($d)) {
            if (($settings['show_address_aadhaar'] ?? '1') !== '1') $d['address'] = 'Hidden';
            if (($settings['show_homeDistName'] ?? '1') !== '1') $d['homeDistName'] = $d['homeDistrict'] = 'Hidden';
            if (($settings['show_homeStateName'] ?? '1') !== '1') $d['homeStateName'] = 'Hidden';
            if (($settings['show_allowed_onorc'] ?? '1') !== '1') $d['allowed_onorc'] = 'Hidden';
            if (($settings['show_districtCode'] ?? '1') !== '1') $d['districtCode'] = 'Hidden';
            if (($settings['show_dup_uid_status'] ?? '1') !== '1') $d['dup_uid_status'] = 'Hidden';
            if (($settings['show_fpsId'] ?? '1') !== '1') $d['fpsId'] = 'Hidden';
            if (($settings['show_schemeId'] ?? '1') !== '1') $d['schemeId'] = 'Hidden';
            if (($settings['show_schemeName'] ?? '1') !== '1') $d['schemeName'] = 'Hidden';
            if (($settings['show_memberDetailsList'] ?? '1') !== '1') $d['memberDetailsList'] = [];
        }

        if (isset($apiData['data'])) {
            $apiData['data'] = $d;
            return $apiData;
        }

        return $d;
    }
}
?>
