<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\AcademyContentMetricDaily;
use App\Models\AcademyEvent;
use App\Models\AcademyLike;
use App\Models\AcademySave;
use App\Models\AcademySearchLog;
use App\Models\AcademyUserProgress;
use App\Support\AcademyAnalytics\AcademyAnalyticsEventType;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Schema;

final class AcademyAnalyticsHealthCommand extends Command
{
    protected $signature = 'academy:analytics-health {--json : Output machine-readable JSON}';

    protected $description = 'Inspect Academy analytics collection health, rollup freshness, and privacy safeguards';

    private const RETENTION_DAYS = 180;

    public function handle(): int
    {
        $report = $this->buildReport();

        if ((bool) $this->option('json')) {
            $this->line(json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) ?: '{}');

            return self::SUCCESS;
        }

        $this->line('Academy Analytics Health Check');
        $this->line('==============================');
        $this->newLine();
        $this->line(sprintf('Events last 24h: %d', $report['events_last_24h']));
        $this->line(sprintf('Events last 7d: %d', $report['events_last_7d']));
        $this->line(sprintf('Latest event: %s', $report['latest_event_at'] ?? 'none'));
        $this->line(sprintf('Latest rollup date: %s', $report['latest_rollup_date'] ?? 'none'));
        $this->line(sprintf('Search logs: %d', $report['search_logs']));
        $this->line(sprintf('Search clicks: %d', $report['search_clicks']));
        $this->line(sprintf('Likes: %d', $report['likes']));
        $this->line(sprintf('Saves: %d', $report['saves']));
        $this->line(sprintf('Progress records: %d', $report['progress_records']));
        $this->line(sprintf('Prompt copies: %d', $report['prompt_copies']));
        $this->line(sprintf('Upgrade clicks: %d', $report['upgrade_clicks']));
        $this->line(sprintf('Human events: %d', $report['human_events']));
        $this->line(sprintf('Bot/admin events: %d', $report['bot_admin_events']));
        $this->line(sprintf('Recent daily metric rows: %d', $report['recent_daily_metric_rows']));
        $this->line(sprintf('Raw IP storage detected: %s', $report['raw_ip_storage_detected'] ? 'yes' : 'no'));
        $this->line(sprintf('Events older than retention: %d', $report['events_older_than_retention']));
        $this->newLine();

        foreach ($report['warnings'] as $warning) {
            $this->warn(sprintf('WARNING: %s', $warning));
        }

        $this->info(sprintf('Status: %s', $report['status']));

