<?php

namespace App\Controller;

error_reporting(error_level: E_ALL);


use PDO;
use PDOException;

/**
 *
 */
class DatabaseConnection
{
    private PDO $dbConnection;

    const TABLE_PREFIX = '';
    const TABLE_DOMAINS = self::TABLE_PREFIX . "domains";
    const TABLE_NAMESERVERS = self::TABLE_PREFIX . "nameservers";
    const TABLE_PANELS = self::TABLE_PREFIX . "panels";
    const TABLE_APIKEYS = self::TABLE_PREFIX . "apikeys";
    const TABLE_DYNDNS = self::TABLE_PREFIX . "dyndns";

    public function __construct(private readonly ConfigController $configController)
    {
        $dbHost = $this->configController->getConfig(configKey: 'dbHost');
        $dbPort = $this->configController->getConfig(configKey: 'dbPort');
        $dbDatabase = $this->configController->getConfig(configKey: 'dbDatabase');
        $dbUser = $this->configController->getConfig(configKey: 'dbUser');
        $dbPassword = $this->configController->getConfig(configKey: 'dbPassword');


        if (!$this->configController->getConfig(configKey: 'test')) {
            // TODO create config => encryption key
            try {
                $this->dbConnection = new PDO(
                    dsn: "mysql:host=$dbHost;port=$dbPort;charset=utf8mb4;dbname=$dbDatabase",
                    username: $dbUser,
                    password: $dbPassword
                );
                $sql = "SHOW TABLES";
                $statement = $this->dbConnection->prepare(query: $sql);
                $statement->execute();
                $result = $statement->fetch();
                if (empty($result)) {
                    // ALTER TABLE `domains` ADD `panel_id` INT NULL AFTER `id`;
                    echo 'Error: Cannot find tables.' . PHP_EOL;
                    if (confirm(message: 'Should I try to create them?')) {
                        $sql = "
						CREATE TABLE `apikeys` (
	                        `id` int(11) NOT NULL AUTO_INCREMENT,
	                        `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
	                        `api_token_prefix` varchar(13) COLLATE utf8mb4_unicode_ci NOT NULL,
	                        `api_token` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
	                        PRIMARY KEY (`id`)
						) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
                        $statement = $this->dbConnection->prepare(query: $sql);
                        $statement->execute();

                        $sql = "
						CREATE TABLE `domains` (
							`id` int(11) NOT NULL AUTO_INCREMENT,
							`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  							`panel` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
							PRIMARY KEY (`id`)
						) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
                        $statement = $this->dbConnection->prepare(query: $sql);
                        $statement->execute();

                        $sql = "
						CREATE TABLE `nameservers` (
							`id` int(11) NOT NULL AUTO_INCREMENT,
							`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
							`a` varbinary(255) DEFAULT NULL,
							`aaaa` varbinary(255) DEFAULT NULL,
							`apikey` varbinary(255) DEFAULT NULL,
							PRIMARY KEY (`id`)
						) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
                        $statement = $this->dbConnection->prepare(query: $sql);
                        $statement->execute();

                        $sql = "
						CREATE TABLE `panels` (
							`id` int(11) NOT NULL AUTO_INCREMENT,
							`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
							`a` varbinary(255) DEFAULT NULL,
							`aaaa` varbinary(255) DEFAULT NULL,
							`apikey` varbinary(255) DEFAULT NULL,
							PRIMARY KEY (`id`)
						) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
                        $statement = $this->dbConnection->prepare(query: $sql);
                        $statement->execute();

                        $sql = "
						CREATE TABLE `dyndns` (
							`id` int(11) NOT NULL AUTO_INCREMENT,
							`name` VARCHAR(255) NOT NULL,
							`a` VARBINARY(255) NOT NULL,
							`aaaa` VARBINARY(255) NOT NULL,
							`last_update` TIMESTAMP NOT NULL,
							PRIMARY KEY (`id`)
						) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";

                        $statement = $this->dbConnection->prepare(query: $sql);
                        $statement->execute();

                        echo 'Tables have been created.' . PHP_EOL;
                    }
                    exit(1);
                }

            } catch (PDOException $exception) {
                echo $exception->getMessage() . PHP_EOL;
                echo 'Did you create the database and adjust the config file?' . PHP_EOL;
                echo PHP_EOL . 'You can create database an user via a panel or manually in mysql shell:' . PHP_EOL;
                $password = $this->generatePassword();
                echo 'Created an initial password: ' . $password . PHP_EOL;
                echo 'CREATE DATABASE bindAPI;' . PHP_EOL;
                echo "CREATE USER 'bindAPI'@'localhost' IDENTIFIED BY '$password';" . PHP_EOL;
                echo "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON bindAPI.* TO 'bindAPI'@'localhost';" . PHP_EOL;
                echo 'There is no need to run FLUSH PRIVILEGES when using GRANT!' . PHP_EOL;
                exit(1);
            }
        }
    }


    /**
     * @param int $length
     *
     * @return string
     */
    function generatePassword(int $length = 8): string
    {
        $chars = '23456789bcdfhkmnprstvzBCDFHJKLMNPRSTVZ';
        $shuffled = str_shuffle(string: $chars);
        return mb_substr(string: $shuffled, start: 0, length: $length);
    }

    /**
     * @return PDO
     */
    public function getConnection(): PDO
    {
        return $this->dbConnection;
    }
}
