<?php

declare(strict_types=1);

namespace mirzaev\deeproots\models;

// Files of the project
use mirzaev\deeproots\models\core,
    mirzaev\deeproots\models\account\localization;

// Svoboda time
use svoboda\time\statement as svoboda;

// Baza database
use mirzaev\baza\database,
    mirzaev\baza\column,
    mirzaev\baza\record,
    mirzaev\baza\enumerations\encoding,
    mirzaev\baza\enumerations\type;

// Framework for Telegram
use Zanzara\Telegram\Type\User as model;

// Built-in libraries
use Exception as exception,
    RuntimeException as exception_runtime;

/**
 * Telegram account
 *
 * @package mirzaev\deeproots\models
 *
 * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 */
final class telegram extends core
{
    /**
     * File
     *
     * @var string $database Path to the database file
     */
    protected string $file = DATABASES . DIRECTORY_SEPARATOR . 'telegram.baza';

    /**
     * Database
     *
     * @var database $database The database
     */
    public protected(set) database $database;

    /**
     * Constructor
     *
     * @return void
     */
    public function __construct()
    {
        // Initializing the database
        $this->database = new database()
            ->encoding(encoding::utf8)
            ->columns(
                new column('identifier', type::long_long_unsigned),
                new column('domain', type::string, ['length' => 32]),
                new column('name_first', type::string, ['length' => 64]),
                new column('name_second', type::string, ['length' => 64]),
                new column('language', type::string, ['length' => 2]),
                new column('robot', type::char),
                new column('updated', type::integer_unsigned),
                new column('created', type::integer_unsigned)
            )
            ->connect($this->file);
    }

    /**
     * Initialize
     *
     * Searches for the telegram account record in the database, and if it does not find it, then create
     *
     * @param model $telegram The telegram account
     *
     * @throws exception_runtime if failed to update the telegram account record in the database by the telegram account values
     * @throws exception_runtime if failed to find the created telegram account
     * @throws exception_runtime if failed to create the telegram account
     *
     * @return record The telegram account record from the database
     */
    public function initialize(model $telegram): record
    {
        // Searching for the account in the database
        $account = $this->database->read(filter: fn(record $record) => $record->identifier === $telegram->getId(), amount: 1)[0] ?? null;

        if ($account instanceof record) {
            // Found the telegram account record

            if (
                $account->name_first !== $telegram->getFirstName() ||
                    $account->name_second !== $telegram->getLastName() ||
                    $account->domain !== $telegram->getUsername()
            ) {
                // The telegram account was updated

                // Updating the account in the database
                $updated = $this->database->read(
                    filter: fn(record $record) => $record->identifier === $telegram->getId(),
                    update: function (record &$record) use ($telegram){
                        // Writing new values into the record
                        $record->name_first = $telegram->getFirstName();
                        $record->name_second = (string) $telegram->getLastName();
                        $record->domain = $telegram->getUsername();
                        $record->updated = svoboda::timestamp();
                    },
                    amount: 1
                )[0] ?? null;

                if ($updated instanceof record && $updated->values() !== $account->values()) {
                    // Updated the account in the database

                    // Exit (success)
                    return $updated;
                } else {
                    // Not updated the account in the database

                    // Exit (fail)
                    throw new exception_runtime('Failed to update the account record in the database by the telegram account values');
                }
            }

            // Exit (success)
            return $account;
        } else {
            // Not found the account record

            if ($this->create($telegram)) {
                // Created the account

                // Searching for the created telegram account in the database
                $account = $this->database->read(filter: fn(record $record) => $record->identifier === $telegram->getId(), amount: 1)[0] ?? null;

                if ($account instanceof record) {
                    // Found the created telegram account

                    // Exit (success)
                    return $account;
                } else {
                    // Not found the created telegram account

                    // Exit (fail)
                    throw new exception_runtime('Failed to find the created telegram account');
                }
            } else {
                // Not created the telegram account

                // Exit (fail)
                throw new exception_runtime('Failed to create the telegram account');
            }
        }
    }

    /**
     * Create
     *
     * Creates the account record in the database
     *
     * @param model $telegram The telegram account
     *
     * @return int|false The record identifier, if created
     */
    public function create(model $telegram): int|false
    {
        // Initializing the identifier
        $identifier = (int) $telegram->getId();

        echo(svoboda::timestamp());

        // Initializing the record
        $record = $this->database->record(
            $identifier,
            $telegram->getUsername(),
            $telegram->getFirstName(),
            (string) $telegram->getLastName(),
            $telegram->getLanguageCode(),
            (int) $telegram->isBot(),
            svoboda::timestamp(),
            svoboda::timestamp()
        );

        // Creating the record in the database
        $created = $this->database->write($record);

        // Exit (success)
        return $created ? $identifier : false;
    }
}
