<?php
/**
 * DRBU_License — Freemius licensing layer.
 *
 * Apstrakcija iznad Freemius WordPress SDK-a. Sva provera licence u plugin-u
 * treba da ide kroz ovu klasu (ili drbu_is_pro_active()), nikad direktno kroz
 * Freemius objekat, tako da kod ostaje testabilan i otporan na izostanak SDK-a.
 *
 * Ako SDK nije prisutan (lokalni razvoj, unit testovi), klasa se ponaša kao
 * "Free / not valid" bez ikakvih grešaka.
 *
 * Zadržani su postojeći filteri kao extension point-i:
 *  - drbu_license_is_valid  (filter, bool)
 *  - drbu_license_status    (filter, string)
 *  - drbu_license_init      (akcija)
 *
 * @package discount-rules-box-upsell
 */

defined( 'ABSPATH' ) || exit;

class DRBU_License {

	/**
	 * Singleton instanca.
	 *
	 * @var DRBU_License|null
	 */
	private static $instance = null;

	/**
	 * Vraća jedinu instancu.
	 *
	 * @return DRBU_License
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Privatan konstruktor.
	 */
	private function __construct() {
		add_action( 'init', array( $this, 'init' ), 99 );
	}

	/**
	 * Poziva akciju drbu_license_init za buduće dodatke.
	 */
	public function init() {
		do_action( 'drbu_license_init', $this );
	}

	/**
	 * Freemius SDK objekat (ili null ako SDK nije uključen).
	 *
	 * @return \Freemius|null
	 */
	public function fs() {
		if ( function_exists( 'drbu_fs' ) ) {
			return drbu_fs();
		}
		return null;
	}

	/**
	 * Da li je Pro licenca aktivna (ili 30-dnevni trial).
	 *
	 * @return bool
	 */
	public function is_pro_active() {
		if ( function_exists( 'drbu_is_pro_active' ) ) {
			return (bool) drbu_is_pro_active();
		}
		return false;
	}

	/**
	 * Da li je licenca validna?
	 *
	 * Vraća true samo ako je Pro aktivan (plaćen ili trial). Kada SDK nije
	 * dostupan vraća false, osim ako neko preko filtera ne odluči drugačije.
	 *
	 * @return bool
	 */
	public function is_valid() {
		if ( $this->is_pro_active() ) {
			return (bool) apply_filters( 'drbu_license_is_valid', true, $this );
		}
		return (bool) apply_filters( 'drbu_license_is_valid', false, $this );
	}

	/**
	 * Da li korisnik plaća (nije u trial-u)?
	 *
	 * @return bool
	 */
	public function is_paying() {
		$fs = $this->fs();
		if ( $fs && method_exists( $fs, 'is_paying' ) ) {
			return (bool) $fs->is_paying();
		}
		return false;
	}

	/**
	 * Da li je korisnik u aktivnom trial periodu?
	 *
	 * @return bool
	 */
	public function is_trial() {
		$fs = $this->fs();
		if ( $fs && method_exists( $fs, 'is_trial' ) ) {
			return (bool) $fs->is_trial();
		}
		return false;
	}

	/**
	 * Da li je korisnik registrovan na Freemius-u?
	 *
	 * @return bool
	 */
	public function is_registered() {
		$fs = $this->fs();
		if ( $fs && method_exists( $fs, 'is_registered' ) ) {
			return (bool) $fs->is_registered();
		}
		return false;
	}

	/**
	 * Trenutni status licence.
	 *
	 * Moguće vrednosti: 'trial', 'active', 'free', 'invalid'.
	 *
	 * @return string
	 */
	public function get_status() {
		$status = 'free';

		if ( $this->is_pro_active() ) {
			$status = $this->is_trial() ? 'trial' : 'active';
		}

		return (string) apply_filters( 'drbu_license_status', $status, $this );
	}

	/**
	 * Da li je korisnik na Free planu.
	 *
	 * @return bool
	 */
	public function is_free() {
		return ! $this->is_pro_active();
	}

	/**
	 * Freemius upgrade / checkout URL.
	 *
	 * Kada SDK nije dostupan vraća null (pozivalac bira fallback link).
	 *
	 * @param bool $trial Da li da cilja na trial checkout (podrazumevano).
	 * @return string|null
	 */
	public function get_upgrade_url( $trial = true ) {
		$fs = $this->fs();
		if ( $fs && method_exists( $fs, 'get_upgrade_url' ) ) {
			return $fs->get_upgrade_url();
		}
		return null;
	}

	/**
	 * Freemius account / dashboard URL (upravljanje licencom).
	 *
	 * @return string|null
	 */
	public function get_account_url() {
		$fs = $this->fs();
		if ( $fs && method_exists( $fs, 'get_account_url' ) ) {
			return $fs->get_account_url();
		}
		return null;
	}

