<?php
declare(strict_types=1);

namespace App;

final class CommunityMigration
{
    public function __construct(private \PDO $pdo)
    {
    }

    public function status(): array
    {
        $checks = [
            'forum_categories' => $this->hasTable('forum_categories'),
            'forum_boards' => $this->hasTable('forum_boards'),
            'forum_post_feedback' => $this->hasTable('forum_post_feedback'),
            'forum_reports' => $this->hasTable('forum_reports'),
            'user_roles' => $this->hasTable('user_roles'),
            'community_admin_applications' => $this->hasTable('community_admin_applications'),
            'community_user_restrictions' => $this->hasTable('community_user_restrictions'),
            'forum_threads.board_id' => $this->hasColumn('forum_threads', 'board_id'),
            'forum_posts.highlighted_by' => $this->hasColumn('forum_posts', 'highlighted_by'),
            'forum_posts.highlighted_at' => $this->hasColumn('forum_posts', 'highlighted_at'),
        ];

        $missing = array_keys(array_filter($checks, static fn(bool $ok): bool => !$ok));

        return [
            'complete' => $missing === [],
            'checks' => $checks,
            'missing' => $missing,
        ];
    }

    public function apply(): array
    {
        $statements = [
            'CREATE TABLE IF NOT EXISTS forum_categories (
              id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
              slug VARCHAR(120) NOT NULL UNIQUE,
              title VARCHAR(180) NOT NULL,
              sort_order SMALLINT UNSIGNED NOT NULL DEFAULT 0
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci',

            'CREATE TABLE IF NOT EXISTS forum_boards (
              id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
              category_id BIGINT UNSIGNED NOT NULL,
              slug VARCHAR(120) NOT NULL UNIQUE,
              title VARCHAR(180) NOT NULL,
              description TEXT NULL,
              icon VARCHAR(32) NULL,
              sort_order SMALLINT UNSIGNED NOT NULL DEFAULT 0,
              INDEX idx_fb_category (category_id)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci',

            'ALTER TABLE forum_threads
              ADD COLUMN IF NOT EXISTS board_id BIGINT UNSIGNED NULL,
              ADD INDEX IF NOT EXISTS idx_ft_board (board_id)',

            'ALTER TABLE forum_posts
              ADD COLUMN IF NOT EXISTS highlighted_by BIGINT UNSIGNED NULL,
              ADD COLUMN IF NOT EXISTS highlighted_at DATETIME NULL',

            'CREATE TABLE IF NOT EXISTS forum_post_feedback (
              post_id BIGINT UNSIGNED NOT NULL,
              user_id BIGINT UNSIGNED NOT NULL,
              value TINYINT NOT NULL,
              created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
              updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
              PRIMARY KEY (post_id, user_id),
              INDEX idx_fpf_value (value)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci',

            'CREATE TABLE IF NOT EXISTS forum_reports (
              id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
              reporter_user_id BIGINT UNSIGNED NOT NULL,
              target_type ENUM("thread","post") NOT NULL,
              target_id BIGINT UNSIGNED NOT NULL,
              reason TEXT NOT NULL,
              status ENUM("open","resolved","dismissed") NOT NULL DEFAULT "open",
              moderator_user_id BIGINT UNSIGNED NULL,
              moderator_note TEXT NULL,
              resolved_at DATETIME NULL,
              created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
              INDEX idx_fr_status (status),
              INDEX idx_fr_target (target_type, target_id)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci',

            'CREATE TABLE IF NOT EXISTS user_roles (
              user_id BIGINT UNSIGNED NOT NULL,
              role ENUM("forum_admin","site_admin","owner") NOT NULL,
              assigned_by BIGINT UNSIGNED NULL,
              assigned_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
              PRIMARY KEY (user_id, role)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci',

            'CREATE TABLE IF NOT EXISTS community_admin_applications (
              id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
              user_id BIGINT UNSIGNED NOT NULL,
              motivation TEXT NOT NULL,
              status ENUM("open","approved","rejected") NOT NULL DEFAULT "open",
              decision_reason TEXT NULL,
              decided_by BIGINT UNSIGNED NULL,
              decided_at DATETIME NULL,
              created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
              INDEX idx_caa_status (status)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci',

            'CREATE TABLE IF NOT EXISTS community_user_restrictions (
              id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
              user_id BIGINT UNSIGNED NOT NULL,
              restriction_type ENUM("thread_create_blocked","reply_blocked") NOT NULL,
              reason TEXT NULL,
              active TINYINT(1) NOT NULL DEFAULT 1,
              created_by BIGINT UNSIGNED NOT NULL,
              expires_at DATETIME NULL,
              created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
              INDEX idx_cur_user_active (user_id, active)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci',
        ];

        foreach ($statements as $sql) {
            $this->pdo->exec($sql);
        }

        // Initial owner/site-admin bootstrap for user 1 if roles table exists.
        if ($this->hasTable('user_roles')) {
            $stmt = $this->pdo->prepare('INSERT IGNORE INTO user_roles (user_id, role, assigned_by) VALUES (1, "owner", 1)');
            $stmt->execute();
            $stmt = $this->pdo->prepare('INSERT IGNORE INTO user_roles (user_id, role, assigned_by) VALUES (1, "site_admin", 1)');
            $stmt->execute();
        }

        return $this->status();
    }

    private function hasTable(string $table): bool
    {
        $stmt = $this->pdo->prepare('SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = :table LIMIT 1');
        $stmt->execute(['table' => $table]);
        return (bool)$stmt->fetchColumn();
    }

    private function hasColumn(string $table, string $column): bool
    {
        $stmt = $this->pdo->prepare('SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = :table AND column_name = :column LIMIT 1');
        $stmt->execute([
            'table' => $table,
            'column' => $column,
        ]);
        return (bool)$stmt->fetchColumn();
    }
}