        return self::SUCCESS;
    }

    /**
     * @return array<string, mixed>
     */
    private function buildReport(): array
    {
        $now = now();
        $last24Hours = $now->copy()->subDay();
        $last7Days = $now->copy()->subDays(7);
        $retentionCutoff = $now->copy()->subDays(self::RETENTION_DAYS);
        $warnings = [];
        $rawIpStorageDetected = $this->rawIpStorageDetected();
        $eventsTableExists = Schema::hasTable('academy_events');
        $metricsTableExists = Schema::hasTable('academy_content_metrics_daily');
        $searchLogsTableExists = Schema::hasTable('academy_search_logs');
        $likesTableExists = Schema::hasTable('academy_likes');
        $savesTableExists = Schema::hasTable('academy_saves');
        $progressTableExists = Schema::hasTable('academy_user_progress');

        $latestEvent = $eventsTableExists ? AcademyEvent::query()->latest('occurred_at')->value('occurred_at') : null;
        $latestRollup = $metricsTableExists ? AcademyContentMetricDaily::query()->latest('date')->value('date') : null;
        $searchLogCount = $searchLogsTableExists ? AcademySearchLog::query()->count() : 0;
        $searchClickCount = $searchLogsTableExists ? AcademySearchLog::query()->whereNotNull('clicked_content_id')->count() : 0;
        $eventsOlderThanRetention = $eventsTableExists ? AcademyEvent::query()->where('occurred_at', '<', $retentionCutoff)->count() : 0;
        $recentDailyMetricRows = $metricsTableExists
            ? AcademyContentMetricDaily::query()->whereBetween('date', [$now->copy()->subDays(6)->toDateString(), $now->toDateString()])->count()
            : 0;

        $report = [
            'events_last_24h' => $eventsTableExists ? AcademyEvent::query()->where('occurred_at', '>=', $last24Hours)->count() : 0,
            'events_last_7d' => $eventsTableExists ? AcademyEvent::query()->where('occurred_at', '>=', $last7Days)->count() : 0,
            'latest_event_at' => $latestEvent ? Carbon::parse((string) $latestEvent)->toDateTimeString() : null,
            'latest_rollup_date' => $latestRollup ? Carbon::parse((string) $latestRollup)->toDateString() : null,
            'search_logs' => $searchLogCount,
            'search_clicks' => $searchClickCount,
            'likes' => $likesTableExists ? AcademyLike::query()->count() : 0,
            'saves' => $savesTableExists ? AcademySave::query()->count() : 0,
            'progress_records' => $progressTableExists ? AcademyUserProgress::query()->count() : 0,
            'prompt_copies' => $eventsTableExists ? AcademyEvent::query()->where('event_type', AcademyAnalyticsEventType::PROMPT_COPY)->count() : 0,
            'upgrade_clicks' => $eventsTableExists ? AcademyEvent::query()->where('event_type', AcademyAnalyticsEventType::UPGRADE_CLICK)->count() : 0,
            'human_events' => $eventsTableExists ? AcademyEvent::query()->where('is_bot', false)->where('is_admin', false)->where('is_suspicious', false)->count() : 0,
            'bot_admin_events' => $eventsTableExists ? AcademyEvent::query()->where(function ($query): void {
                $query->where('is_bot', true)->orWhere('is_admin', true)->orWhere('is_suspicious', true);
            })->count() : 0,
            'raw_ip_storage_detected' => $rawIpStorageDetected,
            'events_older_than_retention' => $eventsOlderThanRetention,
            'recent_daily_metric_rows' => $recentDailyMetricRows,
            'retention_days' => self::RETENTION_DAYS,
            'tables_present' => [
                'academy_events' => $eventsTableExists,
                'academy_content_metrics_daily' => $metricsTableExists,
                'academy_search_logs' => $searchLogsTableExists,
                'academy_likes' => $likesTableExists,
                'academy_saves' => $savesTableExists,
                'academy_user_progress' => $progressTableExists,
            ],
            'warnings' => [],
            'status' => 'OK',
        ];

        foreach ($report['tables_present'] as $table => $present) {
            if (! $present) {
                $warnings[] = sprintf('Analytics table %s is missing.', $table);
            }
        }

        if ($report['events_last_24h'] === 0) {
            $warnings[] = 'No events received in last 24 hours.';
        }

        if ($report['events_last_7d'] === 0) {
            $warnings[] = 'No events received in last 7 days.';
        }

        if ($report['latest_rollup_date'] === null) {
            $warnings[] = 'No rollup rows exist yet.';
        } elseif ($report['latest_rollup_date'] !== $now->toDateString()) {
            $warnings[] = 'Rollup has not run for today.';
        }

        if ($searchLogCount > 0 && $searchClickCount === 0) {
            $warnings[] = 'Search clicks are zero although search logs exist.';
        }

        if ($eventsOlderThanRetention > 0) {
            $warnings[] = 'Raw events older than configured retention period exist.';
        }

        if ($recentDailyMetricRows === 0) {
            $warnings[] = 'No daily metrics exist for recent days.';
        }

        if ($rawIpStorageDetected) {
            $warnings[] = 'Raw IP storage indicators were found in Academy analytics tables.';
        }

        $report['warnings'] = $warnings;
        $report['status'] = $warnings === [] ? 'OK' : 'WARNING';

        return $report;
    }

    private function rawIpStorageDetected(): bool
    {
        foreach (['academy_events', 'academy_search_logs', 'academy_content_metrics_daily', 'academy_likes', 'academy_saves', 'academy_user_progress'] as $table) {
            if (! Schema::hasTable($table)) {
                continue;
            }

            foreach (['ip', 'ip_address', 'visitor_ip', 'raw_ip', 'remote_addr'] as $column) {
                if (Schema::hasColumn($table, $column)) {
                    return true;
                }
            }
        }

        return false;
    }
}
