<?php

namespace Licenzo\Services;

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

use Licenzo\Model\License;
use Licenzo\Model\Subscription;

class QrCodeService
{
    private const TOKEN_TTL_SECONDS = 31536000; // 1 year
    private const HMAC_KEY_PREFIX = 'licenzo-qr-verify:';
    private const TOKEN_SEPARATOR = '.';

    private const ENTITY_LICENSE = 'license';
    private const ENTITY_SUBSCRIPTION = 'subscription';

    public static function generateVerificationToken(string $entityType, int $entityId): string
    {
        $payload = wp_json_encode([
            'type' => $entityType,
            'id'   => $entityId,
            'exp'  => time() + static::TOKEN_TTL_SECONDS,
        ]);

        $encoded = base64_encode($payload);
        $hmac = hash_hmac('sha256', $encoded, static::getSigningKey());

        return $encoded . static::TOKEN_SEPARATOR . $hmac;
    }

    public static function verifyToken(string $token): ?array
    {
        $parts = explode(static::TOKEN_SEPARATOR, $token, 2);
        if (count($parts) !== 2) {
            return null;
        }

        [$encoded, $hmac] = $parts;

        $expected = hash_hmac('sha256', $encoded, static::getSigningKey());
        if (!hash_equals($expected, $hmac)) {
            return null;
        }

        $payload = json_decode(base64_decode($encoded, true) ?: '', true);
        if (!is_array($payload) || empty($payload['type']) || empty($payload['id']) || empty($payload['exp'])) {
            return null;
        }

        if ((int) $payload['exp'] < time()) {
            return null;
        }

        return [
            'type' => (string) $payload['type'],
            'id'   => (int) $payload['id'],
        ];
    }

    public static function getVerificationUrl(string $entityType, int $entityId): string
    {
        $token = static::generateVerificationToken($entityType, $entityId);

        return rest_url('licenzo/v1/verify/' . $token);
    }

    /**
     * Returns safe, public-facing status data for a license or subscription.
     * Never exposes keys, emails, or financial amounts.
     */
    public static function getStatusData(string $entityType, int $entityId): ?array
    {
        if ($entityType === static::ENTITY_LICENSE) {
            return static::getLicenseStatusData($entityId);
        }

        if ($entityType === static::ENTITY_SUBSCRIPTION) {
            return static::getSubscriptionStatusData($entityId);
        }

        return null;
    }

    private static function getLicenseStatusData(int $licenseId): ?array
    {
        $license = License::find($licenseId);
        if (!$license) {
            return null;
        }

        $productName = static::resolveLicenseProductName($license);

        return [
            'entity_type'      => static::ENTITY_LICENSE,
            'status'           => $license->status,
            'product_name'     => $productName,
            'activation_count' => (int) $license->activation_count,
            'activation_limit' => (int) $license->activation_limit,
            'expires_at'       => $license->expire_date
                ? gmdate('Y-m-d', strtotime($license->expire_date))
                : null,
        ];
    }

    private static function getSubscriptionStatusData(int $subscriptionId): ?array
    {
        $subscription = Subscription::find($subscriptionId);
        if (!$subscription) {
            return null;
        }

        $productName = static::resolveSubscriptionProductName($subscription);

        return [
            'entity_type'       => static::ENTITY_SUBSCRIPTION,
            'status'            => $subscription->status,
            'product_name'      => $productName,
            'billing_cycle'     => $subscription->billing_cycle,
            'next_billing_date' => $subscription->next_billing_date
                ? gmdate('Y-m-d', strtotime($subscription->next_billing_date))
                : null,
        ];
    }

    private static function resolveLicenseProductName(License $license): ?string
    {
        $licenseProduct = $license->licenseProducts()->first();

        return $licenseProduct ? $licenseProduct->product_name : null;
    }

    private static function resolveSubscriptionProductName(Subscription $subscription): ?string
    {
        $subscriptionProduct = $subscription->subscriptionProducts()->first();

        return $subscriptionProduct ? $subscriptionProduct->product_name : null;
    }

    private static function getSigningKey(): string
    {
        return static::HMAC_KEY_PREFIX . wp_salt('auth');
    }
}
