<?php

namespace FleekDash\Core;

use WP_REST_Response;

/**
 * Tests the points_per_event migration status and functionality.
 * Extracted from DebugController for S1448 compliance (method count).
 */
class GrowthMigrationTester
{
    private const MIGRATION_NAME = '2025_10_26_000001_add_points_per_event_to_growth_events';

    /**
     * Run all migration tests and return results
     *
     * @return WP_REST_Response
     */
    public function runTests()
    {
        try {
            global $wpdb;
            $table = $wpdb->prefix . 'fleekdash_site_growth_events';
            $migrationsTable = $wpdb->prefix . 'fleekdash_migrations';

            $results = ['tests' => [], 'summary' => []];

            $results['tests']['migrations_table'] = $this->runMigrationTableTest($migrationsTable);
            $results['tests']['migration_executed'] = $this->runMigrationExecutedTest($migrationsTable);
            $results['tests']['events_table'] = $this->runEventsTableTest($table);
            $eventsPass = $results['tests']['events_table']['status'] === 'pass';
            $results['tests']['column_exists'] = $this->runColumnExistsTest($table, $eventsPass);
            $results['tests']['events_data'] = $this->runEventsDataTest($table, $eventsPass);
            $results['tests']['calculation_function'] = $this->runCalculationFunctionTest();

            $results['summary'] = $this->buildMigrationTestSummary($results['tests']);

            return new WP_REST_Response(['success' => true, 'data' => $results], 200);
        } catch (\Exception $e) {
            if (function_exists('fleekdash_log_error')) {
                fleekdash_log_error('FleekDash Debug: Error in testGrowthMigration - ' . $e->getMessage());
            }
            return new WP_REST_Response(['success' => false, 'message' => 'Error running migration test: ' . $e->getMessage()], 500);
        }
    }

    /**
     * @return array{status: string, message: string}
     */
    private function runMigrationTableTest(string $migrationsTable): array
    {
        global $wpdb;
        $exists = $wpdb->get_var("SHOW TABLES LIKE '{$migrationsTable}'") === $migrationsTable;
        return [
            'status' => $exists ? 'pass' : 'fail',
            'message' => $exists ? 'Migrations table exists' : 'Migrations table missing',
        ];
    }

    /**
     * @return array{status: string, message: string}
     */
    private function runMigrationExecutedTest(string $migrationsTable): array
    {
        global $wpdb;
        $executed = (bool) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$migrationsTable} WHERE migration = %s AND status = 'completed'",
            self::MIGRATION_NAME
        ));
        return [
            'status' => $executed ? 'pass' : 'pending',
            'message' => $executed ? 'Migration executed' : 'Migration not executed yet',
        ];
    }

    /**
     * @return array{status: string, message: string}
     */
    private function runEventsTableTest(string $table): array
    {
        global $wpdb;
        $exists = $wpdb->get_var("SHOW TABLES LIKE '{$table}'") === $table;
        return [
            'status' => $exists ? 'pass' : 'fail',
            'message' => $exists ? 'Events table exists' : 'Events table missing',
        ];
    }

    /**
     * @return array{status: string, message: string, details: array|null}
     */
    private function runColumnExistsTest(string $table, bool $eventsExists): array
    {
        global $wpdb;
        $columnExists = false;
        $columnInfo = null;
        if ($eventsExists) {
            $columnExists = (bool) $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = %s AND column_name = 'points_per_event'",
                $table
            ));
            if ($columnExists) {
                $columnInfo = $wpdb->get_row($wpdb->prepare(
                    "SELECT COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = %s AND column_name = 'points_per_event'",
                    $table
                ), ARRAY_A);
            }
        }
        return [
            'status' => $columnExists ? 'pass' : 'fail',
            'message' => $columnExists ? 'Column exists' : 'Column missing',
            'details' => $columnInfo,
        ];
    }

    /**
     * @return array{status: string, total_events?: int, sample_events?: array}
     */
    private function runEventsDataTest(string $table, bool $eventsExists): array
    {
        global $wpdb;
        if (!$eventsExists) {
            return ['status' => 'fail'];
        }
        $events = $wpdb->get_results("SELECT id, event_type, event_name, points_per_event, tracking_config, total_occurrences FROM {$table} LIMIT 10", ARRAY_A);
        $totalEvents = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$table}");
        $eventsData = [];
        foreach ($events as $event) {
            $points = isset($event['points_per_event']) ? (int) $event['points_per_event'] : null;
            $configPoints = null;
            if (!empty($event['tracking_config'])) {
                $config = json_decode($event['tracking_config'], true);
                $config = is_string($config) ? json_decode($config, true) : $config;
                $configPoints = (is_array($config) && isset($config['points_override'])) ? (int) $config['points_override'] : null;
            }
            $eventsData[] = [
                'id' => $event['id'],
                'event_name' => $event['event_name'],
                'event_type' => $event['event_type'],
                'points_per_event' => $points,
                'config_points_override' => $configPoints,
                'total_occurrences' => (int) ($event['total_occurrences'] ?? 0),
                'valid' => $points !== null && $points >= 1 && $points <= 1000,
            ];
        }
        return ['status' => 'pass', 'total_events' => $totalEvents, 'sample_events' => $eventsData];
    }

    /**
     * @return array{status: string, message: string, test_points?: int, expected_points?: int}
     */
    private function runCalculationFunctionTest(): array
    {
        try {
            require_once FLEEKDASH_PLUGIN_DIR . 'includes/Services/SiteGrowthMeter/GrowthHelpers.php';
            $testEvent = ['id' => 999, 'event_type' => 'test', 'points_per_event' => 25, 'total_occurrences' => 10];
            $points = \FleekDash\Services\SiteGrowthMeter\GrowthHelpers::computeEventTotalPoints($testEvent, 10);
            $expected = 250;
            return [
                'status' => $points === $expected ? 'pass' : 'fail',
                'message' => $points === $expected ? 'Calculation correct' : "Calculation incorrect (got {$points}, expected {$expected})",
                'test_points' => $points,
                'expected_points' => $expected,
            ];
        } catch (\Exception $e) {
            return ['status' => 'fail', 'message' => 'Error testing calculation: ' . $e->getMessage()];
        }
    }

    /**
     * @param array<string, array{status?: string}> $tests
     * @return array{total_tests: int, passed: int, failed: int, pending: int, all_passed: bool}
     */
    private function buildMigrationTestSummary(array $tests): array
    {
        $passed = $failed = $pending = 0;
        foreach ($tests as $test) {
            if (isset($test['status'])) {
                if ($test['status'] === 'pass') {
                    $passed++;
                } elseif ($test['status'] === 'fail') {
                    $failed++;
                } elseif ($test['status'] === 'pending') {
                    $pending++;
                }
            }
        }
        return [
            'total_tests' => count($tests),
            'passed' => $passed,
            'failed' => $failed,
            'pending' => $pending,
            'all_passed' => $failed === 0 && $pending === 0,
        ];
    }
}
