<?php
/**
 * A centralized place for data access for the application
 */
class Data {

    /**
     * Obtain a new connection to the database
     * @return SQLite3 A new connection to the database
     */
    private static function getConnection(): SQLite3 {
        $db = new SQLite3('../data/' . DATABASE_NAME);
        $db->exec('PRAGMA foreign_keys = ON;');
        return $db;
    }

    /**
     * Make sure the expected tables exist
     */
    public static function ensureDb(): void {
        $db = self::getConnection();
        $tables = array();
        $tableQuery = $db->query("SELECT name FROM sqlite_master WHERE type = 'table'");
        while ($table = $tableQuery->fetchArray(SQLITE3_NUM)) $tables[] = $table[0];
        if (!in_array('frc_user', $tables)) {
            $query = <<<'SQL'
                CREATE TABLE frc_user (
                    id       INTEGER NOT NULL PRIMARY KEY,
                    email    TEXT    NOT NULL,
                    password TEXT    NOT NULL)
                SQL;
            $db->exec($query);
            $db->exec('CREATE INDEX idx_user_email ON frc_user (email)');
        }
        if (!in_array('feed', $tables)) {
            $query = <<<'SQL'
                CREATE TABLE feed (
                    id         INTEGER NOT NULL PRIMARY KEY,
                    user_id    INTEGER NOT NULL,
                    url        TEXT    NOT NULL,
                    title      TEXT,
                    updated_on TEXT,
                    checked_on TEXT,
                    FOREIGN KEY (user_id) REFERENCES frc_user (id))
                SQL;
            $db->exec($query);
        }
        if (!in_array('item', $tables)) {
            $query = <<<'SQL'
                CREATE TABLE item (
                    id            INTEGER NOT NULL PRIMARY KEY,
                    feed_id       INTEGER NOT NULL,
                    title         TEXT    NOT NULL,
                    published_on  TEXT    NOT NULL,
                    updated_on    TEXT,
                    content       TEXT    NOT NULL,
                    is_encoded    BOOLEAN NOT NULL,
                    is_read       BOOLEAN NOT NULL,
                    is_bookmarked BOOLEAN NOT NULL,
                    FOREIGN KEY (feed_id) REFERENCES feed (id))
                SQL;
            $db->exec($query);
        }
        $db->close();
    }

    /**
     * Find a user by their ID
     *
     * @param string $email The e-mail address of the user to retrieve
     * @return array|null The user information, or null if the user is not found
     */
    public static function findUserByEmail(string $email): ?array {
        $db = self::getConnection();
        $query = $db->prepare('SELECT * FROM frc_user WHERE email = :email');
        $query->bindValue(':email', $email);
        $result = $query->execute();
        if ($result) {
            $user = $result->fetchArray(SQLITE3_ASSOC);
            if ($user) return $user;
            return null;
        }
        return null;
    }

    /**
     * Add a user
     *
     * @param string $email The e-mail address for the user
     * @param string $password The user's password
     */
    public static function addUser(string $email, string $password): void {
        $db = self::getConnection();
        $query = $db->prepare('INSERT INTO frc_user (email, password) VALUES (:email, :password)');
        $query->bindValue(':email', $email);
        $query->bindValue(':password', password_hash($password, PASSWORD_DEFAULT));
        $query->execute();
    }

    /**
     * Add an RSS feed
     * @param string $url The URL for the RSS feed
     * @param string $title The title of the RSS feed
     * @param string $updatedOn The date/time the RSS feed was last updated (from the XML, not when we checked)
     * @return int The ID of the added feed
     */
    public static function addFeed(string $url, string $title, string $updatedOn): int {
        $db = self::getConnection();
        if ($updatedOn) {
            try {
                $updated = (new DateTimeImmutable($updatedOn))->format(DateTimeInterface::ATOM);
            } catch (Exception $ex) {
                $updated = null;
            }
        } else {
            $updated = null;
        }
        $query = $db->prepare('INSERT INTO feed (user_id, url, title, updated_on, checked_on)'
            . ' VALUES (:user, :url, :title, :updated, :checked)');
        $query->bindValue(':user', $_REQUEST['FRC_USER_ID']);
        $query->bindValue(':url', $url);
        $query->bindValue(':title', $title);
        $query->bindValue(':updated', $updated);
        $query->bindValue(':checked', (new DateTimeImmutable())->format(DateTimeInterface::ATOM));
        $result = $query->execute();
        if ($result) {
            $idQuery = $db->prepare('SELECT last_insert_rowid()');
            $idResult = $idQuery->execute();
            if ($idResult) return $idResult->fetchArray(SQLITE3_NUM)[0];
        }
        return -1;
    }
}