<?php

/**
 * Site Growth Meter Service - Refactored
 *
 * Main orchestrator for Site Growth Meter functionality
 * Delegates to specialized services for clean architecture
 *
 * @package FleekDash\Services
 */

namespace FleekDash\Services;

// 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\SiteGrowthTemplate;
use FleekDash\Services\SiteGrowthAchievementsEngine;
use FleekDash\Services\SiteGrowthMeter\EventTracker;
use FleekDash\Services\SiteGrowthMeter\GrowthCalculator;
use FleekDash\Services\SiteGrowthMeter\GoalsManager;
use FleekDash\Services\SiteGrowthMeter\ReportGenerator;
use FleekDash\Services\SiteGrowthMeter\GrowthHelpers;
use FleekDash\Services\SiteGrowthMeter\SnapshotScheduler;

class SiteGrowthMeterService
{
    private $eventTracker;
    private $calculator;
    private $reportGenerator;

    public function __construct()
    {
        $this->eventTracker = new EventTracker();
        $this->calculator = new GrowthCalculator();
        $this->reportGenerator = new ReportGenerator();

        // Initialize snapshot scheduler
        SnapshotScheduler::init();
    }

    /**
     * Initialize Site Growth Meter with template
     */
    public function initializeSiteGrowthMeter($template_id = null)
    {
        $results = [
            'success' => false,
            'events_created' => 0,
            'goals_created' => 0,
            'template_applied' => null,
            'message' => ''
        ];

        try {
            // NEW: Create default core events if no events exist yet
            // This ensures the system works "out of the box" without manual configuration
            $existing_events_count = count(SiteGrowthEvent::getAll());

            if ($existing_events_count === 0) {
                // No events exist, create core defaults
                $created = $this->createDefaultCoreEvents();
                $results['events_created'] = count($created);
                fleekdash_log_info("Growth System: Created {$results['events_created']} default core events");
            } else {
                fleekdash_log_debug("Growth System: {$existing_events_count} events already exist, skipping default creation");
            }

            if ($template_id) {
                $template = SiteGrowthTemplate::find($template_id);
                if (!$template) {
                    throw new \Exception('Template not found');
                }

                // Note: SiteGrowthTemplate needs applyToSite() method implementation
                // For now, skip template application (legacy code)
                $results['template_applied'] = $template['template_name'] ?? 'Unknown';
                $results['message'] = 'Template application pending refactoring';
            }

            $this->eventTracker->setupAutomaticTracking();

            $metrics = $this->calculator->calculateInitialMetrics();
            $this->updateEventsWithCurrentValues($metrics);

            // NEW: Sync event occurrences with real WordPress counts
            // This ensures events show correct totals based on existing content
            $this->syncCoreEventOccurrences();

            // NEW: Create initial snapshots for current and previous month
            // This sets up the baseline for growth tracking and goal calculation
            $this->createInitialSnapshots();

            $achievements_results = SiteGrowthAchievementsEngine::bootstrap();
            $results['achievements'] = $achievements_results;

            // Schedule monthly snapshot cron job
            SnapshotScheduler::schedule();

            $results['success'] = true;
            $results['message'] = 'Site Growth Meter initialized successfully';

        } catch (\Exception $e) {
            $results['message'] = 'Error: ' . $e->getMessage();
            fleekdash_log_error('FleekDash Site Growth: ' . $e->getMessage());
        }

        return $results;
    }

