<?php
declare(strict_types=1);

namespace Instinctor\Services;

use Instinctor\Core\Config;
use Instinctor\Core\DB;
use Instinctor\Core\Auth;


if (!defined('ABSPATH')) exit;

/**
 * MembershipService - Membership tiers, content restriction, member pricing
 * @since 2.0.44
 */
class MembershipService
{
    private static ?self $instance = null;
    
    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Store-type driven since the addons layer collapse (2026-07-29):
     * membership machinery exists when the store type sells plans.
     */
    public static function isActive(): bool
    {
        return \Instinctor\Core\StoreFeatures::isFeatureEnabled('subscriptions');
    }
    
    /**
     * Get all membership tiers
     */
    public static function getTiers(): array
    {
        $table = DB::prefix() . 'instinctor_membership_tiers';
        
        if (DB::get_var("SHOW TABLES LIKE '{$table}'") !== $table) {
            return [];
        }
        
        return DB::get_results("SELECT * FROM {$table} ORDER BY sort_order ASC", ARRAY_A) ?: [];
    }
    
    /**
     * Get tier by ID
     */
    public static function getTier(int $id): ?array
    {
        $table = DB::prefix() . 'instinctor_membership_tiers';
        
        $tier = DB::get_row(
            DB::prepare("SELECT * FROM {$table} WHERE id = %d", $id), // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Safe table name
            ARRAY_A
        );
        
        return $tier ?: null;
    }
    
    /**
     * Save tier
     */
    public static function saveTier(array $data): int
    {
        $table = DB::prefix() . 'instinctor_membership_tiers';
        
        $tierData = [
            'name' => sanitize_text_field($data['name'] ?? ''),
            'slug' => sanitize_title($data['slug'] ?? $data['name'] ?? ''),
            'description' => sanitize_textarea_field($data['description'] ?? ''),
            'price' => floatval($data['price'] ?? 0),
            'billing_period' => sanitize_text_field($data['billing_period'] ?? 'monthly'),
            'discount_percent' => intval($data['discount_percent'] ?? 0),
            'restricted_categories' => wp_json_encode($data['restricted_categories'] ?? []),
            'restricted_products' => wp_json_encode($data['restricted_products'] ?? []),
            'benefits' => wp_json_encode($data['benefits'] ?? []),
            'is_active' => intval($data['is_active'] ?? 1),
            'sort_order' => intval($data['sort_order'] ?? 0),
        ];
        
        if (!empty($data['id'])) {

            DB::update($table, $tierData, ['id' => intval($data['id'])]);
            return intval($data['id']);
        } else {
            $tierData['created_at'] = current_time('mysql');
            DB::insert($table, $tierData);
            return DB::insert_id();
        }
    }
    
    /**
     * Delete tier
     */
    public static function deleteTier(int $id): bool
    {
        $table = DB::prefix() . 'instinctor_membership_tiers';
        return DB::delete($table, ['id' => $id]) !== false;
    }
    
    /**
     * Get user's membership
     */
    public static function getUserMembership(int $userId): ?array
    {
        $table = DB::prefix() . 'instinctor_user_memberships';
        
        if (DB::get_var("SHOW TABLES LIKE '{$table}'") !== $table) { // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Safe table name
            return null;
        }
        
        return DB::get_row(
            DB::prepare(
                "SELECT um.*, mt.name as tier_name, mt.discount_percent FROM {$table} um JOIN {$p}instinctor_membership_tiers mt ON um.tier_id = mt.id WHERE um.user_id = %d AND um.status = 'active' AND (um.expires_at IS NULL OR um.expires_at > NOW())", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Safe table name
                $userId
            ),
            ARRAY_A
        );
    }
    
    /**
     * Assign membership to user
     */
    public static function assignMembership(int $userId, int $tierId, ?string $expiresAt = null): bool
    {
        $table = DB::prefix() . 'instinctor_user_memberships';
        
        // Deactivate existing memberships
        DB::update($table, ['status' => 'cancelled'], ['user_id' => $userId, 'status' => 'active']);
        
        return DB::insert($table, [
            'user_id' => $userId,
            'tier_id' => $tierId,
            'status' => 'active',
            'started_at' => current_time('mysql'),
            'expires_at' => $expiresAt,
            'created_at' => current_time('mysql'),
        ]) !== false;
    }
    
    /**
     * Check if user can access product
     */
    public static function canAccessProduct(int $productId, int $userId = 0): bool
    {
        if (!self::isActive()) {
            return true;
        }
        
        $productTable = DB::prefix() . 'instinctor_products';
        
        $product = DB::get_row(
            DB::prepare("SELECT membership_required, membership_tiers FROM {$productTable} WHERE id = %d", $productId), // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Safe table name
            ARRAY_A
        );
        
        if (!$product || !$product['membership_required']) {
            return true;
        }
        
        if (!$userId) {
            $userId = Auth::userId();
        }
        
        if (!$userId) {
            return false;
        }
        
        $membership = self::getUserMembership($userId);
        
        if (!$membership) {
            return false;
        }
        
        $requiredTiers = json_decode($product['membership_tiers'] ?? '[]', true);
        
        if (empty($requiredTiers)) {
            return true; // Any membership allows access
        }
        
        return in_array($membership['tier_id'], $requiredTiers);
    }
    
    /**
     * Get member price for product
     */
    public static function getMemberPrice(float $price, int $userId = 0): float
    {
        if (!self::isActive()) {
            return $price;
        }
        
        if (!$userId) {
            $userId = Auth::userId();
        }
        
        if (!$userId) {
            return $price;
        }
        
        $membership = self::getUserMembership($userId);
        
        if (!$membership || !$membership['discount_percent']) {
            return $price;
        }
        
        $discount = $membership['discount_percent'] / 100;
        return round($price * (1 - $discount), 2);
    }
    
    /**
     * Get member count
     */
    public static function getMemberCount(): int
    {
        $table = DB::prefix() . 'instinctor_user_memberships';
        
        if (DB::get_var("SHOW TABLES LIKE '{$table}'") !== $table) {
            return 0;
        }
        
        return (int) DB::get_var("SELECT COUNT(*) FROM {$table} WHERE status = 'active'");
    }
    
    /**
     * Create database tables
     */
    public static function createTables(): void
    {
        $charset = DB::get_charset_collate();
        
        $tierTable = DB::prefix() . 'instinctor_membership_tiers';
        $memberTable = DB::prefix() . 'instinctor_user_memberships';
        
        $sql = "CREATE TABLE IF NOT EXISTS {$tierTable} (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            name varchar(255) NOT NULL,
            slug varchar(255) NOT NULL,
            description text,
            price decimal(10,2) DEFAULT 0,
            billing_period varchar(20) DEFAULT 'monthly',
            discount_percent int DEFAULT 0,
            restricted_categories longtext,
            restricted_products longtext,
            benefits longtext,
            is_active tinyint(1) DEFAULT 1,
            sort_order int DEFAULT 0,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY slug (slug)
        ) {$charset};
        
        CREATE TABLE IF NOT EXISTS {$memberTable} (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            user_id bigint(20) unsigned NOT NULL,
            tier_id bigint(20) unsigned NOT NULL,
            status varchar(20) DEFAULT 'active',
            started_at datetime DEFAULT CURRENT_TIMESTAMP,
            expires_at datetime DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY user_id (user_id),
            KEY tier_id (tier_id),
            KEY status (status)
        ) {$charset};";
        
        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        dbDelta($sql);
    }
}