	/**
	 * URL za deaktivaciju licence.
	 *
	 * Deaktivacija se vrši preko Freemius account stranice (Customer Portal),
	 * koja sadrži ugrađeni "Deactivate" tok.
	 *
	 * @return string|null
	 */
	public function get_deactivate_url() {
		return $this->get_account_url();
	}

	/**
	 * Trenutni plan — slug.
	 *
	 * Primeri: 'free', 'pro-1-yearly', 'pro-5-lifetime', 'pro-10-yearly'.
	 *
	 * @return string
	 */
	public function get_plan_slug(): string {
		$slug = 'free';

		if ( $this->is_pro_active() ) {
			$sites   = $this->get_sites_limit();
			$billing = $this->is_lifetime() ? 'lifetime' : 'yearly';

			$slug = 'pro';
			if ( $sites > 0 ) {
				$slug .= '-' . $sites;
			}
			$slug .= '-' . $billing;
		}

		return (string) apply_filters( 'drbu_license_plan', $slug, $this );
	}

	/**
	 * Naziv plana za prikaz (iz Freemius-a, npr. "Pro 5 Sites").
	 *
	 * @return string
	 */
	public function get_plan_title(): string {
		if ( $this->is_trial() ) {
			return __( 'Pro Trial (30 Days)', 'drbu-discount-rules-box-for-woocommerce' );
		}
		$fs = $this->fs();
		if ( $fs && method_exists( $fs, 'get_plan' ) ) {
			$plan = $fs->get_plan();
			if ( is_object( $plan ) ) {
				if ( isset( $plan->title ) && is_string( $plan->title ) && '' !== trim( $plan->title ) ) {
					return $plan->title;
				}
				if ( isset( $plan->name ) && is_string( $plan->name ) && '' !== trim( $plan->name ) ) {
					return $plan->name;
				}
			}
		}
		return __( 'Pro', 'drbu-discount-rules-box-for-woocommerce' );
	}

	/**
	 * Broj sajtova koje licenca pokriva (1, 5, 10 ili 0 za Free).
	 *
	 * @return int
	 */
	public function get_sites_limit(): int {
		if ( ! $this->is_pro_active() ) {
			return 0;
		}

		$sites = 0;

		// 1) Iz plan objekta ako SDK izlaže sites_limit.
		$fs = $this->fs();
		if ( $fs && method_exists( $fs, 'get_plan' ) ) {
			$plan = $fs->get_plan();
			if ( is_object( $plan ) ) {
				if ( isset( $plan->sites_limit ) && (int) $plan->sites_limit > 0 ) {
					$sites = (int) $plan->sites_limit;
				} elseif ( isset( $plan->title ) && is_string( $plan->title ) ) {
					$sites = $this->sites_from_title( $plan->title );
				}
			}
		}

		// 2) Fallback: parsiraj naziv plana.
		if ( $sites <= 0 ) {
			$sites = $this->sites_from_title( $this->get_plan_title() );
		}

		// 3) Finalni fallback — svaki plaćeni plan pokriva bar 1 sajt.
		if ( $sites <= 0 ) {
			$sites = 1;
		}

		return (int) apply_filters( 'drbu_license_sites_limit', $sites, $this );
	}

	/**
	 * Da li je plan yearly (subscription)?
	 *
	 * @return bool
	 */
	public function is_yearly(): bool {
		return $this->is_pro_active() && ! $this->is_lifetime();
	}

	/**
	 * Da li je plan lifetime (one-time)?
	 *
	 * @return bool
	 */
	public function is_lifetime(): bool {
		if ( ! $this->is_pro_active() ) {
			return false;
		}

		$license = $this->get_license_object();
		if ( $license ) {
			if ( method_exists( $license, 'is_lifetime' ) ) {
				return (bool) $license->is_lifetime();
			}
			if ( isset( $license->is_lifetime ) ) {
				return (bool) $license->is_lifetime;
			}
			// Ako postoji rok trajanja, radi se o subscription-u.
			if ( isset( $license->expiration ) && (int) $license->expiration > 0 ) {
				return false;
			}
			return true;
		}

		return false;
	}

	/**
	 * License key (secret_key iz Freemius licence).
	 *
	 * @return string|null
	 */
	public function get_license_key(): ?string {
		$license = $this->get_license_object();
		if ( $license ) {
			if ( isset( $license->secret_key ) && is_string( $license->secret_key ) && '' !== $license->secret_key ) {
				return $license->secret_key;
			}
			if ( method_exists( $license, 'get_secret_key' ) ) {
				$key = $license->get_secret_key();
				if ( is_string( $key ) && '' !== $key ) {
					return $key;
				}
			}
		}
		return null;
	}

