<?php

/**
 * Site Counter
 *
 * Manages site counting and activation limits for license tiers
 *
 * @package ProRank\SEO\Core
 * @since   1.0.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Core;

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


/**
 * Site Counter class
 */


class SiteCounter {

    /**
     * Site limits by tier
     *
     * @var array<string, int>
     */
    private const TIER_LIMITS = [
        'free'     => 1,
        'pro'      => 1,
        'business' => 5,
        'agency'   => 25,
    ];

    /**
     * Available add-ons
     *
     * @var array<string, array>
     */
    private const ADD_ONS = [
        '+3_sites' => [
            'sites' => 3,
            'available_for' => ['pro', 'business'],
        ],
        '+10_sites' => [
            'sites' => 10,
            'available_for' => ['business', 'agency'],
        ],
        '+50_sites' => [
            'sites' => 50,
            'available_for' => ['agency'],
        ],
    ];

    /**
     * Staging hostname patterns (not counted)
     *
     * @var array<string>
     */
    private const STAGING_PATTERNS = [
        '/^staging\./i',
        '/^dev\./i',
        '/^test\./i',
        '/^local\./i',
        '/\.local$/i',
        '/\.test$/i',
        '/\.staging\./i',
        '/\.dev\./i',
    ];

    /**
     * License manager instance
     *
     * @var LicenseManager
     */
    private LicenseManager $license_manager;

    /**
     * Constructor
     *
     * @param LicenseManager $license_manager License manager instance
     */
    public function __construct(LicenseManager $license_manager) {
        $this->license_manager = $license_manager;
    }

    /**
     * Get site limit for current license
     *
     * @return int Total sites allowed
     */
    public function get_site_limit(): int {
        $tier = $this->license_manager->get_tier();
        $base_limit = self::TIER_LIMITS[$tier] ?? 1;

        // Add any add-on sites
        $add_ons = $this->get_active_add_ons();
        $additional_sites = 0;

        foreach ($add_ons as $add_on_id) {
            if (isset(self::ADD_ONS[$add_on_id])) {
                $additional_sites += self::ADD_ONS[$add_on_id]['sites'];
            }
        }

        return $base_limit + $additional_sites;
    }

    /**
     * Get active add-ons from license data
     *
     * @return array<string>
     */
    private function get_active_add_ons(): array {
        $license_status = $this->license_manager->get_license_data();
        return $license_status['add_ons'] ?? [];
    }

    /**
     * Get number of currently activated sites
     *
     * @return int
     */
    public function get_activated_site_count(): int {
        $activated_sites = $this->get_activated_sites();
        return count($activated_sites);
    }

    /**
     * Get list of activated sites
     *
     * @return array<string>
     */
    public function get_activated_sites(): array {
        $license_status = $this->license_manager->get_license_data();
        return $license_status['activated_sites'] ?? [];
    }

    /**
     * Check if current site is activated
     *
     * @return bool
     */
    public function is_current_site_activated(): bool {
        $current_hostname = $this->get_current_hostname();
        $activated_sites = $this->get_activated_sites();

        return in_array($current_hostname, $activated_sites, true);
    }

    /**
     * Check if a new site can be activated
     *
     * @return bool
     */
    public function can_activate_new_site(): bool {
        // If current site is already activated, always allow
        if ($this->is_current_site_activated()) {
            return true;
        }

        // If staging site, always allow (doesn't count)
        if ($this->is_staging_site()) {
            return true;
        }

        // Check if under limit
        $current_count = $this->get_activated_site_count();
        $limit = $this->get_site_limit();

        return $current_count < $limit;
    }

    /**
     * Get remaining site slots
     *
     * @return int
     */
    public function get_remaining_slots(): int {
        $limit = $this->get_site_limit();
        $used = $this->get_activated_site_count();

        return max(0, $limit - $used);
    }

