<?php

namespace FleekDash\Services\SiteGrowthMeter;

// Load debug helpers
if (!function_exists('fleekdash_log_error')) {
    require_once FLEEKDASH_PLUGIN_DIR . 'includes/Core/debug-helpers.php';
}

use FleekDash\Models\SiteGrowthEvent;
use FleekDash\Models\SiteGrowthAchievement;

/**
 * Report Generator
 *
 * Generates dashboard data and reports
 *
 * @package FleekDash\Services\SiteGrowthMeter
 */
class ReportGenerator
{
    private $calculator;

    public function __construct()
    {
        $this->calculator = new GrowthCalculator();
    }

    /**
     * Check if snapshots table exists
     *
     * Prevents database errors during plugin activation
     *
     * @return bool
     */
    private function snapshotsTableExists(): bool
    {
        global $wpdb;
        $snapshots_table = $wpdb->prefix . 'fleekdash_site_growth_monthly_snapshots';

        $suppress_errors = $wpdb->suppress_errors(true);
        $show_errors = $wpdb->show_errors;
        $wpdb->show_errors = false;

        try {
            $result = $wpdb->get_var($wpdb->prepare(
                "SHOW TABLES LIKE %s",
                $snapshots_table
            ));
            return $result === $snapshots_table;
        } finally {
            $wpdb->suppress_errors($suppress_errors);
            $wpdb->show_errors = $show_errors;
        }
    }

    /**
     * Get dashboard data
     *
     * @param string $period Period type
     * @return array Dashboard data
     */
    public function getDashboardData($period = 'monthly')
    {
        try {
            return [
                'summary' => $this->getDashboardSummary(),
                'growth' => $this->calculator->calculateMonthOverMonthGrowth(),
                'record_challenge' => $this->getMonthlyRecordChallenge(),
                'recent_achievements' => $this->getRecentAchievements(),
                'active_events' => $this->getActiveEvents(),
                'insights' => $this->generateInsights()
            ];
        } catch (\Exception $e) {
            fleekdash_log_error('FleekDash Site Growth: Dashboard error: ' . $e->getMessage());
            return [];
        }
    }

    /**
     * Get dashboard summary
     *
     * Added kpi_goal_points field (Bug #7)
     * Uses best record + 20% as goal, or 1000 as default
     *
     * @return array Summary data
     */
    private function getDashboardSummary()
    {
        $current_points = $this->calculator->calculateCurrentMonthPoints();
        // Goals system removed - using Achievements system instead
        $goal_points = 0;
        $total_points = $current_points + $goal_points;

        $events = SiteGrowthEvent::getActive();
        $active_events_count = count($events);

        $total_occurrences = array_reduce($events, function ($carry, $event) {
            return $carry + ($event['total_occurrences'] ?? 0);
        }, 0);

        // Calculate KPI goal points (Bug #7)
        // Use best record + 20% as goal, or intelligent default for fresh installs
        $record_challenge = $this->getMonthlyRecordChallenge();
        $best_record = $record_challenge['record_points'] ?? 0;

        if ($best_record > 0) {
            // Goal is best record + 20% (challenging but achievable)
            $kpi_goal_points = (int) round($best_record * 1.2);
        } else {
            // IMPROVED: For fresh installs, use intelligent goal calculation
            // - Sites with content: current * 1.3 (30% growth target)
            // - New sites (0 points): 500 (smaller, more achievable goal)
            // This creates an achievable but challenging goal for new sites
            if ($current_points > 0) {
                $kpi_goal_points = (int) round($current_points * 1.3);
            } else {
                // IMPROVED: Lower default goal (500 instead of 1000) for new sites
                // More achievable and encourages initial engagement
                $kpi_goal_points = 500; // Default for sites with no content yet
            }
        }

        return [
            'total_points' => $total_points,
            'current_month_points' => $current_points,
            'goal_bonus_points' => $goal_points,
            'kpi_goal_points' => $kpi_goal_points, // Added (Bug #7)
            'active_events_count' => $active_events_count,
            'total_event_occurrences' => $total_occurrences,
            'period' => date('F Y')
        ];
    }

