<?php

/**
 * Subscriber Table - Custom database table for newsletter subscribers
 * 
 * Provides scalable storage for subscribers instead of wp_options
 * 
 * @package WooNooW\Database
 */

namespace WooNooW\Database;

class SubscriberTable
{

    const TABLE_NAME = 'woonoow_subscribers';
    const DB_VERSION = '1.0';
    const DB_VERSION_OPTION = 'woonoow_subscribers_db_version';

    /**
     * Get full table name with prefix
     */
    public static function get_table_name()
    {
        global $wpdb;
        return $wpdb->prefix . self::TABLE_NAME;
    }

    /**
     * Create or update the subscribers table
     */
    public static function create_table()
    {
        global $wpdb;

        $table_name = self::get_table_name();
        $charset_collate = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE $table_name (
            id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            email VARCHAR(255) NOT NULL,
            user_id BIGINT(20) UNSIGNED DEFAULT NULL,
            status ENUM('pending','active','unsubscribed') DEFAULT 'pending',
            consent TINYINT(1) DEFAULT 0,
            consent_text TEXT,
            source VARCHAR(50) DEFAULT 'form',
            subscribed_at DATETIME DEFAULT NULL,
            confirmed_at DATETIME DEFAULT NULL,
            unsubscribed_at DATETIME DEFAULT NULL,
            ip_address VARCHAR(45) DEFAULT NULL,
            PRIMARY KEY (id),
            UNIQUE KEY idx_email (email),
            KEY idx_status (status),
            KEY idx_user_id (user_id)
        ) $charset_collate;";

        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);