    /**
     * Get current site hostname (normalized)
     *
     * @return string
     */
    public function get_current_hostname(): string {
        $url = home_url();
        $host = wp_parse_url($url, PHP_URL_HOST);

        return $this->normalize_hostname($host ?: '');
    }

    /**
     * Normalize hostname for comparison
     *
     * Removes www prefix and converts to lowercase
     *
     * @param string $hostname Hostname to normalize
     * @return string Normalized hostname
     */
    public function normalize_hostname(string $hostname): string {
        $hostname = strtolower($hostname);

        // Remove www. prefix (canonicalize)
        if (strpos($hostname, 'www.') === 0) {
            $hostname = substr($hostname, 4);
        }

        return $hostname;
    }

    /**
     * Check if current site is a staging/dev site
     *
     * @return bool
     */
    public function is_staging_site(): bool {
        $hostname = $this->get_current_hostname();

        // Check against staging patterns
        foreach (self::STAGING_PATTERNS as $pattern) {
            if (preg_match($pattern, $hostname)) {
                return true;
            }
        }

        // Check for custom staging patterns from settings
        $custom_patterns = get_option('prorank_staging_patterns', []);
        foreach ($custom_patterns as $pattern) {
            if (stripos($hostname, $pattern) !== false) {
                return true;
            }
        }

        // Check WP_ENVIRONMENT_TYPE if available
        if (function_exists('wp_get_environment_type')) {
            $env = wp_get_environment_type();
            if (in_array($env, ['local', 'development', 'staging'], true)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Check if hostname is a staging variant of a production site
     *
     * @param string $staging_hostname Potential staging hostname
     * @param string $production_hostname Production hostname
     * @return bool
     */
    public function is_staging_variant(string $staging_hostname, string $production_hostname): bool {
        $staging = $this->normalize_hostname($staging_hostname);
        $production = $this->normalize_hostname($production_hostname);

        // Check if staging hostname contains production hostname
        if (strpos($staging, $production) !== false) {
            return true;
        }

        // Check common patterns like staging.example.com for example.com
        foreach (['staging.', 'dev.', 'test.'] as $prefix) {
            if ($staging === $prefix . $production) {
                return true;
            }
        }

        return false;
    }

    /**
     * Get staging allowance per production site
     *
     * @return int
     */
    public function get_staging_allowance(): int {
        return 2; // 2 staging sites per production site
    }

    /**
     * Get site usage summary
     *
     * @return array
     */
    public function get_usage_summary(): array {
        return [
            'tier' => $this->license_manager->get_tier(),
            'base_limit' => self::TIER_LIMITS[$this->license_manager->get_tier()] ?? 1,
            'add_ons' => $this->get_active_add_ons(),
            'total_limit' => $this->get_site_limit(),
            'activated_count' => $this->get_activated_site_count(),
            'activated_sites' => $this->get_activated_sites(),
            'remaining_slots' => $this->get_remaining_slots(),
            'current_site' => $this->get_current_hostname(),
            'is_current_activated' => $this->is_current_site_activated(),
            'is_staging' => $this->is_staging_site(),
            'staging_allowance' => $this->get_staging_allowance(),
        ];
    }

    /**
     * Get available add-ons for current tier
     *
     * @return array
     */
    public function get_available_add_ons(): array {
        $tier = $this->license_manager->get_tier();
        $available = [];

        foreach (self::ADD_ONS as $id => $add_on) {
            if (in_array($tier, $add_on['available_for'], true)) {
                $available[$id] = [
                    'id' => $id,
                    'sites' => $add_on['sites'],
                ];
            }
        }

        return $available;
    }

    /**
     * Check if add-on is valid for tier
     *
     * @param string $add_on_id Add-on identifier
     * @param string $tier License tier
     * @return bool
     */
    public function is_add_on_valid_for_tier(string $add_on_id, string $tier): bool {
        if (!isset(self::ADD_ONS[$add_on_id])) {
            return false;
        }

        return in_array($tier, self::ADD_ONS[$add_on_id]['available_for'], true);
    }
}
