<?php

namespace FleekDash\Models;

defined('ABSPATH') || exit;

class SiteGrowthEvent extends BaseModel
{
    protected $table = 'fleekdash_site_growth_events';
    protected $primaryKey = 'id';

    /**
     * Fillable attributes
     */
    protected $fillable = [
        'event_type',
        'event_name',
        'description',
        'tracking_method',
        'tracking_config',
        'points_per_event',
        'is_active',
        'total_occurrences',
        'last_occurrence_at'
    ];

    /**
     * Attributes that should be cast to specific types
     */
    protected $casts = [
        'is_active' => 'boolean',
        'total_occurrences' => 'integer',
        'points_per_event' => 'integer',
        'tracking_config' => 'json'
    ];

    /**
     * Get all active events
     *
     * Returns empty array if table doesn't exist (during activation)
     */
    public static function getActive()
    {
        // Check if table exists before querying
        // Prevents "Table doesn't exist" error during plugin activation
        if (!static::tableExists()) {
            return [];
        }

        $instance = new static();

        // Suppress errors during query to prevent output during activation
        $suppress_errors = $instance->wpdb->suppress_errors(true);
        $show_errors = $instance->wpdb->show_errors;
        $instance->wpdb->show_errors = false;

        try {
            $results = $instance->wpdb->get_results(
                "SELECT * FROM {$instance->table}
                 WHERE is_active = 1
                 ORDER BY total_occurrences DESC",
                ARRAY_A
            );

            return $results ? array_map([$instance, 'castAttributes'], $results) : [];
        } finally {
            // Restore error handling
            $instance->wpdb->suppress_errors($suppress_errors);
            $instance->wpdb->show_errors = $show_errors;
        }
    }

    /**
     * Get all events (active and inactive)
     *
     * Returns empty array if table doesn't exist (during activation)
     */
    public static function getAll()
    {
        // Check if table exists before querying
        // Prevents "Table doesn't exist" error during plugin activation
        if (!static::tableExists()) {
            return [];
        }

        $instance = new static();

        // Suppress errors during query to prevent output during activation
        $suppress_errors = $instance->wpdb->suppress_errors(true);
        $show_errors = $instance->wpdb->show_errors;
        $instance->wpdb->show_errors = false;

        try {
            $results = $instance->wpdb->get_results(
                "SELECT * FROM {$instance->table}
                 ORDER BY is_active DESC, total_occurrences DESC",
                ARRAY_A
            );

            return $results ? array_map([$instance, 'castAttributes'], $results) : [];
        } finally {
            // Restore error handling
            $instance->wpdb->suppress_errors($suppress_errors);
            $instance->wpdb->show_errors = $show_errors;
        }
    }

    /**
     * Get events by type
     *
     * Returns null if table doesn't exist (during activation)
     */
    public static function getByType(string $event_type): ?array
    {
        // Check if table exists before querying
        // Prevents "Table doesn't exist" error during plugin activation
        if (!static::tableExists()) {
            return null;
        }

        $instance = new static();

        // Suppress errors during query to prevent output during activation
        $suppress_errors = $instance->wpdb->suppress_errors(true);
        $show_errors = $instance->wpdb->show_errors;
        $instance->wpdb->show_errors = false;

        try {
            $result = $instance->wpdb->get_row($instance->wpdb->prepare(
                "SELECT * FROM {$instance->table}
                 WHERE event_type = %s AND is_active = 1",
                $event_type
            ), ARRAY_A);

            return $result ? $instance->castAttributes($result) : null;
        } finally {
            // Restore error handling
            $instance->wpdb->suppress_errors($suppress_errors);
            $instance->wpdb->show_errors = $show_errors;
        }
    }

    /**
     * Find event row by type regardless of is_active.
     *
     * The table enforces a unique key on event_type; inactive rows must still be found
     * to avoid duplicate INSERT errors when auto-creating or reactivating core events.
     *
     * @return array|null Cast row or null
     */
    public static function findByEventTypeAnyStatus(string $event_type): ?array
    {
        if (!static::tableExists()) {
            return null;
        }

        $instance = new static();

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

        try {
            $result = $instance->wpdb->get_row($instance->wpdb->prepare(
                "SELECT * FROM {$instance->table} WHERE event_type = %s LIMIT 1",
                $event_type
            ), ARRAY_A);

            return $result ? $instance->castAttributes($result) : null;
        } finally {
            $instance->wpdb->suppress_errors($suppress_errors);
            $instance->wpdb->show_errors = $show_errors;
        }
    }