	/**
	 * Datum isteka licence (Y-m-d) ili null za lifetime / Free.
	 *
	 * @return string|null
	 */
	public function get_expiration_date(): ?string {
		// Trial nema pravu 'expiration' vrednost na license objektu — Freemius
		// je tamo drži kao null za trial (FS_Plugin_License::is_lifetime()
		// upravo to i proverava). Stvarni datum isteka trial-a je na SITE
		// (install) objektu kao 'trial_ends' — to i native Freemius Account
		// stranica koristi za "Expires in X weeks" (templates/account.php:
		// strtotime($site->trial_ends)). Bez ove grane, is_trial() slučaj je
		// uvek padao na "Lifetime / n/a" iako je trial imao stvaran datum isteka.
		if ( $this->is_trial() ) {
			$fs = $this->fs();
			if ( $fs && method_exists( $fs, 'get_site' ) ) {
				$site = $fs->get_site();
				if ( is_object( $site ) && ! empty( $site->trial_ends ) ) {
					$exp = strtotime( $site->trial_ends );
					if ( false !== $exp && $exp > 0 ) {
						return gmdate( 'Y-m-d', $exp );
					}
				}
			}
		}

		$license = $this->get_license_object();
		if ( $license && ! empty( $license->expiration ) ) {
			// Freemius vraća 'expiration' kao datumski string (npr. "2026-09-16 00:00:00"),
			// ne kao Unix timestamp — (int) cast na takav string uzima samo početne cifre
			// (npr. "2026"), pa gmdate() to protumači kao par sekundi posle 1970-01-01
			// (uvek prikazivalo "1970-01-01" bez obzira na stvarni datum isteka).
			$exp = strtotime( $license->expiration );
			if ( false !== $exp && $exp > 0 ) {
				return gmdate( 'Y-m-d', $exp );
			}
		}
		return null;
	}

	/**
	 * Broj aktiviranih sajtova pod trenutnom licencom.
	 *
	 * NAPOMENA (bug fix): ranije je ovde pogrešno pozivan `Freemius::get_sites()`
	 * — to je NEPOVEZANA WordPress multisite metoda (vraća pod-sajtove mreže,
	 * `includes/class-freemius.php`), koja na običnom single-site instalu uvek
	 * vraća prazan niz — otud je "Activations" uvek pisalo "0 / N sites" čak i
	 * dok je licenca stvarno aktivna na ovom sajtu. Stvaran broj aktivacija
	 * živi na `activated` (+ `activated_local` za localhost instalacije) polju
	 * license entiteta (`FS_Plugin_License::total_activations()`,
	 * `entities/class-fs-plugin-license.php`).
	 *
	 * @return int
	 */
	public function get_sites_used(): int {
		if ( ! $this->is_pro_active() ) {
			return 0;
		}

		$license = $this->get_license_object();
		if ( $license && isset( $license->activated ) && is_numeric( $license->activated ) ) {
			$used = (int) $license->activated;
			if ( isset( $license->activated_local ) && is_numeric( $license->activated_local ) ) {
				$used += (int) $license->activated_local;
			}
			if ( $used > 0 ) {
				return $used;
			}
		}

		// Fallback: Pro/trial je aktivan na OVOM sajtu (is_pro_active() je već
		// proverio), pa je makar 1 aktivacija stvarna čak i ako license
		// objekat (npr. kod nekih trial stanja) ne popuni 'activated'.
		return 1;
	}

	/**
	 * Vremenski žig poslednje sinhronizacije licence (webhook / lifecycle event).
	 *
	 * @return int
	 */
	public function get_last_sync(): int {
		return (int) get_option( 'drbu_license_last_sync', 0 );
	}

	/**
	 * Osvežava keš licence i bilježi vreme sinhronizacije.
	 *
	 * Zove se iz Freemius lifecycle hook-ova i webhook endpoint-a.
	 */
	public function refresh_cache() {
		$cache_keys = array( 'drbu_license_state', 'drbu_license_plan_data' );
		foreach ( $cache_keys as $cache_key ) {
			if ( function_exists( 'delete_transient' ) ) {
				delete_transient( $cache_key );
			}
			if ( function_exists( 'wp_cache_delete' ) ) {
				wp_cache_delete( $cache_key, 'drbu_license' );
			}
		}
		if ( function_exists( 'update_option' ) ) {
			update_option( 'drbu_license_last_sync', time() );
		}
		do_action( 'drbu_license_refreshed', $this );
	}

	/**
	 * Iz naziva plana izvlači broj sajtova ("Pro 5 Sites" -> 5).
	 *
	 * @param string $title Naziv/title plana.
	 * @return int
	 */
	private function sites_from_title( $title ) {
		if ( is_string( $title ) && preg_match( '/(\d+)\s*sites?/i', $title, $m ) ) {
			return (int) $m[1];
		}
		return 0;
	}

	/**
	 * Freemius license objekat (ili null).
	 *
	 * @return object|null
	 */
	private function get_license_object() {
		$fs = $this->fs();
		if ( $fs && method_exists( $fs, '_get_license' ) ) {
			$license = $fs->_get_license();
			return is_object( $license ) ? $license : null;
		}
		return null;
	}
}

/**
 * Globalni helper — ista instanca kao DRBU_License::instance().
 *
 * @return DRBU_License
 */
function drbu_license() {
	return DRBU_License::instance();
}
