<?php
/**
 * @author 1902 Software
 * @copyright Copyright © 2023 1902 Software (https://1902software.com/magento/)
 * @package WriteTextAI_WriteTextAI
 */

namespace WriteTextAI\WriteTextAI\ViewModel;

use WriteTextAI\WriteTextAI\Model\ApiManager;
use Magento\Framework\App\CacheInterface;

class Premium implements \Magento\Framework\View\Element\Block\ArgumentInterface
{
    public const UNLOCK_PREMIUM_URL = 'https://platform.writetext.ai/premium';

    public const ALL_FEATURES_URL = 'https://writetext.ai/features';

    public const MEMBERSHIP_TYPE_FREE_TRIAL = 'FreeTrial';

    public const MEMBERSHIP_TYPE_STARTER = 'Starter';

    public const MEMBERSHIP_TYPE_PROFESSIONAL = 'Professional';

    public const MEMBERSHIP_TYPE_ENTERPRISE = 'Enterprise';

    /**
     * @var ApiManager
     */
    protected $apiManager;

    /**
     * @var CacheInterface
     */
    protected $cache;

    /**
     * Cache key prefix for credit data
     */
    public const CACHE_KEY_PREFIX = 'wtai_premium_credit_';

    /**
     * Cache lifetime in seconds (59 minutes)
     */
    public const CACHE_LIFETIME = 3540;

    /**
     * @var int
     */
    protected $totalCredits = null;

    /**
     * @var int
     */
    protected $availableCredits = null;

    /**
     * @var bool
     */
    protected $isPremium = null;

    /**
     * @var bool
     */
    protected $freePremiumCredits = null;

    /**
     * @var bool
     */
    protected $freeCreditsAlreadyPremium = null;

    /**
     * @var bool
     */
    protected $welcomePremium20 = null;

    /**
     * @var bool
     */
    protected $unlockedPremium = null;

    /**
     * @var bool
     */
    protected $unlockedFreeTrial = null;

    /**
     * @var bool
     */
    protected $noCreditsFreeTrial = null;

    /**
     * @var bool
     */
    protected $unlockedProfessional = null;

    /**
     * @var bool
     */
    protected $unlockedEnterprise = null;

    /**
     * @var string
     */
    protected $membershipType = null;

    /**
     * @var bool
     */
    protected $hasProAccess = null;

    /**
     * @var string
     */
    protected $subscriptionExpiration = null;
    
    /**
     * @var array
     */
    protected $account = [];

    /**
     * Constructor
     *
     * @param ApiManager $apiManager
     * @param CacheInterface $cache
     */
    public function __construct(
        ApiManager $apiManager,
        CacheInterface $cache
    ) {
        $this->apiManager = $apiManager;
        $this->cache = $cache;
    }
    