    /**
     * Auto create events from template
     *
     * Returns empty array if table doesn't exist (during activation)
     *
     * @param array<string, mixed> $config
     * @return array<int, array<string, mixed>|null>
     */
    public static function autoCreateFromTemplate(array $config): array
    {
        if (!static::tableExists()) {
            return [];
        }

        if (!isset($config['events']) || !is_array($config['events'])) {
            return [];
        }

        $created_events = [];
        foreach ($config['events'] as $event_data) {
            if (!is_array($event_data)) {
                continue;
            }
            $created = self::upsertTemplateEventRow($event_data);
            if ($created !== null) {
                $created_events[] = $created;
            }
        }

        return $created_events;
    }

    /**
     * Insert template event or reactivate inactive row (same event_type).
     *
     * @param array<string, mixed> $event_data
     * @return array<string, mixed>|null Newly created row; null when skipped or existing handled without create
     */
    private static function upsertTemplateEventRow(array $event_data): ?array
    {
        $existing_any = self::findByEventTypeAnyStatus($event_data['event_type']);
        if ($existing_any !== null) {
            self::reactivateInactiveTemplateEvent($existing_any, $event_data);
            return null;
        }

        $id = self::create([
            'event_type' => $event_data['event_type'],
            'event_name' => $event_data['event_name'],
            'description' => $event_data['description'],
            'tracking_method' => $event_data['tracking_method'],
            'is_active' => 1,
            'total_occurrences' => 0,
        ]);

        return $id ? self::find($id) : null;
    }

    /**
     * @param array<string, mixed> $existing_any
     * @param array<string, mixed> $event_data
     */
    private static function reactivateInactiveTemplateEvent(array $existing_any, array $event_data): void
    {
        $is_active = isset($existing_any['is_active']) && (int) $existing_any['is_active'] === 1;
        $has_id = isset($existing_any['id']);
        $should_reactivate = !$is_active && $has_id;
        if (!$should_reactivate) {
            return;
        }

        self::update((int) $existing_any['id'], [
            'event_name' => $event_data['event_name'],
            'description' => $event_data['description'],
            'tracking_method' => $event_data['tracking_method'],
            'is_active' => 1,
        ]);
    }

    /**
     * Increment occurrence count
     *
     * Returns false if table doesn't exist (during activation)
     */
    public static function incrementOccurrence(int $id)
    {
        // Check if table exists before updating
        if (!static::tableExists()) {
            return false;
        }

        $instance = new static();

        // Suppress errors during query to prevent output during activation
        $suppress_errors = $instance->wpdb->suppress_errors(true);
        $show_errors = $instance->wpdb->show_errors;
        $instance->wpdb->show_errors = false;

        try {
            return $instance->wpdb->query($instance->wpdb->prepare(
                "UPDATE {$instance->table}
                 SET total_occurrences = total_occurrences + 1,
                     last_occurrence_at = %s
                 WHERE id = %d",
                \current_time('mysql'),
                $id
            ));
        } finally {
            // Restore error handling
            $instance->wpdb->suppress_errors($suppress_errors);
            $instance->wpdb->show_errors = $show_errors;
        }
    }

    /**
     * Get statistics
     *
     * Returns zero values if table doesn't exist (during activation)
     */
    public static function getStatistics()
    {
        // Return safe defaults if table doesn't exist
        if (!static::tableExists()) {
            return [
                'total_events' => 0,
                'active_events' => 0,
                'total_occurrences' => 0,
                'top_event' => null
            ];
        }

        $instance = new static();

        // Suppress errors during query to prevent output during activation
        $suppress_errors = $instance->wpdb->suppress_errors(true);
        $show_errors = $instance->wpdb->show_errors;
        $instance->wpdb->show_errors = false;

        try {
            return [
                'total_events' => $instance->wpdb->get_var(
                    "SELECT COUNT(*) FROM {$instance->table}"
                ),
                'active_events' => $instance->wpdb->get_var(
                    "SELECT COUNT(*) FROM {$instance->table} WHERE is_active = 1"
                ),
                'total_occurrences' => $instance->wpdb->get_var(
                    "SELECT SUM(total_occurrences) FROM {$instance->table} WHERE is_active = 1"
                ),
                'top_event' => $instance->wpdb->get_row(
                    "SELECT event_name, total_occurrences
                     FROM {$instance->table}
                     WHERE is_active = 1
                     ORDER BY total_occurrences DESC
                     LIMIT 1",
                    ARRAY_A
                )
            ];
        } finally {
            // Restore error handling
            $instance->wpdb->suppress_errors($suppress_errors);
            $instance->wpdb->show_errors = $show_errors;
        }
    }

    /**
     * Override create to check table existence
     *
     * Returns false if table doesn't exist (during activation)
     */
    public static function create(array $data)
    {
        // Check if table exists before inserting
        if (!static::tableExists()) {
            if (function_exists('fleekdash_log_debug')) {
                fleekdash_log_debug('SiteGrowthEvent::create() - Table does not exist yet (activation in progress)');
            }
            return false;
        }

        return parent::create($data);
    }
}