    /**
     * Create default core events
     *
     * Creates essential events that work for most WordPress sites:
     * - new_post: Tracks published posts (10 points)
     * - new_user: Tracks user registrations (20 points)
     * - new_comment: Tracks approved comments (5 points)
     *
     * This method is idempotent - safe to call multiple times.
     *
     * @return array Created events
     */
    private function createDefaultCoreEvents()
    {
        $core_events = [
            [
                'event_type' => 'new_post',
                'event_name' => 'New Post Published',
                'description' => 'Automatically tracks when new posts are published',
                'tracking_method' => 'automatic',
                'points_per_event' => 10,
                'is_active' => 1,
                'total_occurrences' => 0,
            ],
            [
                'event_type' => 'new_user',
                'event_name' => 'New User Registration',
                'description' => 'Automatically tracks when new users register',
                'tracking_method' => 'automatic',
                'points_per_event' => 20,
                'is_active' => 1,
                'total_occurrences' => 0,
            ],
            [
                'event_type' => 'new_comment',
                'event_name' => 'New Comment',
                'description' => 'Automatically tracks when new comments are posted',
                'tracking_method' => 'automatic',
                'points_per_event' => 5,
                'is_active' => 1,
                'total_occurrences' => 0,
            ],
        ];

        $created_events = [];

        foreach ($core_events as $event_data) {
            try {
                // Double-check: Skip if event type already exists (idempotent)
                $existing = SiteGrowthEvent::getByType($event_data['event_type']);
                if ($existing) {
                    fleekdash_log_debug("Growth System: Event '{$event_data['event_type']}' already exists, skipping");
                    continue;
                }

                $event_id = SiteGrowthEvent::create($event_data);

                if ($event_id) {
                    $created_events[] = SiteGrowthEvent::find($event_id);
                    fleekdash_log_info("Growth System: Created core event '{$event_data['event_type']}' (ID: {$event_id})");
                }
            } catch (\Exception $e) {
                fleekdash_log_error("Growth System: Failed to create event '{$event_data['event_type']}': " . $e->getMessage());
                // Continue with other events even if one fails
            }
        }

        return $created_events;
    }

    /**
     * Register tracking hooks
     *
     * Only syncs if tables exist (prevents activation errors)
     */
    public function registerTrackingHooks(): void
    {
        $this->eventTracker->setupAutomaticTracking();

        // Only sync if tables exist (prevents "Table doesn't exist" error during activation)
        if (SiteGrowthEvent::tableExists()) {
            $this->syncCoreEventOccurrences();
        } else {
            fleekdash_log_debug('SiteGrowthMeterService: Skipping sync - tables not yet created (activation in progress)');
        }
    }

    /**
     * Ensure baseline events match actual site metrics (self-healing)
     *
     * Checks table existence before any operation
     */
    private function syncCoreEventOccurrences(): void
    {
        try {
            // Double-check table exists (defensive programming)
            if (!SiteGrowthEvent::tableExists()) {
                fleekdash_log_debug('SiteGrowthMeterService::syncCoreEventOccurrences - Table does not exist yet');
                return;
            }

            $metrics = $this->calculator->calculateInitialMetrics();
            $syncMap = [
                'new_post' => (int) ($metrics['total_posts'] ?? 0),
                'new_user' => (int) ($metrics['total_users'] ?? 0),
                'new_comment' => (int) ($metrics['total_comments'] ?? 0),
            ];

            foreach ($syncMap as $eventType => $count) {
                $event = SiteGrowthEvent::getByType($eventType);
                if ($event && (int) ($event['total_occurrences'] ?? 0) !== $count) {
                    SiteGrowthEvent::update($event['id'], [
                        'total_occurrences' => $count,
                        'last_occurrence_at' => \current_time('mysql'),
                    ]);
                }
            }
        } catch (\Throwable $e) {
            if (function_exists('fleekdash_log_error')) {
                fleekdash_log_error('Site Growth Meter sync error: ' . $e->getMessage());
            }
        }
    }