        update_option(self::DB_VERSION_OPTION, self::DB_VERSION);
    }

    /**
     * Check if table exists
     */
    public static function table_exists()
    {
        global $wpdb;
        $table_name = self::get_table_name();
        return $wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name;
    }

    /**
     * Migrate existing subscribers from wp_options to custom table
     * 
     * @return array Migration result with counts
     */
    public static function migrate_from_options()
    {
        global $wpdb;

        // Ensure table exists
        if (!self::table_exists()) {
            self::create_table();
        }

        $table_name = self::get_table_name();
        $subscribers = get_option('woonoow_newsletter_subscribers', []);

        if (empty($subscribers)) {
            return ['migrated' => 0, 'skipped' => 0, 'message' => 'No subscribers to migrate'];
        }

        $migrated = 0;
        $skipped = 0;

        foreach ($subscribers as $sub) {
            if (empty($sub['email'])) {
                $skipped++;
                continue;
            }

            // Check if already exists in table
            $exists = $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM $table_name WHERE email = %s",
                $sub['email']
            ));

            if ($exists) {
                $skipped++;
                continue;
            }

            // Insert into new table
            $result = $wpdb->insert($table_name, [
                'email' => $sub['email'],
                'user_id' => $sub['user_id'] ?? null,
                'status' => $sub['status'] ?? 'active',
                'consent' => !empty($sub['consent']) ? 1 : 0,
                'subscribed_at' => $sub['subscribed_at'] ?? current_time('mysql'),
                'confirmed_at' => $sub['confirmed_at'] ?? null,
                'ip_address' => $sub['ip_address'] ?? null,
            ]);

            if ($result) {
                $migrated++;
            } else {
                $skipped++;
            }
        }

        // If all migrated successfully, remove the option
        if ($migrated > 0 && $skipped === 0) {
            delete_option('woonoow_newsletter_subscribers');
        }

        return [
            'migrated' => $migrated,
            'skipped' => $skipped,
            'message' => "Migrated $migrated subscribers, skipped $skipped",
        ];
    }
    
    // =========================================================================
    // CRUD OPERATIONS
    // =========================================================================

    /**
     * Add a new subscriber
     */
    public static function add($data)
    {
        global $wpdb;
        $table_name = self::get_table_name();

        $result = $wpdb->insert($table_name, [
            'email' => $data['email'],
            'user_id' => $data['user_id'] ?? null,
            'status' => $data['status'] ?? 'pending',
            'consent' => !empty($data['consent']) ? 1 : 0,
            'consent_text' => $data['consent_text'] ?? null,
            'source' => $data['source'] ?? 'form',
            'subscribed_at' => $data['subscribed_at'] ?? current_time('mysql'),
            'ip_address' => $data['ip_address'] ?? null,
        ]);

        if ($result) {
            return $wpdb->insert_id;
        }

        return false;
    }

    /**
     * Get a subscriber by email
     */
    public static function get_by_email($email)
    {
        global $wpdb;
        $table_name = self::get_table_name();

        return $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $table_name WHERE email = %s",
            $email
        ), ARRAY_A);
    }

    /**
     * Get a subscriber by ID
     */
    public static function get($id)
    {
        global $wpdb;
        $table_name = self::get_table_name();

        return $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $table_name WHERE id = %d",
            $id
        ), ARRAY_A);
    }

    /**
     * Update a subscriber
     */
    public static function update($id, $data)
    {
        global $wpdb;
        $table_name = self::get_table_name();

        return $wpdb->update($table_name, $data, ['id' => $id]);
    }

    /**
     * Update subscriber by email
     */
    public static function update_by_email($email, $data)
    {
        global $wpdb;
        $table_name = self::get_table_name();

        return $wpdb->update($table_name, $data, ['email' => $email]);
    }

    /**
     * Delete a subscriber
     */
    public static function delete($id)
    {
        global $wpdb;
        $table_name = self::get_table_name();

        return $wpdb->delete($table_name, ['id' => $id]);
    }

    /**
     * Delete subscriber by email
     */
    public static function delete_by_email($email)
    {
        global $wpdb;
        $table_name = self::get_table_name();

        return $wpdb->delete($table_name, ['email' => $email]);
    }

    /**
     * Get all active subscribers
     * 
     * @param array $filters Optional filters
     * @return array List of subscribers
     */
    public static function get_active($filters = [])
    {
        global $wpdb;
        $table_name = self::get_table_name();

        $where = ["status = 'active'"];
        $values = [];

        // Filter: subscribed after date
        if (!empty($filters['subscribed_after'])) {
            $where[] = "subscribed_at >= %s";
            $values[] = $filters['subscribed_after'];
        }

        // Filter: subscribed before date
        if (!empty($filters['subscribed_before'])) {
            $where[] = "subscribed_at <= %s";
            $values[] = $filters['subscribed_before'];
        }

        // Filter: registered users only
        if (!empty($filters['registered_only'])) {
            $where[] = "user_id IS NOT NULL";
        }

        // Filter: guests only
        if (!empty($filters['guests_only'])) {
            $where[] = "user_id IS NULL";
        }

        $where_sql = implode(' AND ', $where);
        $sql = "SELECT * FROM $table_name WHERE $where_sql ORDER BY subscribed_at DESC";

        if (!empty($values)) {
            $sql = $wpdb->prepare($sql, ...$values);
        }

        return $wpdb->get_results($sql, ARRAY_A);
    }

    /**
     * Get all subscribers with pagination
     */
    public static function get_all($args = [])
    {
        global $wpdb;
        $table_name = self::get_table_name();

        $defaults = [
            'per_page' => 20,
            'page' => 1,
            'status' => '',
            'search' => '',
            'orderby' => 'subscribed_at',
            'order' => 'DESC',
        ];

        $args = wp_parse_args($args, $defaults);
        $where = [];
        $values = [];

        if (!empty($args['status'])) {
            $where[] = "status = %s";
            $values[] = $args['status'];
        }

        if (!empty($args['search'])) {
            $where[] = "email LIKE %s";
            $values[] = '%' . $wpdb->esc_like($args['search']) . '%';
        }

        $where_sql = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

        // Get total count
        $count_sql = "SELECT COUNT(*) FROM $table_name $where_sql";
        if (!empty($values)) {
            $count_sql = $wpdb->prepare($count_sql, ...$values);
        }
        $total = (int) $wpdb->get_var($count_sql);

        // Get paginated results
        $offset = ($args['page'] - 1) * $args['per_page'];
        $orderby = sanitize_sql_orderby($args['orderby'] . ' ' . $args['order']) ?: 'subscribed_at DESC';

        $sql = "SELECT * FROM $table_name $where_sql ORDER BY $orderby LIMIT %d OFFSET %d";
        $values[] = $args['per_page'];
        $values[] = $offset;

        $items = $wpdb->get_results($wpdb->prepare($sql, ...$values), ARRAY_A);

        return [
            'items' => $items,
            'total' => $total,
            'pages' => ceil($total / $args['per_page']),
        ];
    }

    /**
     * Count subscribers by status
     */
    public static function count_by_status($status = null)
    {
        global $wpdb;
        $table_name = self::get_table_name();

        if ($status) {
            return (int) $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM $table_name WHERE status = %s",
                $status
            ));
        }

        return (int) $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
    }
}
