<?php
/**
 * Copyright (C) Baluart.COM - All Rights Reserved
 *
 * @since 1.0
 * @author Baluart E.I.R.L.
 * @copyright Copyright (c) 2015 - 2021 Baluart E.I.R.L.
 * @license http://codecanyon.net/licenses/faq Envato marketplace licenses
 * @link https://easyforms.dev/ Easy Forms
 */
namespace app\modules\subscription\models;

use app\helpers\CurrencyHelper;
use Yii;
use yii\behaviors\BlameableBehavior;
use yii\behaviors\TimestampBehavior;

/**
 * This is the model class for table "{{%subscription_price}}".
 *
 * @property int $id
 * @property int $product_id
 * @property string|null $paypal_price_id
 * @property string|null $test_paypal_price_id
 * @property string|null $stripe_price_id
 * @property string|null $test_stripe_price_id
 * @property string $name
 * @property string|null $description
 * @property string|null $image
 * @property int $status
 * @property int|null $amount
 * @property string|null $currency_code
 * @property string|null $model
 * @property string|null $type
 * @property string $interval
 * @property integer|null $interval_count
 * @property string $trial_period_days
 * @property int $created_by
 * @property int $updated_by
 * @property int|null $created_at
 * @property int|null $updated_at
 *
 * @property SubscriptionProduct $product
 * @property string $typeLabel
 * @property string $intervalAbbr
 */
class SubscriptionPrice extends \yii\db\ActiveRecord
{

    const TYPE_ONE_TIME = 'one-time';
    const TYPE_RECURRING = 'recurring';

