<?php

declare(strict_types=1);

/** @var PDO $pdo */
$pdo = require __DIR__ . '/../../connection_pdo.php';

include_once __DIR__ . '/../session_guards.php';

header('Content-Type: application/json; charset=utf-8');

function userNormalizeAddonDomainInput(string $value): ?string
{
    $domain = strtolower(trim($value));
    $domain = preg_replace('/^https?:\/\//i', '', $domain) ?? '';
    $domain = trim($domain, " \t\n\r\0\x0B./");

    if ($domain === '' || strlen($domain) > 253) {
        return null;
    }

    if (preg_match('/[\/\\:@?#\[\]]/', $domain) === 1) {
        return null;
    }

    if (preg_match('/^(localhost|localdomain)$/i', $domain) === 1) {
        return null;
    }

    if (filter_var($domain, FILTER_VALIDATE_IP) !== false) {
        return null;
    }

    if (preg_match('/^(?=.{1,253}$)(?!-)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/', $domain) !== 1) {
        return null;
    }

    return $domain;
}

function userDomainRows(PDO $pdo, string $subDomain): array
{
    $stmt = $pdo->prepare('SELECT sub_domain, domain FROM addondomain WHERE sub_domain = :sub_domain ORDER BY domain ASC');
    if (!$stmt) {
        throw new RuntimeException('Failed to prepare user domain list query.');
    }

    $stmt->execute(['sub_domain' => $subDomain]);

    $rows = [];
    $counter = 1;
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $rows[] = [
            'id' => $counter++,
            'sub_domain' => (string) ($row['sub_domain'] ?? ''),
            'domain' => (string) ($row['domain'] ?? ''),
        ];
    }

    return $rows;
}

try {
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        jsonError(405, 'method-not-allowed');
    }

    startUserGuardSession();
    $sessionSubId = authenticatedUserSubId();
    if ($sessionSubId === '') {
        jsonError(403, 'unauthorized');
    }
    if (!hasValidSessionCsrf('user_portal', requestCsrfToken())) {
        jsonError(419, 'invalid-csrf');
    }

    $subDomain = strtoupper(trim((string) ($_POST['sub_domain'] ?? '')));
    $domain = userNormalizeAddonDomainInput((string) ($_POST['domain'] ?? ''));
    if ($subDomain === '') {
        jsonError(422, 'missing-fields');
    }
    if ($domain === null) {
        jsonError(422, 'invalid-domain');
    }
    if ($subDomain !== $sessionSubId) {
        jsonError(403, 'forbidden');
    }

    $existingStmt = $pdo->prepare(
        'SELECT id FROM addondomain WHERE sub_domain = :sub_domain AND domain = :domain ORDER BY id ASC LIMIT 1',
    );
    if (!$existingStmt) {
        throw new RuntimeException('Failed to prepare duplicate domain query.');
    }
    $existingStmt->execute(['sub_domain' => $subDomain, 'domain' => $domain]);
    if ($existingStmt->fetchColumn() !== false) {
        echo json_encode(
            userDomainRows($pdo, $subDomain),
            JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_THROW_ON_ERROR,
        );
        exit;
    }

    $stmt = $pdo->prepare('INSERT INTO addondomain (sub_domain, domain) VALUES (:sub_domain, :domain)');
    if (!$stmt) {
        throw new RuntimeException('Failed to prepare insert query.');
    }

    $stmt->execute(['sub_domain' => $subDomain, 'domain' => $domain]);

    echo json_encode(userDomainRows($pdo, $subDomain), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_THROW_ON_ERROR);
} catch (Throwable $e) {
    jsonError(500, 'server-error');
}