    /**
     * Create initial snapshots for growth tracking
     *
     * Creates snapshots for current and previous month to establish baseline.
     * This enables proper goal calculation and growth tracking from day 1.
     *
     * Logic:
     * 1. Calculate total accumulated points (from existing content)
     * 2. Create current month snapshot with these points
     * 3. Create previous month snapshot with 70% of current (establishes growth goal)
     * 4. This makes goal = current * 1.2 / 0.7 ≈ current * 1.7 (challenging but achievable)
     *
     * Checks table existence before any operation
     */
    private function createInitialSnapshots(): void
    {
        try {
            global $wpdb;
            $snapshots_table = $wpdb->prefix . 'fleekdash_site_growth_monthly_snapshots';

            // Check if snapshots table exists before any query
            // Prevents "Table doesn't exist" error during plugin activation
            $table_exists = $wpdb->get_var($wpdb->prepare(
                "SHOW TABLES LIKE %s",
                $snapshots_table
            ));

            if (!$table_exists) {
                fleekdash_log_debug('Growth System: Snapshots table does not exist yet (activation in progress)');
                return;
            }

            // Also check if events table exists (needed for point calculation)
            if (!SiteGrowthEvent::tableExists()) {
                fleekdash_log_debug('Growth System: Events table does not exist yet (activation in progress)');
                return;
            }

            $current_month = date('Y-m');
            $previous_month = date('Y-m', strtotime('-1 month'));

            // Check if snapshots already exist (idempotent)
            $current_exists = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$snapshots_table} WHERE month_year = %s",
                $current_month
            ));

            $previous_exists = $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$snapshots_table} WHERE month_year = %s",
                $previous_month
            ));

            if ($current_exists && $previous_exists) {
                fleekdash_log_debug('Growth System: Snapshots already exist, skipping creation');
                return;
            }

            // Calculate current total accumulated points
            $total_accumulated = $this->calculator->calculateTotalAccumulatedPoints();

            // Create current month snapshot
            if (!$current_exists) {
                $this->calculator->createMonthlySnapshot($current_month);
                fleekdash_log_info("Growth System: Created current month snapshot ({$current_month}): {$total_accumulated} pts");
            }

            // Create previous month snapshot (baseline for goal calculation)
            // IMPROVED: Always create baseline, even for new sites (0 points)
            // This ensures consistent growth calculation from 0 → goal
            if (!$previous_exists) {
                // Set previous month to 70% of current to create achievable growth goal
                // For new sites (0 points), baseline will be 0, allowing growth tracking
                // Goal will be: current * 1.2 = (prev * 1.2) where prev = current * 0.7
                // This creates a goal that's ~30% higher than current baseline
                $previous_baseline = $total_accumulated > 0
                    ? (int) round($total_accumulated * 0.7)
                    : 0; // Baseline zero for new sites

                $wpdb->insert(
                    $snapshots_table,
                    [
                        'month_year' => $previous_month,
                        'total_points' => $previous_baseline,
                        'total_posts' => 0,
                        'total_users' => 0,
                        'total_comments' => 0,
                        'total_sales' => 0,
                        'total_orders' => 0,
                        'total_traffic' => 0,
                        'goals_achieved' => 0,
                        'growth_percentage' => null,
                        'created_at' => \current_time('mysql'),
                        'updated_at' => \current_time('mysql'),
                    ]
                );

                if ($previous_baseline > 0) {
                    fleekdash_log_info("Growth System: Created previous month snapshot ({$previous_month}): {$previous_baseline} pts (baseline for goal)");
                } else {
                    fleekdash_log_info("Growth System: Created previous month snapshot ({$previous_month}): 0 pts (baseline for new site)");
                }
            }

        } catch (\Throwable $e) {
            fleekdash_log_error('Growth System: Failed to create initial snapshots: ' . $e->getMessage());
        }
    }

    /**
     * Track new post - Delegate to EventTracker
     */
    public function trackNewPost($post_id, $post)
    {
        $this->eventTracker->trackNewPost($post_id, $post);
    }

    /**
     * Track new comment - Delegate to EventTracker
     */
    public function trackNewComment($comment_id, $commentdata)
    {
        $this->eventTracker->trackNewComment($comment_id, $commentdata);
    }

    /**
     * Handle comment status transition - Delegate to EventTracker
     */
    public function onCommentStatusTransition($new_status, $old_status, $comment)
    {
        $this->eventTracker->onCommentStatusTransition($new_status, $old_status, $comment);
    }

    /**
     * Track new user - Delegate to EventTracker
     */
    public function trackNewUser($user_id)
    {
        $this->eventTracker->trackNewUser($user_id);
    }

    /**
     * Track new order - Delegate to EventTracker
     */
    public function trackNewOrder($order_id)
    {
        $this->eventTracker->trackNewOrder($order_id);
    }

    /**
     * Track new product - Delegate to EventTracker
     */
    public function trackNewProduct($product_id)
    {
        $this->eventTracker->trackNewProduct($product_id);
    }

    /**
     * Track product review - Delegate to EventTracker
     */
    public function trackProductReview($comment_id, $comment_approved, $commentdata)
    {
        $this->eventTracker->trackProductReview($comment_id, $comment_approved, $commentdata);
    }

    /**
     * Track manual event - Delegate to EventTracker
     */
    public function trackManualEvent($event_type, $data = [])
    {
        $this->eventTracker->trackManualEvent($event_type, $data);
    }

    /**
     * Get dashboard data - Delegate to ReportGenerator
     */
    public function getDashboardData($period = 'monthly')
    {
        return $this->reportGenerator->getDashboardData($period);
    }

    /**
     * Get analytics data - Delegate to ReportGenerator
     */
    public function getAnalyticsData($period = 'monthly', $days = 30)
    {
        return $this->reportGenerator->getAnalyticsData($period, $days);
    }

    /**
     * Get event points map
     *
     * Now uses points_per_event column directly (Bug #1 & #2)
     */
    public function getEventPointsMap()
    {
        $events = SiteGrowthEvent::getAll();
        $map = [];

        foreach ($events as $event) {
            $map[$event['event_type']] = [
                'event_name' => $event['event_name'],
                'points_per_occurrence' => $event['points_per_event'] ?? 10, // Use new column
                'total_occurrences' => $event['total_occurrences'] ?? 0,
                'total_points' => GrowthHelpers::computeEventTotalPoints(
                    $event, // Pass full event array
                    $event['total_occurrences'] ?? 0
                )
            ];
        }

        return $map;
    }

    /**
     * Get event types
     */
    public function getEventTypes(): array
    {
        return SiteGrowthEvent::getAll();
    }

    /**
     * Save points map
     */
    public function savePointsMap(array $map)
    {
        foreach ($map as $event_type => $config) {
            if (isset($config['points_per_occurrence'])) {
                $this->saveEventTypePoints($event_type, $config['points_per_occurrence']);
            }
        }
    }

    /**
     * Save event type points
     *
     * Now saves to points_per_event column (Bug #2)
     */
    public function saveEventTypePoints($event_type, $points)
    {
        $event = SiteGrowthEvent::getByType($event_type);
        if ($event) {
            // Validate points range
            $points = max(1, min(1000, (int) $points));

            SiteGrowthEvent::update($event['id'], [
                'points_per_event' => $points // Use new column name
            ]);
        }
    }

    /**
     * Get active events with computed fields
     *
     * Now uses points_per_event column directly (Bug #1 & #2)
     */
    public function getActiveEventsWithComputedFields()
    {
        $events = SiteGrowthEvent::getActive();

        foreach ($events as &$event) {
            // Pass full event array so computeEventTotalPoints can use points_per_event column
            $event['total_points'] = GrowthHelpers::computeEventTotalPoints(
                $event, // Pass full event array
                $event['total_occurrences'] ?? 0
            );
        }

        return $events;
    }

    /**
     * Get points breakdown map
     */
    public function getPointsBreakdownMap()
    {
        return $this->getEventPointsMap();
    }

    /**
     * Update monthly snapshot
     *
     * Now uses calculateTotalAccumulatedPoints() instead of calculateCurrentMonthPoints()
     * Snapshots should store the total accumulated points at that moment in time,
     * not just the points earned in the current month.
     */
    public function updateMonthlySnapshot()
    {
        $total_points = $this->calculator->calculateTotalAccumulatedPoints();
        $this->saveMonthlySnapshot($total_points);
    }

    /**
     * Create custom event
     *
     * Now saves points_per_event directly in column (Bug #2)
     * Still maintains points_override in tracking_config for backward compatibility
     */
    public function createCustomEvent($event_type, $event_name = null, $tracking_config = [], $points_override = null, $description = null, $tracking_method = 'manual', $is_active = true)
    {
        $normalized_type = is_string($event_type) ? \sanitize_key($event_type) : '';

        if ($normalized_type === '') {
            throw new \InvalidArgumentException('Event type is required.');
        }

        // Normalize tracking config
        if (is_string($tracking_config)) {
            $decoded = json_decode($tracking_config, true);
            $tracking_config = is_array($decoded) ? $decoded : [];
        } elseif (!is_array($tracking_config)) {
            $tracking_config = [];
        }

        // Extract points_per_event from points_override parameter or tracking_config
        $points_per_event = 10; // Default
        if ($points_override !== null && is_numeric($points_override)) {
            $points_per_event = max(1, (int) $points_override);
            $tracking_config['points_override'] = $points_per_event; // Keep for backward compatibility
        } elseif (isset($tracking_config['points_override']) && is_numeric($tracking_config['points_override'])) {
            $points_per_event = max(1, (int) $tracking_config['points_override']);
        } elseif (isset($tracking_config['points']) && is_numeric($tracking_config['points'])) {
            $points_per_event = max(1, (int) $tracking_config['points']);
        }

        $normalized_name = null;
        if ($event_name !== null) {
            $trimmed = trim((string) $event_name);
            if ($trimmed !== '') {
                $normalized_name = \sanitize_text_field($trimmed);
            }
        }

        if (!$normalized_name) {
            $normalized_name = GrowthHelpers::buildEventName($normalized_type, $tracking_config);
        }

        $normalized_description = $description !== null && $description !== ''
            ? sanitize_textarea_field((string) $description)
            : null;

        $normalized_tracking_method = is_string($tracking_method) ? \sanitize_key($tracking_method) : 'manual';
        if ($normalized_tracking_method === '') {
            $normalized_tracking_method = 'manual';
        }

        return SiteGrowthEvent::create([
            'event_type' => $normalized_type,
            'event_name' => $normalized_name,
            'description' => $normalized_description,
            'tracking_method' => $normalized_tracking_method,
            'tracking_config' => !empty($tracking_config) ? \wp_json_encode($tracking_config) : null,
            'points_per_event' => $points_per_event, // Save directly in column
            'is_active' => $is_active ? 1 : 0,
            'total_occurrences' => 0
        ]);
    }

    /**
     * Update events with current values
     */
    private function updateEventsWithCurrentValues($metrics)
    {
        // Implementation maintained for backward compatibility
        // Future: Can be extracted to MetricsCollector service
    }

    /**
     * Save monthly snapshot
     */
    private function saveMonthlySnapshot($total_points)
    {
        global $wpdb;
        $snapshots_table = $wpdb->prefix . 'fleekdash_site_growth_monthly_snapshots';
        $month_year = date('Y-m');

        $existing = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$snapshots_table} WHERE month_year = %s",
            $month_year
        ));

        if ($existing) {
            $wpdb->update(
                $snapshots_table,
                ['total_points' => $total_points, 'updated_at' => \current_time('mysql')],
                ['month_year' => $month_year]
            );
        } else {
            $wpdb->insert($snapshots_table, [
                'month_year' => $month_year,
                'total_points' => $total_points,
                'created_at' => \current_time('mysql'),
                'updated_at' => \current_time('mysql')
            ]);
        }
    }

    /**
     * Recalculate all points for all events
     *
     * This method:
     * 1. Syncs core event occurrences with real WordPress data
     * 2. Recalculates total accumulated points
     * 3. Updates current month snapshot
     * 4. Returns summary of changes
     *
     * @return array Results with events updated, total points, and status
     */
    public function recalculatePoints(): array
    {
        try {
            $results = [
                'success' => false,
                'events_updated' => 0,
                'total_points_before' => 0,
                'total_points_after' => 0,
                'snapshot_updated' => false,
                'message' => ''
            ];

            // Get total points before recalculation
            $results['total_points_before'] = $this->calculator->calculateTotalAccumulatedPoints();

            // Calculate current metrics from WordPress
            $metrics = $this->calculator->calculateInitialMetrics();

            // Sync core event occurrences with real WordPress counts
            $syncMap = [
                'new_post' => (int) ($metrics['total_posts'] ?? 0),
                'new_user' => (int) ($metrics['total_users'] ?? 0),
                'new_comment' => (int) ($metrics['total_comments'] ?? 0),
            ];

            foreach ($syncMap as $eventType => $count) {
                $event = SiteGrowthEvent::getByType($eventType);
                if ($event) {
                    $old_count = (int) ($event['total_occurrences'] ?? 0);
                    if ($old_count !== $count) {
                        SiteGrowthEvent::update($event['id'], [
                            'total_occurrences' => $count,
                            'last_occurrence_at' => \current_time('mysql'),
                        ]);
                        $results['events_updated']++;
                        fleekdash_log_debug("Recalculated {$eventType}: {$old_count} → {$count}");
                    }
                }
            }

            // Recalculate total points after sync
            $results['total_points_after'] = $this->calculator->calculateTotalAccumulatedPoints();

            // Update current month snapshot
            $snapshot_created = $this->calculator->createMonthlySnapshot();
            $results['snapshot_updated'] = $snapshot_created;

            $results['success'] = true;
            $results['message'] = sprintf(
                'Points recalculated successfully. %d events updated. Total points: %d → %d',
                $results['events_updated'],
                $results['total_points_before'],
                $results['total_points_after']
            );

            fleekdash_log_info('Growth System: Points recalculated - ' . $results['message']);

            return $results;

        } catch (\Exception $e) {
            fleekdash_log_error('Growth System: Error recalculating points: ' . $e->getMessage());
            return [
                'success' => false,
                'message' => 'Error recalculating points: ' . $e->getMessage()
            ];
        }
    }
}