    /**
     * Get monthly record challenge
     *
     * Now includes breakdown data (Bug #8)
     * Added table existence check to prevent activation errors
     *
     * @return array Record challenge data
     */
    private function getMonthlyRecordChallenge()
    {
        global $wpdb;
        $snapshots_table = $wpdb->prefix . 'fleekdash_site_growth_monthly_snapshots';

        $current_month = date('Y-m');
        $current_points = $this->calculator->calculateCurrentMonthPoints();

        // Check if table exists before querying
        if (!$this->snapshotsTableExists()) {
            fleekdash_log_debug('Growth System: Snapshots table does not exist yet (activation in progress)');
            return [
                'current_points' => $current_points,
                'record_points' => 0,
                'record_month' => null,
                'points_to_record' => 0,
                'is_new_record' => false,
                'breakdown' => []
            ];
        }

        $suppress_errors = $wpdb->suppress_errors(true);
        $show_errors = $wpdb->show_errors;
        $wpdb->show_errors = false;

        try {
            // Calculate points earned in each month (not total accumulated)
            // Get all snapshots ordered by month to calculate monthly differences
            $all_snapshots = $wpdb->get_results("
                SELECT month_year, total_points
                FROM {$snapshots_table}
                ORDER BY month_year ASC
            ", ARRAY_A);

            // Guard against empty snapshot sets
            if (empty($all_snapshots)) {
                $record_points = 0;
                $record_month = null;
                $previous_total = 0;
            } else {
                $record_points = 0;
                $record_month = null;
                $previous_total = 0;

                // Calculate points earned in each month and find the record
                foreach ($all_snapshots as $snapshot) {
                    $month_total = (int) $snapshot['total_points'];
                    $month_points = max(0, $month_total - $previous_total);

                    if ($month_points > $record_points) {
                        $record_points = $month_points;
                        $record_month = $snapshot['month_year'];
                    }

                    $previous_total = $month_total;
                }
            }
        } finally {
            $wpdb->suppress_errors($suppress_errors);
            $wpdb->show_errors = $show_errors;
        }

        // Now comparing points earned in current month vs points earned in best month
        // Ensure numeric comparison safety
        $current_points = (int) $current_points;
        $record_points = (int) $record_points;
        $points_to_record = max(0, $record_points - $current_points);
        $is_record = $current_points > $record_points;

        // Calculate breakdown for best record (Bug #8)
        $breakdown = [];
        if ($record_points > 0) {
            $breakdown = $this->calculateRecordBreakdown($record_points, $record_month);
        }

        return [
            'current_points' => $current_points,
            'record_points' => $record_points,
            'record_month' => $record_month,
            'points_to_record' => $points_to_record,
            'is_new_record' => $is_record,
            'breakdown' => $breakdown // Added (Bug #8)
        ];
    }

    /**
     * Calculate breakdown for a record month
     *
     * Calculates breakdown from snapshot and current events (Bug #8)
     * Uses proportional distribution based on current event weights
     *
     * @param int $record_points Total points for the record month
     * @param string|null $record_month Month of the record (YYYY-MM)
     * @return array Breakdown items
     */
    private function calculateRecordBreakdown($record_points, $record_month = null)
    {
        $events = SiteGrowthEvent::getActive();

        if (empty($events) || $record_points <= 0) {
            return [];
        }

        // Calculate current total points to get proportions
        $current_total = 0;
        $event_points = [];

        foreach ($events as $event) {
            $points_per_event = isset($event['points_per_event']) ? (int) $event['points_per_event'] : 10;
            $occurrences = (int) ($event['total_occurrences'] ?? 0);
            $total = $points_per_event * $occurrences;

            $event_points[] = [
                'event_type' => $event['event_type'],
                'event_name' => $event['event_name'],
                'points_per_event' => $points_per_event,
                'current_total' => $total
            ];

            $current_total += $total;
        }

        // If no current points, distribute evenly
        if ($current_total <= 0) {
            $points_per_event_type = $record_points / count($events);
            return array_map(function ($event) use ($points_per_event_type) {
                return [
                    'event_type' => $event['event_type'],
                    'event_name' => $event['event_name'],
                    'points_per_event' => $event['points_per_event'],
                    'points' => (int) round($points_per_event_type),
                    'occurrences' => $event['points_per_event'] > 0
                        ? (int) round($points_per_event_type / $event['points_per_event'])
                        : 0
                ];
            }, $event_points);
        }

        // Calculate proportional breakdown based on current event weights
        $breakdown = [];
        foreach ($event_points as $event) {
            $proportion = $event['current_total'] / $current_total;
            $points = (int) round($record_points * $proportion);
            $occurrences = $event['points_per_event'] > 0
                ? (int) round($points / $event['points_per_event'])
                : 0;

            if ($points > 0) {
                $breakdown[] = [
                    'event_type' => $event['event_type'],
                    'event_name' => $event['event_name'],
                    'points_per_event' => $event['points_per_event'],
                    'points' => $points,
                    'occurrences' => $occurrences
                ];
            }
        }

        // Sort by points descending
        usort($breakdown, function ($a, $b) {
            return $b['points'] - $a['points'];
        });

        return $breakdown;
    }

    /**
     * Get recent achievements
     *
     * Added table existence check to prevent activation errors
     *
     * @param int $days Number of days
     * @return array Recent achievements
     */
    private function getRecentAchievements($days = 7)
    {
        // Check if table exists before querying
        if (!SiteGrowthAchievement::tableExists()) {
            fleekdash_log_debug('Growth System: Achievements table does not exist yet (activation in progress)');
            return [];
        }

        global $wpdb;
        $achievements_table = $wpdb->prefix . 'fleekdash_site_growth_achievements';

        $cutoff_date = date('Y-m-d H:i:s', strtotime("-{$days} days"));

        $suppress_errors = $wpdb->suppress_errors(true);
        $show_errors = $wpdb->show_errors;
        $wpdb->show_errors = false;

        try {
            $achievements = $wpdb->get_results($wpdb->prepare("
                SELECT * FROM {$achievements_table}
                WHERE achieved_at >= %s
                ORDER BY achieved_at DESC
                LIMIT 10
            ", $cutoff_date), ARRAY_A);
        } finally {
            $wpdb->suppress_errors($suppress_errors);
            $wpdb->show_errors = $show_errors;
        }

        return $achievements ?: [];
    }

    /**
     * Get active events
     *
     * @return array Active events
     */
    private function getActiveEvents()
    {
        return SiteGrowthEvent::getActive();
    }

    /**
     * Generate insights
     *
     * @return array Insights
     */
    private function generateInsights()
    {
        $events = SiteGrowthEvent::getActive();
        $insights = [];

        if (count($events) > 0) {
            $top_event = $events[0];
            $insights[] = [
                'type' => 'top_event',
                'message' => "Your top event is '{$top_event['event_name']}' with {$top_event['total_occurrences']} occurrences"
            ];
        }

        return $insights;
    }

    /**
     * Get analytics data
     *
     * @param string $period Period type
     * @param int $days Number of days
     * @return array Analytics data
     */
    public function getAnalyticsData($period = 'monthly', $days = 30)
    {
        return [
            'metrics' => $this->calculator->calculateInitialMetrics(),
            'summary' => $this->getDashboardSummary(),
            'period' => $period
        ];
    }
}