    /**
     * Get credit data with caching support
     *
     * @param bool $refreshCachedData If true, force refresh from API and update cache
     * @return bool
     */
    public function getCredit($refreshCachedData = false)
    {
        $cacheKey = self::CACHE_KEY_PREFIX . 'data';
        $credit = null;
        
        if ($refreshCachedData) {
            // Force refresh: get from API and save to cache
            try {
                $credit = $this->apiManager->getCredit();
            } catch (\Exception $e) {
                $credit = [];
            }
            
            if ($credit) {
                $this->cache->save(json_encode($credit), $cacheKey, [], self::CACHE_LIFETIME);
            }
        } else {
            // Try to get from cache first
            $cachedData = $this->cache->load($cacheKey);
            
            if ($cachedData !== false) {
                $credit = json_decode($cachedData, true);
            } else {
                // Cache miss: get from API and save to cache
                $credit = $this->apiManager->getCredit();
                if ($credit) {
                    $this->cache->save(json_encode($credit), $cacheKey, [], self::CACHE_LIFETIME);
                }
            }
        }
        
        // If we still don't have credit data, return default values
        if (!$credit) {
            $credit = [];
        }

        $totalCredits = isset($credit['totalCredits']) ? (int) $credit['totalCredits'] : 0;
        $this->setTotalCredits($totalCredits);

        $availableCredits = isset($credit['availableCredits']) ? (int) $credit['availableCredits'] : 0;
        $this->setAvailableCredits($availableCredits);

        $isPremium = isset($credit['isPremium']) ? (bool) $credit['isPremium'] : false;
        $this->setIsPremium($isPremium);

        $freePremiumCredits = isset($credit['freePremiumCredits']) ? (bool) $credit['freePremiumCredits'] : false;
        $this->setFreePremiumCredits($freePremiumCredits);

        $freeCreditsAlreadyPremium = isset($credit['freeCreditsAlreadyPremium'])
            ? (bool) $credit['freeCreditsAlreadyPremium']
            : false;
        $this->setFreeCreditsAlreadyPremium($freeCreditsAlreadyPremium);
        
        $welcomePremium20 = isset($credit['welcomePremium20']) ? (bool) $credit['welcomePremium20'] : false;
        $this->setWelcomePremium20($welcomePremium20);

        $unlockedPremium = isset($credit['unlockedPremium']) ? (bool) $credit['unlockedPremium'] : false;
        $this->setUnlockedPremium($unlockedPremium);

        $unlockedFreeTrial = isset($credit['unlockedFreeTrial']) ? (bool) $credit['unlockedFreeTrial'] : false;
        $this->setUnlockedFreeTrial($unlockedFreeTrial);

        $noCreditsFreeTrial = isset($credit['noCreditsFreeTrial']) ? (bool) $credit['noCreditsFreeTrial'] : false;
        $this->setNoCreditsFreeTrial($noCreditsFreeTrial);

        $unlockedProfessional = isset($credit['unlockedProfessional']) ? (bool) $credit['unlockedProfessional'] : false;
        $this->setUnlockedProfessional($unlockedProfessional);

        $unlockedEnterprise = isset($credit['unlockedEnterprise']) ? (bool) $credit['unlockedEnterprise'] : false;
        $this->setUnlockedEnterprise($unlockedEnterprise);

        $membershipType = isset($credit['membershipType']) ? (string) $credit['membershipType'] : '';
        $this->setMembershipType($membershipType);

        $hasProAccess = isset($credit['hasProAccess']) ? (bool) $credit['hasProAccess'] : false;
        $this->setHasProAccess($hasProAccess);

        $subscriptionExpiration = isset($credit['subscriptionExpiration'])
            ? (string) $credit['subscriptionExpiration']
            : '';
        $this->setSubscriptionExpiration($subscriptionExpiration);

        return $isPremium;
    }

    /**
     * Get unclock premium url
     *
     * @return string
     */
    public function getUnlockPremiumUrl()
    {
        return self::UNLOCK_PREMIUM_URL;
    }

    /**
     * Get all features url
     *
     * @return string
     */
    public function getAllFeaturesUrl()
    {
        return self::ALL_FEATURES_URL;
    }

    /**
     * Get ads
     *
     * @return array
     */
    public function getAds()
    {
        return $this->apiManager->getSpecificAds('Magento1920x100');
    }

    /**
     * Get ads horizontal
     *
     * @return array
     */
    public function getAdsFullWidth()
    {
        try {
            $ads = [
                '1920' => $this->apiManager->getSpecificAds('Magento1920x100'),
                // '1697' => $this->apiManager->getSpecificAds('Magento1697x100'),
                // '1440' => $this->apiManager->getSpecificAds('Magento1440x100'),
                // '1180' => $this->apiManager->getSpecificAds('Magento1180x98'),
                // '768' => $this->apiManager->getSpecificAds('Magento768x64'),
            ];
        } catch (\Exception $e) {
            return [
                '1920' => '',
                '1697' => '',
                '1440' => '',
                '1180' => '',
                '768' => '',
            ];
        }

        return $ads;
    }

    /**
     * Get freemium credits
     *
     * @return int
     */
    public function getFreemiumCredits()
    {
        if (!empty($this->account)) {
            $account = $this->account;
        } else {
            $account = $this->apiManager->getAccount();
        }

        return $account['account']['company']['freePremiumCredits'] ?? 110;
    }

