<?php
namespace app\models;

use app\app;
use app\models\emails;

class magic_links
{
    public static function init()
    {
        app::$db->exec("CREATE TABLE IF NOT EXISTS magic_links (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id INTEGER REFERENCES users(id),
            email TEXT NOT NULL,
            code TEXT NOT NULL,
            token TEXT NOT NULL,
            ipv4 TEXT NOT NULL,
            expires_at DATETIME NOT NULL,
            used BOOLEAN DEFAULT FALSE
        )");
    }

    public static function add($email, $user_id)
    {
        $token = bin2hex(random_bytes(32));
        $seed  = hexdec(substr($token, 0, 8)); // Use the first 8 characters of the token as a seed
        mt_srand($seed);
        $code       = str_pad(strval(mt_rand(0, 999999)), 6, "0", STR_PAD_LEFT);
        $expires_at = date('Y-m-d H:i:s', time() + 60 * 15);
        $ipv4       = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; // Get client's IPv4 address
        $query      = "INSERT INTO magic_links (
            email,
            user_id,
            token,
            code,
            expires_at,
            ipv4
        ) VALUES (
            :email,
            :user_id,
            :token,
            :code,
            :expires_at,
            :ipv4
        )";
        $stmt = app::$db->prepare($query);
        $stmt->bindParam(':email', $email);
        $stmt->bindParam(':user_id', $user_id);
        $stmt->bindParam(':token', $token);
        $stmt->bindParam(':code', $code);
        $stmt->bindParam(':expires_at', $expires_at);
        $stmt->bindParam(':ipv4', $ipv4);
        $stmt->execute();
        $link          = $_ENV['APP_HOST'] . "/magic-link?token=" . urlencode($token);
        $subject       = "Your Magic Sign-In Link";
        $message       = "Enter this code into the sign-in form\n$code\n or copy-paste this link into your browser to sign in:\n$link";
        $template_vars = ['code' => $code, 'link' => $link];
        emails::send(
            $subject,
            $_ENV['SMTP_FROM'],
            $_ENV['APP_NAME'],
            $email,
            $message,
            'verify.twig',
            $template_vars
        );
        $_SESSION['success'] = 'Link sent to your email!';
        return $token;
    }

    public static function validateToken($token)
    {
        $query = "SELECT * FROM magic_links
            WHERE token = :token
            AND used = FALSE
            AND expires_at > datetime('now')";
        $stmt = app::$db->prepare($query);
        $stmt->bindParam(':token', $token);
        $stmt->execute();
        $link = $stmt->fetch(\PDO::FETCH_ASSOC);

        $updateQuery = "UPDATE magic_links SET used = TRUE WHERE token = :token";
        $updateStmt  = app::$db->prepare($updateQuery);
        $updateStmt->bindParam(':token', $token);
        $updateStmt->execute();

        return $link;
    }

    public static function validateCode($code)
    {
        $query = "SELECT * FROM magic_links
            WHERE code = :code
            AND used = FALSE
            AND expires_at > datetime('now')";
        $stmt = app::$db->prepare($query);
        $stmt->bindParam(':code', $code);
        $stmt->execute();
        $link = $stmt->fetch(\PDO::FETCH_ASSOC);

        $updateQuery = "UPDATE magic_links SET used = TRUE WHERE code = :code";
        $updateStmt  = app::$db->prepare($updateQuery);
        $updateStmt->bindParam(':code', $code);
        $updateStmt->execute();

        return $link;
    }
}