    const INTERVAL_DAY = 'day';
    const INTERVAL_WEEK = 'week';
    const INTERVAL_MONTH = 'month';
    const INTERVAL_YEAR = 'year';

    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return '{{%subscription_price}}';
    }

    /**
     * @inheritdoc
     */
    public static function primaryKey()
    {
        return ['id'];
    }

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            BlameableBehavior::class,
            TimestampBehavior::class,
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['product_id', 'name', 'interval'], 'required'],
            [['product_id', 'amount', 'status', 'interval_count', 'created_by', 'updated_by', 'created_at', 'updated_at'], 'integer'],
            [['description', 'image'], 'string'],
            [['paypal_price_id', 'test_paypal_price_id', 'stripe_price_id', 'test_stripe_price_id'], 'string', 'max' => 64],
            [['name', 'interval', 'trial_period_days'], 'string', 'max' => 255],
            [['currency_code'], 'string', 'max' => 3],
            [['model', 'type'], 'string', 'max' => 32],
            ['interval_count', 'required',
                'when' => function ($model) {
                    return !empty($model->interval);
                },
                'whenClient' => "function (attribute, value) {
                    return $(\"input[name='SubscriptionPrice[interval]']\").val() !== '';
                }"],
            ['interval_count', 'validateIntervalCount'],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'product_id' => Yii::t('app', 'Product ID'),
            'paypal_price_id' => Yii::t('app', 'Paypal Plan ID'),
            'test_paypal_price_id' => Yii::t('app', 'Paypal Plan ID (Sandbox)'),
            'stripe_price_id' => Yii::t('app', 'Stripe Price ID'),
            'test_stripe_price_id' => Yii::t('app', 'Stripe Price ID (Test)'),
            'name' => Yii::t('app', 'Name'),
            'description' => Yii::t('app', 'Description'),
            'image' => Yii::t('app', 'Image URL'),
            'status' => Yii::t('app', 'Status'),
            'amount' => Yii::t('app', 'Amount'),
            'currency_code' => Yii::t('app', 'Currency'),
            'model' => Yii::t('app', 'Model'),
            'type' => Yii::t('app', 'Type'),
            'interval' => Yii::t('app', 'Interval'),
            'interval_count' => Yii::t('app', 'Number of Intervals'),
            'trial_period_days' => Yii::t('app', 'Trial Period Days'),
            'created_by' => Yii::t('app', 'Created By'),
            'updated_by' => Yii::t('app', 'Updated By'),
            'created_at' => Yii::t('app', 'Created At'),
            'updated_at' => Yii::t('app', 'Updated At'),
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProduct()
    {
        return $this->hasOne(SubscriptionProduct::class,['id'=>'product_id']);
    }

    public function validateIntervalCount($attribute, $params, $validator)
    {
        $maxAllowedIntervalCount = self::maxAllowedIntervalCount();

        $maxAllowed = !empty($maxAllowedIntervalCount[$this->interval]) ? $maxAllowedIntervalCount[$this->interval] : 0;

        if ($this->$attribute > $maxAllowed) {
            $this->addError($attribute, Yii::t('app', 'The interval count must be less than or equal to {maxAllowed}.', [
                'maxAllowed' => $maxAllowed,
            ]));
        }
    }

    /**
     * Get Type list
     *
     * @return array
     */
    public static function availableTypes()
    {
        return [
            self::TYPE_RECURRING => Yii::t('app', 'Recurring'),
            self::TYPE_ONE_TIME => Yii::t('app', 'One time'),
        ];
    }

    /**
     * Get Available Intervals
     *
     * @return array
     */
    public static function availableIntervals()
    {
        return [
            self::INTERVAL_DAY => Yii::t('app', 'Day'),
            self::INTERVAL_WEEK => Yii::t('app', 'Week'),
            self::INTERVAL_MONTH => Yii::t('app', 'Month'),
            self::INTERVAL_YEAR => Yii::t('app', 'Year'),
        ];
    }

    /**
     * Get the Maximum Allowed Interval Count
     *
     * @return array
     */
    public static function maxAllowedIntervalCount()
    {
        return [
            self::INTERVAL_DAY => 365,
            self::INTERVAL_WEEK => 52,
            self::INTERVAL_MONTH => 12,
            self::INTERVAL_YEAR => 1,
        ];
    }

    /**
     * Get Interval Abbreviation
     *
     * @return string
     */
    public function getIntervalAbbr()
    {
        $interval = $this->interval;

        if ($this->interval === self::INTERVAL_MONTH) {
            $interval = Yii::t('app', 'Mo');
        } elseif ($this->interval === self::INTERVAL_YEAR) {
            $interval = Yii::t('app', 'Yr');
        } elseif ($this->interval === self::INTERVAL_WEEK) {
            $interval = Yii::t('app', 'Week');
        } elseif ($this->interval === self::INTERVAL_DAY) {
            $interval = Yii::t('app', 'Day');
        }

        return $interval;
    }

    public function getIntervalLabel()
    {
        $interval = $this->interval;

        if ($this->interval_count !== 1) {
            if ($interval === self::INTERVAL_MONTH) {
                $interval = Yii::t('app', 'Months');
            } elseif ($interval === self::INTERVAL_YEAR) {
                $interval = Yii::t('app', 'Years');
            } elseif ($interval === self::INTERVAL_WEEK) {
                $interval = Yii::t('app', 'Weeks');
            } elseif ($interval === self::INTERVAL_DAY) {
                $interval = Yii::t('app', 'Days');
            }

            $interval = $this->interval_count . ' ' . $interval;
        } else {
            if ($interval === self::INTERVAL_MONTH) {
                $interval = Yii::t('app', 'Monthly');
            } elseif ($interval === self::INTERVAL_YEAR) {
                $interval = Yii::t('app', 'Yearly');
            } elseif ($interval === self::INTERVAL_WEEK) {
                $interval = Yii::t('app', 'Weekly');
            } elseif ($interval === self::INTERVAL_DAY) {
                $interval = Yii::t('app', 'Daily');
            }
        }

        return $interval;
    }

    /**
     * Calculate Trial Ends At
     *
     * @param int|null $from Unix Timestamp
     * @return false|int|null
     */
    public function calculateTrialEndsAt($from = null)
    {
        $from = is_null($from) ? time() : $from;
        $days = $this->trial_period_days;

        return !empty($days) && is_numeric($days) ? strtotime('+' . $days . ' day', $from) : null;
    }

    /**
     * Calculate Ends At
     *
     * @param int|null $from Unix timestamp
     * @return false|int|null
     */
    public function calculateEndsAt($from = null)
    {
        if (!empty($this->interval_count)) {

            $interval = $this->interval;
            $days = 0;

            if ($interval === self::INTERVAL_YEAR) {
                $days = 365;
            } elseif ($interval === self::INTERVAL_MONTH) {
                $days = 30;
            } elseif ($interval === self::INTERVAL_WEEK) {
                $days = 7;
            } elseif ($interval === self::INTERVAL_DAY) {
                $days = 1;
            }

            $days = (int) $this->interval_count * $days;

            $from = is_null($from) ? time() : $from;

            // If there are pending trial period days
            if (!empty($this->trial_period_days)) {
                $from = $this->calculateTrialEndsAt($from);
            }

            return strtotime('+' . $days . ' day', $from);
        }

        return null;
    }

    /**
     * Get Type Label
     *
     * @return string
     */
    public function getTypeLabel()
    {
        $types = self::availableTypes();

        return !empty($types[$this->type]) ? $types[$this->type] : '';
    }

    /**
     * Get Paypal Plan ID
     *
     * @return string|null
     */
    public function getPaypalId()
    {
        return Yii::$app->settings->get('subscription.environment') == SubscriptionProduct::MODE_LIVE
            ? $this->paypal_price_id
            : $this->test_paypal_price_id;
    }

    /**
     * Has Paypal Plan ID
     *
     * @return bool
     */
    public function hasPaypalId()
    {
        $paypalID = Yii::$app->settings->get('subscription.environment') == SubscriptionProduct::MODE_LIVE
            ? $this->paypal_price_id
            : $this->test_paypal_price_id;

        return !empty($paypalID);
    }

    /**
     * Get Stripe Plan ID
     *
     * @return string|null
     */
    public function getStripeId()
    {
        return Yii::$app->settings->get('subscription.environment') == SubscriptionProduct::MODE_LIVE
            ? $this->stripe_price_id
            : $this->test_stripe_price_id;
    }

    /**
     * Has Stripe Plan ID
     *
     * @return bool
     */
    public function hasStripeId()
    {
        $stripeID = Yii::$app->settings->get('subscription.environment') == SubscriptionProduct::MODE_LIVE
            ? $this->stripe_price_id
            : $this->test_stripe_price_id;

        return !empty($stripeID);
    }

    /**
     * Get Formatted Amount
     *
     * @return string|null
     */
    public function getFormattedAmount()
    {
        $amount = null;

        if (!empty($this->amount)) {
            // Amount is in cents
            $amount = $this->amount / 100;
            $amount = Yii::$app->formatter->asDecimal($amount, 2);
        }

        return $amount;
    }

    public function getCurrencySymbol()
    {
        if (!empty($this->currency_code)) {
            $currency = strtoupper($this->currency_code);
            return CurrencyHelper::getCurrencySymbolAsHtmlEntity($currency);
        }

        return null;
    }

    /**
     * Is it a recurring payment?
     *
     * @return bool
     */
    public function isRecurring()
    {
        return $this->type === self::TYPE_RECURRING;
    }
}
