<?php

namespace pictpostpersonal\model;

use pictpostpersonal\SQLiteCRUD;
use Exception;

/**
 * トークン管理用モデルクラス
 */
class TokenModel
{
    /**
     * @var SQLiteCRUD データベース操作補助クラス
     */
    private $db;

    /**
     * コンストラクタ
     *
     * @param SQLiteCRUD $db SQLiteCRUD インスタンス
     */
    public function __construct(SQLiteCRUD $db)
    {
        $this->db = $db;
    }

    private function initialize()
    {
        $this->db->table('tokens')->createTable(
            [
                'id INTEGER PRIMARY KEY AUTOINCREMENT',
                'token_hash CHAR(64) NOT NULL UNIQUE',
                'user_id VARCHAR(255) NOT NULL',
                'expiration DATETIME NOT NULL',
                'created_at DATETIME DEFAULT CURRENT_TIMESTAMP',
                'updated_at DATETIME DEFAULT CURRENT_TIMESTAMP'
            ],
            [
                'token_hash',
                'user_id',
                'expiration'
            ]
        );
    }

    /**
     * トークンをデータベースに保存する
     *
     * @param string $tokenHash SHA-256 ハッシュ化されたトークン
     * @param string $userId ユーザーID
     * @param int $expirationTimestamp UNIXタイムスタンプの有効期限
     * @return bool 成功時は true
     */
    public function saveToken(string $token_hash, string $user_id, $expiration_timestamp): bool
    {
        $expiration = date('Y-m-d H:i:s', $expiration_timestamp);
        $data = [
            'token_hash' => $token_hash,
            'user_id' => $user_id,
            'expiration' => $expiration
        ];

        try {
            $this->db->create($data);
            return true;
        } catch (Exception $e) {
            // エラーハンドリング（ログに記録するなど）
            return false;
        }
    }

    /**
     * トークンを削除する
     *
     * @param string $tokenHash SHA-256 ハッシュ化されたトークン
     * @return bool 成功時は true
     */
    public function deleteToken(string $token_hash): bool
    {
        $this->db->where('token_hash = :token_hash', ['token_hash' => $token_hash]);
        try {
            $deleted_rows = $this->db->delete();
            return $deleted_rows > 0;
        } catch (Exception $e) {
            // エラーハンドリング
            return false;
        }
    }

    /**
     * 有効なトークンを取得する
     *
     * @param string $tokenHash SHA-256 ハッシュ化されたトークン
     * @return array|null トークン情報または null
     */
    public function getValidToken(string $token_hash): ?array
    {
        $current_time = date('Y-m-d H:i:s');
        $this->db->where('token_hash = :token_hash AND expiration > :current_time', [
            'token_hash' => $token_hash,
            'current_time' => $current_time
        ]);

        $result = $this->db->fetch();

        return $result[0] ?? null;
    }

    /**
     * ユーザーIDに紐づくトークンを全て削除する
     *
     * @param string $userId ユーザーID
     * @return bool 成功時は true
     */
    public function deleteTokensByUserId(string $user_id): bool
    {
        $this->db->where('user_id = :user_id', ['user_id' => $user_id]);
        try {
            $deleted_rows = $this->db->delete();
            return $deleted_rows > 0;
        } catch (Exception $e) {
            // エラーハンドリング
            return false;
        }
    }

    /**
     * トークンの有効期限を更新する
     *
     * @param string $tokenHash SHA-256 ハッシュ化されたトークン
     * @param int $newExpirationTimestamp UNIXタイムスタンプの新しい有効期限
     * @return bool 成功時は true
     */
    public function refreshToken(string $token_hash, $new_expiration_timestamp): bool
    {
        $new_expiration = date('Y-m-d H:i:s', $new_expiration_timestamp);
        $data = [
            'expiration' => $new_expiration
        ];

        $this->db->where('token_hash = :token_hash', ['token_hash' => $token_hash]);

        try {
            $updated_rows = $this->db->update($data);
            return $updated_rows > 0;
        } catch (Exception $e) {
            // エラーハンドリング
            return false;
        }
    }
}
