<?php
/**
 * PageMapper for SphinxSearch plugin
 * Handles mapping between DokuWiki Page IDs and Sphinx CRCs
 */

class PageMapper {
    private ?PDO $_db = null;
    private string $_dbFile = '';

    public function __construct() {
        global $conf;

        // 1. Resolve the savedir relative to DOKU_INC
        // This handles cases where savedir is just 'data' or './data'
        $saveDir = $conf['savedir'];
        if (strpos($saveDir, '/') !== 0 && !preg_match('/^[a-z]:\\\/i', $saveDir)) {
            // It is a relative path, anchor it to DOKU_INC
            $saveDir = DOKU_INC . $saveDir;
        }
        
        $dbPath = $saveDir . '/sphinxsearchwas';
        
        // 2. Ensure the directory exists
        if (!is_dir($dbPath)) {
            @mkdir($dbPath, 0777, true);
        }

        $this->_dbFile = $dbPath . '/pages.db';
        
        // DEBUG: Uncomment the line below if it still fails, to see where it is trying to write
        // file_put_contents('php://stderr', "Writing DB to: " . $this->_dbFile . "\n");

        $this->_initDb();
    }

    /**
     * Connect to SQLite and ensure the table exists
     */
    private function _initDb(): void {
        try {
            $this->_db = new PDO("sqlite:" . $this->_dbFile);
            $this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            
            // Create the table if it doesn't exist
            $sql = "CREATE TABLE IF NOT EXISTS pages (
                page TEXT,
                title TEXT,
                title_text TEXT,
                hid TEXT,
                crc INTEGER PRIMARY KEY
            )";
            $this->_db->exec($sql);
            
            // Optimization for SQLite
            $this->_db->exec("PRAGMA journal_mode = WAL");
            $this->_db->exec("PRAGMA synchronous = NORMAL");

        } catch (PDOException $e) {
            die("Database Error: " . $e->getMessage());
        }
    }

    /**
     * Add or Update a page mapping
     */
    public function add(string $page, string $title, string $title_text = '', string $hid = ''): void {
        $crc = sprintf('%u', crc32($page . $hid) ?: 1);
        
        $sql = "REPLACE INTO pages (page, title, title_text, hid, crc) 
                VALUES (:page, :title, :title_text, :hid, :crc)";
        
        try {
            $stmt = $this->_db->prepare($sql);
            $stmt->bindValue(':page', $page);
            $stmt->bindValue(':title', $title);
            $stmt->bindValue(':title_text', $title_text);
            $stmt->bindValue(':hid', $hid);
            $stmt->bindValue(':crc', $crc);
            $stmt->execute();
        } catch (PDOException $e) {
            // Ignore write errors during indexing to keep stream alive
        }
    }

    /**
     * Retrieve mapping by CRC
     */
    public function getByCrc(array $crcs): array {
        if (empty($crcs)) return [];

        $placeholders = implode(',', array_fill(0, count($crcs), '?'));
        $sql = "SELECT * FROM pages WHERE crc IN ($placeholders)";

        try {
            $stmt = $this->_db->prepare($sql);
            $stmt->execute(array_values($crcs));
            $results = [];
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                $results[$row['crc']] = $row;
            }
            return $results;
        } catch (PDOException $e) {
            return [];
        }
    }
}
