<?php
/**
 * app/plugins/members/models/membership_records.php
 *
 * This class is used for the manipulation of the membership_records database table.
 *
 * @package TP Members
 * @version 3.0
 * @author  Joey Kimsey <Joey@thetempusproject.com>
 * @link    https://TheTempusProject.com
 * @license https://opensource.org/licenses/MIT [MIT LICENSE]
 */
namespace TheTempusProject\Models;

use TheTempusProject\Canary\Bin\Canary as Debug;
use TheTempusProject\Bedrock\Functions\Check;
use TheTempusProject\Bedrock\Functions\Sanitize;
use TheTempusProject\Classes\DatabaseModel;
use TheTempusProject\TheTempusProject as App;
use TheTempusProject\Models\MembershipProducts;
use TheTempusProject\Bedrock\Classes\Config;
use TheTempusProject\Canary\Classes\CustomException;

class Memberships extends DatabaseModel {
    public static $stripe;
    public static $products;
    private static $loaded = false;
    public $tableName = 'membership_records';
    public $databaseMatrix = [
        [ 'stripe_customer', 'varchar', '64' ],
        [ 'stripe_subscription', 'varchar', '64' ],
        [ 'subscription_price_id', 'varchar', '64' ],
        [ 'current_period_end', 'int', '10' ],
        [ 'current_period_start', 'int', '10' ],
        [ 'status', 'varchar', '64' ],
        [ 'local_user_id', 'int', '10' ],
        [ 'billing_frequency', 'varchar', '16' ],
    ];

    public function __construct() {
        parent::__construct();
        if ( ! self::$loaded ) {
            self::$products = new MembershipProducts;
            $api_key = Config::getValue( 'memberships/stripeSecret' );
            if ( $api_key == 'sk_xxxxxxxxxxxxxxx' || empty($api_key) ) {
                Debug::error( "Memberships:__construct No Stripe Key found" );
            } else {
                self::$stripe = new \Stripe\StripeClient( $api_key );
            }
            self::$loaded = true;
        }
    }

    public function filter( $postArray, $params = [] ) {
        foreach ( $postArray as $instance ) {
            if ( !is_object( $instance ) ) {
                $instance = $postArray;
                $end = true;
            }
            $instance->name = self::$user->getUsername( $instance->local_user_id );
            $priceData = self::$products->findByPriceID( $instance->subscription_price_id );
            if ( $priceData ) {
                if ( $priceData->stripe_price_monthly == $instance->subscription_price_id ) {
                    $price = $priceData->monthly_price;
                } else {
                    $price = $priceData->yearly_price;
                }
                $instance->productName = $priceData->name;
                $instance->prettyPrice = '&#36;' . number_format( $price / 100, 2 ); // Outputs: $99.49
            } else {
                $instance->prettyPrice = "unknown";
                $instance->productName = "unknown";
            }
            $out[] = $instance;
            if ( !empty( $end ) ) {
                $out = $out[0];
                break;
            }
        }
        return $out;
    }

    public function getUserSubs( $limit = null ) {
        $whereClause = ['local_user_id', '=', App::$activeUser->ID ];
        if ( empty( $limit ) ) {
            $postData = self::$db->get( $this->tableName, $whereClause );
        } else {
            $postData = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
        }
        if ( !$postData->count() ) {
            Debug::info( 'No user subs found.' );
            return false;
        }
        return $this->filter( $postData->results() );
    }

    public function findByUserID( $d ) {
        $data = self::$db->get( $this->tableName, [ 'local_user_id', '=', $d ] );
        if ( ! $data->count() ) {
            return false;
        }
        return $data->first();
    }
    
    public function findActiveByUserID( $d ) {
        $data = self::$db->get( $this->tableName, [ 'local_user_id', '=', $d, 'AND', 'status', '=', 'active' ] );
        if ( ! $data->count() ) {
            return false;
        }
        return $data->first();
    }

    public function cancel( $id ) {
        $data = self::$db->get( $this->tableName, [ 'ID', '=', $id, 'AND', 'local_user_id', '=', App::$activeUser->ID, 'AND', 'status', '=', 'active' ] );
        if ( ! $data->count() ) {
            return false;
        }
        $membershipID = $data->first()->stripe_subscription;
        $out = false;
        try {
            $out = self::$stripe->subscriptions->cancel($membershipID, []);
        } catch(\Exception $e) {
            Debug::error( 'Exception' );
            Debug::v( $e );
        }
        return $out;
    }

    public function findBySubscriptionID( $d ) {
        $data = self::$db->get( $this->tableName, [ 'stripe_subscription', '=', $d ] );
        if ( ! $data->count() ) {
            return false;
        }
        return $data->first();
    }

    public function create( $customer, $subscription, $price, $start, $end, $status, $user_id, $frequency ) {
        $fields = [
            'stripe_customer' => $customer,
            'stripe_subscription' => $subscription,
            'subscription_price_id' => $price,
            'current_period_end' => $end,
            'current_period_start' => $start,
            'status' => $status,
            'local_user_id' => $user_id,
            'billing_frequency' => $frequency,
        ];
        
        if ( !self::$db->insert( $this->tableName, $fields ) ) {
            Debug::error( "Memberships: not created: $fields" );
            new CustomException( 'membershipsCreate' );
            return false;
        }

        return true;
    }
    
    public function update( $id, $start, $end, $status ) {
        $fields = [
            'current_period_end' => $end,
            'current_period_start' => $start,
            'status' => $status,
        ];
        
        if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
            Debug::error( "Memberships: not updated: " );
            Debug::v( $fields );
            new CustomException( 'membershipsUpdate' );
            return false;
        }

        return true;
    }
}