    /**
     * Set total credits
     *
     * @param int $totalCredits
     */
    public function setTotalCredits($totalCredits)
    {
        $this->totalCredits = $totalCredits;
    }

    /**
     * Get total credits
     *
     * @param bool $refreshCachedData
     * @return int
     */
    public function getTotalCredits($refreshCachedData = false)
    {
        if ($this->totalCredits !== null && !$refreshCachedData) {
            return $this->totalCredits;
        }
        $this->getCredit($refreshCachedData);

        return $this->totalCredits;
    }

    /**
     * Set available credits
     *
     * @param int $availableCredits
     * @return void
     */
    public function setAvailableCredits($availableCredits)
    {
        $this->availableCredits = $availableCredits;
    }

    /**
     * Get available credits
     *
     * @return int
     */
    public function getAvailableCredits()
    {
        if ($this->availableCredits !== null) {
            return $this->availableCredits;
        }
        $this->getCredit();

        return $this->availableCredits;
    }

    /**
     * Set is premium
     *
     * @param bool $isPremium
     * @return void
     */
    protected function setIsPremium($isPremium)
    {
        $this->isPremium = $isPremium;
    }

    /**
     * Get is premium
     *
     * @return bool
     */
    public function getIsPremium()
    {
        if ($this->isPremium !== null) {
            return $this->isPremium;
        }
        $this->getCredit();

        return $this->isPremium;
    }

    /**
     * Set freePremiumCredits
     *
     * @param bool $freePremiumCredits
     * @return void
     */
    public function setFreePremiumCredits($freePremiumCredits)
    {
        $this->freePremiumCredits = $freePremiumCredits;
    }

    /**
     * Get free premium credits
     *
     * @return bool
     */
    public function getFreePremiumCredits()
    {
        if ($this->freePremiumCredits !== null) {
            return $this->freePremiumCredits;
        }

        $this->getCredit();

        return $this->freePremiumCredits;
    }

    /**
     * Set freeCreditsAlreadyPremium
     *
     * @param bool $freeCreditsAlreadyPremium
     * @return void
     */
    public function setFreeCreditsAlreadyPremium($freeCreditsAlreadyPremium)
    {
        $this->freeCreditsAlreadyPremium = $freeCreditsAlreadyPremium;
    }

    /**
     * Get free credits already premium
     *
     * @return bool
     */
    public function getFreeCreditsAlreadyPremium()
    {
        if ($this->freeCreditsAlreadyPremium !== null) {
            return $this->freeCreditsAlreadyPremium;
        }

        $this->getCredit();

        return $this->freeCreditsAlreadyPremium;
    }
    
    /**
     * Set welcome premium 20
     *
     * @param bool $welcomePremium20
     */
    public function setWelcomePremium20($welcomePremium20)
    {
        $this->welcomePremium20 = $welcomePremium20;
    }

    /**
     * Get welcome premium 20
     *
     * @return bool
     */
    public function getWelcomePremium20()
    {
        if ($this->welcomePremium20 !== null) {
            return $this->welcomePremium20;
        }

        $this->getCredit();

        return $this->welcomePremium20;
    }

    /**
     * Set unlocked premium
     *
     * @param bool $unlockedPremium
     */
    public function setUnlockedPremium($unlockedPremium)
    {
        $this->unlockedPremium = $unlockedPremium;
    }

    /**
     * Get unlocked premium
     *
     * @return bool
     */
    public function getUnlockedPremium()
    {
        if ($this->unlockedPremium !== null) {
            return $this->unlockedPremium;
        }

        $this->getCredit();

        return $this->unlockedPremium;
    }

    /**
     * Set unlocked free trial
     *
     * @param bool $unlockedFreeTrial
     * @return void
     */
    public function setUnlockedFreeTrial($unlockedFreeTrial)
    {
        $this->unlockedFreeTrial = $unlockedFreeTrial;
    }

    /**
     * Get unlocked free trial
     *
     * @return bool
     */
    public function getUnlockedFreeTrial()
    {
        if ($this->unlockedFreeTrial !== null) {
            return $this->unlockedFreeTrial;
        }

        $this->getCredit();

        return $this->unlockedFreeTrial;
    }

