<?php
namespace Pay4All\Pro\License;

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

/**
 * SaaS + option-name constants. Kept in one class so the LicenseManager /
 * ApiClient can share a single source of truth. Trial constants are exposed
 * as class constants (not filters) — the merchant CANNOT extend the trial
 * from wp-config.
 */
final class Constants {

	public const PRODUCT_CODE = 'pay4all-pro';

	// Drives /plugins/<slug>/update-check on the SaaS. Must match the
	// product code/slug declared on pay4all.net → /config/plugins so the
	// SaaS resolves the row and returns the metadata WP expects.
	public const UPDATE_PRODUCT_CODE = 'pay4all-pro';

	public const API_BASE = 'https://pay4all.net/api/v1';
	public const SAAS_URL = 'https://pay4all.net';

	public const HTTP_TIMEOUT_SECS = 15;

	// Trial window fallback — only used to compute a display default when the
	// SaaS response is unavailable. The AUTHORITATIVE trial length lives on
	// the SaaS (config/app.php → licence.trial_days) and is echoed back on
	// every /domains/check response. See Store::trial_ends_at() consumer.
	public const TRIAL_DAYS = 30;

	// SaaS check cadence + grace window used by LicenseManager. Matches the
	// 48h / 72h agreement documented in the SaaS architecture doc.
	public const CHECK_INTERVAL_SECONDS = 48 * HOUR_IN_SECONDS;
	public const GRACE_SECONDS          = 72 * HOUR_IN_SECONDS;

	// wp_options keys owned by the License layer.
	// OPT_TRIAL_STARTED_AT — DEPRECATED : the trial anchor now lives on the
	// SaaS domains row. Kept in code so old installs can be cleaned up on
	// upgrade, but never read by the gate. See Store::trial_ends_at().
	public const OPT_TRIAL_STARTED_AT   = 'p4all_pro_trial_started_at';
	public const OPT_INSTALLATION_UUID  = 'p4all_pro_installation_uuid';
	public const OPT_INSTALLATION_SECRET= 'p4all_pro_installation_secret';
	public const OPT_LAST_CHECK_AT      = 'p4all_pro_license_last_check_at';
	public const OPT_VALID_UNTIL        = 'p4all_pro_license_valid_until';
	public const OPT_GRACE_UNTIL        = 'p4all_pro_license_grace_until';
	public const OPT_STATUS             = 'p4all_pro_license_status';   // active | trial | pending_subscription | suspended | …
	public const OPT_DOMAIN             = 'p4all_pro_license_domain';
	public const OPT_REGISTERED_AT      = 'p4all_pro_registered_at';
	public const OPT_LAST_ERROR         = 'p4all_pro_license_last_error';
	public const OPT_PREVIOUS_DOMAIN    = 'p4all_pro_license_previous_domain';
	// Server-signed trial anchor + end date, populated from /domains/check.
	// Both are ISO-8601 UTC strings ; empty when the domain is already paid
	// or when no successful check has run yet.
	public const OPT_TRIAL_ENDS_AT      = 'p4all_pro_license_trial_ends_at';
	public const OPT_TRIAL_STARTED_SAAS = 'p4all_pro_license_trial_started_saas';
	// Subscription-type mirror (populated from /domains/check when a paid
	// or lifetime subscription exists). Empty when the domain is on trial
	// or has no subscription. Purely display-side ; feature gating stays
	// driven by OPT_STATUS.
	public const OPT_PLAN_INTERVAL      = 'p4all_pro_license_plan_interval';       // 'month' | 'year' | ''
	public const OPT_PLAN_AMOUNT_CENTS  = 'p4all_pro_license_plan_amount_cents';   // int cents, 0 when unknown
	public const OPT_PLAN_CURRENCY      = 'p4all_pro_license_plan_currency';       // 'chf' | 'eur' | ''
	public const OPT_IS_LIFETIME        = 'p4all_pro_license_is_lifetime';         // '1' | ''

	// WP-Cron hook — unique per plugin so uninstalling one Pay4All-family
	// plugin doesn't unschedule the check for the others.
	public const CRON_HOOK = 'p4all_pro_license_check';

	// SaaS-side statuses treated as « unlock the paid features ». Mirrors the
	// Stripe subscription lifecycle : `past_due` stays live so a merchant who
	// missed a debit doesn't lose access before the retry window closes.
	// `trial` = SaaS-anchored 30-day free trial (server-side signed).
	public const LIVE_STATUSES = [ 'active', 'trialing', 'past_due', 'cancel_at_period_end', 'trial' ];

	// Statuses that immediately lock the paid features, bypassing the 72 h
	// grace window. Used by the tri-state gating in LicenseManager.
	// `pending_subscription` = SaaS-signed « trial over, no paid plan yet » ;
	// treated as hard-reject so the grace window (meant for network hiccups)
	// doesn't accidentally keep Pro features live after the trial ends.
	public const HARD_REJECT_STATUSES = [ 'suspended', 'expired', 'disabled', 'pending_subscription' ];

	// Transient key used by AdminPage to carry a flash notice across the
	// admin-post redirect. Bounded TTL so a stale message never sticks.
	public const FLASH_TRANSIENT = 'p4all_pro_admin_flash';
}
