<?php
namespace app\models;

use app\app;
use app\models\addresses;
use app\models\emails;
use app\models\user_settings;
use swentel\nostr\Key\Key;

class users
{
    public static function init()
    {
        app::$db->exec("CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            email TEXT UNIQUE,
            shipping_address_id INTEGER REFERENCES addresses(id),
            billing_address_id INTEGER REFERENCES addresses(id),
            lifetime_spend INTEGER DEFAULT 0,
            lifetime_orders INTEGER DEFAULT 0,
            verified BOOLEAN NOT NULL,
            nsec TEXT,
            npub TEXT NOT NULL,
            replace_email_token TEXT,
            name TEXT,
            company_name TEXT,
            company_type TEXT,
            company_size TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )");
    }

    public static function setDefaultShipping($user_id, $shipping_address_id)
    {
        $query = "UPDATE users SET shipping_address_id = :shipping_address_id WHERE id = :user_id";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':shipping_address_id', $shipping_address_id, \PDO::PARAM_INT);
        $stmt->bindParam(':user_id', $user_id, \PDO::PARAM_INT);
        $stmt->execute();
    }
    public static function updateOptIn($user_id, $opt_in_promotional, $opt_in_subscription, $opt_in_order)
    {
        $query = "UPDATE user_settings SET
                    opt_in_promotional = :opt_in_promotional,
                    opt_in_subscription = :opt_in_subscription,
                    opt_in_order = :opt_in_order
                  WHERE user_id = :user_id";
        $stmt = app::$db->prepare($query);
        $stmt->bindParam(':opt_in_promotional', $opt_in_promotional, \PDO::PARAM_BOOL);
        $stmt->bindParam(':opt_in_subscription', $opt_in_subscription, \PDO::PARAM_BOOL);
        $stmt->bindParam(':opt_in_order', $opt_in_order, \PDO::PARAM_BOOL);
        $stmt->bindParam(':user_id', $user_id, \PDO::PARAM_INT);
        $stmt->execute();
    }

    public static function setDefaultBilling($user_id, $billing_address_id)
    {
        $query = "UPDATE users SET billing_address_id = :billing_address_id WHERE id = :user_id";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':billing_address_id', $billing_address_id, \PDO::PARAM_INT);
        $stmt->bindParam(':user_id', $user_id, \PDO::PARAM_INT);
        $stmt->execute();
    }

    public static function updateReplaceEmailTokenById($user_id, $replace_token)
    {
        $query = "UPDATE users SET replace_email_token = :replace_token WHERE id = :user_id";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':replace_token', $replace_token);
        $stmt->bindParam(':user_id', $user_id);
        $stmt->execute();
    }

    public static function updateEmailById($user_id, $email)
    {
        $query = "UPDATE users SET email = :email, replace_email_token = NULL WHERE id = :user_id";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':email', $email);
        $stmt->bindParam(':user_id', $user_id);
        $stmt->execute();
    }

    public static function getByReplaceEmailToken($token)
    {
        $query = "SELECT * FROM users WHERE replace_email_token = :token";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':token', $token);
        $stmt->execute();
        return $stmt->fetch(\PDO::FETCH_ASSOC);
    }

    public static function updateProfileById($user_id, $post)
    {
        $query = "UPDATE users SET
            name = :name,
            company_name = :company_name,
            company_type = :company_type,
            company_size = :company_size
            WHERE id = :user_id";
        $stmt = app::$db->prepare($query);
        $stmt->bindParam(':name', $post['name']);
        $stmt->bindParam(':company_name', $post['company_name']);
        $stmt->bindParam(':company_type', $post['company_type']);
        $stmt->bindParam(':company_size', $post['company_size']);
        $stmt->bindParam(':user_id', $user_id);
        $stmt->execute();
    }

    public static function add($email, $ship_id, $bill_id, $opt_in_promotional, $verified, $dark_theme)
    {
        $key         = new Key();
        $private_key = $key->generatePrivateKey();
        $public_key  = $key->getPublicKey($private_key);
        $npub        = $key->convertPublicKeyToBech32($public_key);
        $nsec        = $key->convertPrivateKeyToBech32($private_key);
        $query       = "INSERT INTO users (
            email,
            shipping_address_id,
            billing_address_id,
            verified,
            nsec,
            npub
        ) VALUES (
            :email,
            :shipping_address_id,
            :billing_address_id,
            :verified,
            :nsec,
            :npub
        )";
        $stmt = app::$db->prepare($query);
        $stmt->bindParam(':email', $email);
        $stmt->bindParam(':shipping_address_id', $ship_id);
        $stmt->bindParam(':billing_address_id', $bill_id);
        $stmt->bindParam(':verified', $verified);
        $stmt->bindParam(':nsec', $nsec);
        $stmt->bindParam(':npub', $npub);
        $stmt->execute();
        $user_id = app::$db->lastInsertId();
        user_settings::add($user_id, $opt_in_promotional, $dark_theme);
        addresses::updateUserIdById($ship_id, $user_id);
        if ($ship_id != $bill_id) {
            addresses::updateUserIdById($bill_id, $user_id);
        }
        emails::updateUserIdByEmail($email, $user_id);
        return $user_id;
    }

    public static function verify($email)
    {
        $query = "UPDATE users SET verified = 1 WHERE email = :email";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':email', $email);
        $stmt->execute();
    }

    public static function getById($id)
    {
        $query = "SELECT * FROM users WHERE id = :id";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->execute();
        return $stmt->fetch(\PDO::FETCH_ASSOC);
    }

    public static function getByNpub($npub)
    {
        $query = "SELECT * FROM users WHERE npub = :npub";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':npub', $npub);
        $stmt->execute();
        return $stmt->fetch(\PDO::FETCH_ASSOC);
    }

    public static function getByEmail($email)
    {
        $query = "SELECT * FROM users WHERE email = :email";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':email', $email);
        $stmt->execute();
        return $stmt->fetch(\PDO::FETCH_ASSOC);
    }

    public static function getUsers($n)
    {
        $query = "SELECT * FROM users LIMIT :limit";
        $stmt  = app::$db->prepare($query);
        $stmt->bindParam(':limit', $n, \PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll(\PDO::FETCH_ASSOC);
    }
}