    /**
     * Set no credits free trial
     *
     * @param bool $noCreditsFreeTrial
     * @return void
     */
    public function setNoCreditsFreeTrial($noCreditsFreeTrial)
    {
        $this->noCreditsFreeTrial = $noCreditsFreeTrial;
    }

    /**
     * Get no credits free trial
     *
     * @return bool
     */
    public function getNoCreditsFreeTrial()
    {
        if ($this->noCreditsFreeTrial !== null) {
            return $this->noCreditsFreeTrial;
        }

        $this->getCredit();

        return $this->noCreditsFreeTrial;
    }

    /**
     * Set unlocked professional
     *
     * @param bool $unlockedProfessional
     * @return void
     */
    public function setUnlockedProfessional($unlockedProfessional)
    {
        $this->unlockedProfessional = $unlockedProfessional;
    }

    /**
     * Get unlocked professional
     *
     * @return bool
     */
    public function getUnlockedProfessional()
    {
        if ($this->unlockedProfessional !== null) {
            return $this->unlockedProfessional;
        }

        $this->getCredit();

        return $this->unlockedProfessional;
    }

    /**
     * Set unlocked enterprise
     *
     * @param bool $unlockedEnterprise
     * @return void
     */
    public function setUnlockedEnterprise($unlockedEnterprise)
    {
        $this->unlockedEnterprise = $unlockedEnterprise;
    }

    /**
     * Get unlocked enterprise
     *
     * @return bool
     */
    public function getUnlockedEnterprise()
    {
        if ($this->unlockedEnterprise !== null) {
            return $this->unlockedEnterprise;
        }

        $this->getCredit();

        return $this->unlockedEnterprise;
    }

    /**
     * Set membership type
     *
     * @param string $membershipType
     * @return void
     */
    public function setMembershipType($membershipType)
    {
        $this->membershipType = $membershipType;
    }

    /**
     * Get membership type
     *
     * @return string
     */
    public function getMembershipType()
    {
        if ($this->membershipType !== null) {
            return $this->membershipType;
        }
        $this->getCredit();

        return $this->membershipType;
    }

    /**
     * Set has pro access
     *
     * @param bool $hasProAccess
     * @return void
     */
    public function setHasProAccess($hasProAccess)
    {
        $this->hasProAccess = $hasProAccess;
    }

    /**
     * Get has pro access
     *
     * @return bool
     */
    public function getHasProAccess()
    {
        if ($this->hasProAccess !== null) {
            return $this->hasProAccess;
        }
        $this->getCredit();

        return $this->hasProAccess;
    }

    /**
     * Set subscription expiration
     *
     * @param string $subscriptionExpiration
     * @return void
     */
    public function setSubscriptionExpiration($subscriptionExpiration)
    {
        $this->subscriptionExpiration = $subscriptionExpiration;
    }

    /**
     * Get subscription expiration
     *
     * @return string
     */
    public function getSubscriptionExpiration()
    {
        if ($this->subscriptionExpiration !== null) {
            return $this->subscriptionExpiration;
        }
        $this->getCredit();

        return $this->subscriptionExpiration;
    }

    /**
     * Clear cached credit data
     *
     * @return void
     */
    public function clearCachedCreditData()
    {
        $cacheKey = self::CACHE_KEY_PREFIX . 'data';
        $this->cache->remove($cacheKey);
        
        // Reset all local properties to null so they get refreshed
        $this->totalCredits = null;
        $this->availableCredits = null;
        $this->isPremium = null;
        $this->freePremiumCredits = null;
        $this->freeCreditsAlreadyPremium = null;
        $this->welcomePremium20 = null;
        $this->unlockedPremium = null;
        $this->unlockedFreeTrial = null;
        $this->noCreditsFreeTrial = null;
        $this->unlockedProfessional = null;
        $this->unlockedEnterprise = null;
        $this->membershipType = null;
        $this->hasProAccess = null;
        $this->subscriptionExpiration = null;
    }
}
