<?php

namespace KeyLair;

/**
 * Optional per-product platform restriction + claimable quota
 * (sql/migrations/008_product_platforms.sql). A product with no rows here
 * is unrestricted: every configured platform is shown on its claim page,
 * with no cap beyond actual key stock -- exactly the behavior before this
 * table existed. A product opts in by having any row at all; from then on,
 * only its selected platforms are supported, each optionally capped by
 * claim_limit independent of how many keys actually exist for it.
 */
class ProductPlatform
{
    /** @return array<string, ?int> platform slug => claim_limit (null = unlimited), in Platform::slugs() order */
    public static function forProduct(int $productId): array
    {
        $pdo = Database::connection();
        $stmt = $pdo->prepare(
            'SELECT pp.platform, pp.claim_limit
             FROM product_platforms pp
             JOIN platforms p ON p.slug = pp.platform
             WHERE pp.product_id = :product_id
             ORDER BY p.sort_order, p.label'
        );
        $stmt->execute(['product_id' => $productId]);

        $rows = [];
        foreach ($stmt->fetchAll() as $row) {
            $rows[$row['platform']] = $row['claim_limit'] !== null ? (int) $row['claim_limit'] : null;
        }
        return $rows;
    }

    public static function isRestricted(int $productId): bool
    {
        $pdo = Database::connection();
        $stmt = $pdo->prepare('SELECT 1 FROM product_platforms WHERE product_id = :product_id LIMIT 1');
        $stmt->execute(['product_id' => $productId]);
        return (bool) $stmt->fetchColumn();
    }

    /** @return string[] Slugs this product actually supports -- every configured platform if unrestricted. */
    public static function supportedSlugs(int $productId): array
    {
        $rows = self::forProduct($productId);
        return $rows ? array_keys($rows) : Platform::slugs();
    }

    /** Null means "no cap" -- either unrestricted, the platform isn't selected for this product, or no limit was set. */
    public static function claimLimit(int $productId, string $platform): ?int
    {
        return self::forProduct($productId)[$platform] ?? null;
    }

    /** Keys already redeemed for this product+platform, regardless of any quota. */
    public static function claimedCount(int $productId, string $platform): int
    {
        $pdo = Database::connection();
        $stmt = $pdo->prepare(
            "SELECT COUNT(*) FROM `keys` WHERE product_id = :product_id AND platform = :platform AND status = 'redeemed'"
        );
        $stmt->execute(['product_id' => $productId, 'platform' => $platform]);
        return (int) $stmt->fetchColumn();
    }

    /**
     * Replaces the full platform selection for a product in one go.
     * @param array<string, ?int> $selections platform slug => claim_limit (null = unlimited). Pass [] to make the product unrestricted again.
     */
    public static function set(int $productId, array $selections): void
    {
        $pdo = Database::connection();
        $pdo->beginTransaction();
        try {
            $pdo->prepare('DELETE FROM product_platforms WHERE product_id = :product_id')
                ->execute(['product_id' => $productId]);

            if ($selections) {
                $insert = $pdo->prepare(
                    'INSERT INTO product_platforms (product_id, platform, claim_limit) VALUES (:product_id, :platform, :claim_limit)'
                );
                foreach ($selections as $platform => $limit) {
                    if (!Platform::exists($platform)) {
                        continue;
                    }
                    $insert->execute(['product_id' => $productId, 'platform' => $platform, 'claim_limit' => $limit]);
                }
            }

            $pdo->commit();
        } catch (\Throwable $e) {
            $pdo->rollBack();
            throw $e;
        }
    }
}
