<?php

namespace Salesloo\Rest_Api;

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

use \Salesloo\Abstracts\Rest_Api;
use \Salesloo\Models\Access;

/**
 * File Rest api
 */
class File extends Rest_Api
{
    protected $version = 'v1';

    protected $route = 'file';

    /**
     * register new route
     * 
     */
    public function register_routes()
    {
        if (\Salesloo\Plugin::instance()->license->status != 200) return;

        register_rest_route(
            $this->namespace,
            '/' . $this->version . '/' . $this->route . '/info/(?P<id>\w+)',
            [
                'methods'             => \WP_REST_Server::READABLE,
                'callback'            => [$this, 'get'],
                'permission_callback' => [$this, 'permissions'],
            ],
        );

        register_rest_route(
            $this->namespace,
            '/' . $this->version . '/' . $this->route . '/(?P<id>\w+)/download/(?P<auth>\S+)',
            [
                'methods'             => \WP_REST_Server::READABLE,
                'callback'            => [$this, 'download'],
                'permission_callback' => '__return_true',
            ],
        );

        register_rest_route(
            $this->namespace,
            '/' . $this->version . '/' . $this->route . '/license',
            [
                'methods'             => \WP_REST_Server::READABLE,
                'callback'            => [$this, 'activate'],
                'permission_callback' => [$this, 'permissions'],
            ],
        );

        register_rest_route(
            $this->namespace,
            '/' . $this->version . '/' . $this->route . '/license',
            [
                'methods'             => \WP_REST_Server::CREATABLE,
                'callback'            => [$this, 'activate'],
                'permission_callback' => [$this, 'permissions'],
            ],
        );

        register_rest_route(
            $this->namespace,
            '/' . $this->version . '/' . $this->route . '/license',
            [
                'methods'             => \WP_REST_Server::DELETABLE,
                'callback'            => [$this, 'delete'],
                'permission_callback' => [$this, 'permissions'],
            ],
        );
    }

    /**
     * permissions
     *
     * @param  mixed $request
     * @return mixed
     */
    public function permissions(\WP_REST_Request $request)
    {
        $params = $request->get_params();
        if (!isset($params['purchase_code']) || !isset($params['id']) || !isset($params['host'])) {

            return false;
        }

        return true;
    }

    public function get(\WP_REST_Request $request)
    {
        $access = $this->get_access($request);

        if (is_wp_error($access)) {
            return new \WP_REST_Response([
                'message' => $access->get_error_message(),
                'status' => 404
            ], 404);
        }

        $id   = sanitize_text_field($request->get_param('id'));
        $purchase_code   = sanitize_text_field($request->get_param('purchase_code'));
        $host   = sanitize_text_field($request->get_param('host'));

        $item = get_post(salesloo_get_item_by_license_id($id));

        $package =  get_post_meta($item->ID, 'package', true);

        $auth = salesloo_encrypt(json_encode([
            $purchase_code,
            $host
        ]));

        $package_url = site_url() . '/wp-json/v1/file/' . $id . '/download/' . $auth;

        return new \WP_REST_Response([
            'name'        => $item->post_title,
            'id'          => $id,
            'version'     => get_post_meta($item->ID, 'version', true),
            'package'     => $package_url,
            'description' => $item->post_excerpt,
            'changelog'   => strip_tags(get_post_meta($item->ID, 'changelog', true)),
        ], 404);
    }

    public function download(\WP_REST_Request $request)
    {
        $auth = sanitize_text_field($request->get_param('auth'));
        $id            = sanitize_text_field($request->get_param('id'));

        $array_auth = json_decode(salesloo_decrypt($auth), true);

        $purchase_code = isset($array_auth[0]) ? sanitize_text_field($array_auth[0]) : '';
        $host = isset($array_auth[1]) ? $array_auth[1] : '';

        $item_id = salesloo_get_item_by_license_id($id);

        $query = "WHERE item_id = $item_id AND status = 'active' AND code = '$purchase_code'";

        $access = Access::leftJoin('salesloo_order', ['salesloo_access.order_id', 'salesloo_order.ID', '='])
            ->select(
                ['salesloo_access.*'],
                ['salesloo_order.code'],
                ['salesloo_order.user_id'],
                ['salesloo_order.product_id'],
                ['salesloo_order.status'],
                ['salesloo_order.expired_at'],
            )
            ->query($query)
            ->first();

        if ($access->ID > 0) {
            $file = get_post_meta($item_id, 'package', true);

            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . basename($file) . '"');
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: ' . filesize($file));
            flush(); // Flush system output buffer
            readfile($file);
            die();
        }

        exit;
    }

    /**
     * checking license
     */
    public function check(\WP_REST_Request $request)
    {
        $id            = sanitize_text_field($request->get_param('id'));
        $host          = sanitize_text_field($request->get_param('host'));

        $access = $this->get_access($request);

        if (is_wp_error($access)) {
            return new \WP_REST_Response([
                'message' => $access->get_error_message(),
                'status' => 404
            ], 404);
        }

        $current_license       = $access->meta('license');
        $count_current_license = $current_license ? count((array)$current_license) : 0;
        $blocked_host          = $access->meta('license_blocked');
        $order                 = salesloo_get_order($access->order_id);

        if (in_array($host, (array)$blocked_host)) {
            return new \WP_REST_Response([
                'message' => sprintf(__('Your domain "%s" has been blocked, please contact admin', 'salesloo'), $host),
                'status' => 403
            ], 403);
        }

        $match = in_array($host, (array)$current_license);

        if (!$match) {
            //check if host started with www
            if (strpos($host, 'www.') !== false) {
                $checkHost = str_replace('www.', '', $host);
            } else {
                $checkHost = 'www.' . $host;
            }

            $match = in_array($checkHost, (array)$current_license);

            if ($match) {
                $host = $checkHost;
            }
        }

        if (!$match) {
            return new \WP_REST_Response([
                'message' => sprintf(__('Your domain "%s" has been deleted or has not been activated', 'salesloo'), $host),
                'status' => 403
            ], 403);
        }


        if ($access->expired_at && strtotime($access->expired_at) <= strtotime('now') || $access->status == 'expired') {
            return new \WP_REST_Response([
                'message' => sprintf(__('Your purchase code has an expired, please renew your purchase or use another active purchase code', 'salesloo'), $host),
                'status' => 402
            ], 402);
        }

        $data = salesloo_get_access_meta($access->ID, 'license_' . $host, true);
        $data['last_checked'] = date('Y-m-d H:i:s');

        salesloo_update_access_meta($access->ID, 'license_' . $host, $data);

        $respons = [
            'status'        => 200,
            'message'       => sprintf(__('The license for host "%s" is active', 'salesloo'), $host),
            'purchase_code' => $access->code,
            'expired_at'    => $access->expired_at ? $access->expired_at : '~',
            'license'       => [
                'limit' => $order->get_license_limit(),
                'used'  => $count_current_license
            ],
            'id'   => $id,
            'host' => $host,
        ];

        return new \WP_REST_Response($respons, 200);
    }

    /**
     * activate license
     */
    public function activate(\WP_REST_Request $request)
    {
        $id            = sanitize_text_field($request->get_param('id'));
        $host          = sanitize_text_field($request->get_param('host'));

        $access = $this->get_access($request);

        if (is_wp_error($access)) {
            return new \WP_REST_Response([
                'message' => $access->get_error_message(),
                'status' => 404
            ], 404);
        }

        $current_license       = $access->meta('license');
        $count_current_license = $current_license ? count((array)$current_license) : 0;
        $blocked_host          = (array)$access->meta('license_blocked');
        $order                 = salesloo_get_order($access->order_id);

        if (in_array($host, $blocked_host)) {
            return new \WP_REST_Response([
                'message' => sprintf(__('This domain "%s" cannot use this purchase code because it has been blocked', 'salesloo'), $host),
                'status' => 403
            ], 403);
        }

        if ($access->status == 'inactive') {
            return new \WP_REST_Response([
                'message' => __('This purchase code is not yet actived', 'salesloo'),
                'status' => 403
            ], 403);
        }

        if ($access->expired_at && strtotime($access->expired_at) <= strtotime('now') || $access->status == 'expired') {
            return new \WP_REST_Response([
                'message' => sprintf(__('This purchase code has expired, please renew your purchase or use another active purchase code', 'salesloo'), $host),
                'status' => 402
            ], 402);
        }

        $match = in_array($host, (array)$current_license);

        if (!$match) {
            //check if host started with www
            if (strpos($host, 'www.') !== false) {
                $checkHost = str_replace('www.', '', $host);
            } else {
                $checkHost = 'www.' . $host;
            }

            $match = in_array($checkHost, (array)$current_license);

            if ($match) {
                $host = $checkHost;
            }
        }

        if ($match) {
            $data = salesloo_get_access_meta($access->ID, 'license_' . $host, true);
            $data['last_checked'] = date('Y-m-d H:i:s');

            salesloo_update_access_meta($access->ID, 'license_' . $host, $data);

            $respons = [
                'status'        => 200,
                'message'       => sprintf(__('The license for host "%s" is active', 'salesloo'), $host),
                'purchase_code' => $access->code,
                'expired_at'    => $access->expired_at ? $access->expired_at : '~',
                'license'       => [
                    'limit' => $order->get_license_limit() <= 0 ? '~' : $order->get_license_limit(),
                    'used'  => $count_current_license
                ],
                'id'   => $id,
                'host' => $host,
            ];

            return new \WP_REST_Response($respons, 200);
        }

        if ($order->get_license_limit() > 0 && $count_current_license >= $order->get_license_limit()) {
            return new \WP_REST_Response([
                'message' => __('Can\'t activate host "' . $host . ' 
                " because the license has exceeded the limit.', 'salesloo'),
                'status' => 403
            ], 403);
        }

        salesloo_add_access_meta($access->ID, 'license', $host);
        $data = [
            'activate_at' => date('Y-m-d H:i:s'),
            'last_checked' => date('Y-m-d H:i:s')
        ];
        salesloo_add_access_meta($access->ID, 'license_' . $host, $data);

        $respons = [
            'status'        => 200,
            'purchase_code' => $access->code,
            'expired_at'    => $access->expired_at ? $access->expired_at : '~',
            'license'       => [
                'limit' => $order->get_license_limit() <= 0 ? '~' : $order->get_license_limit(),
                'used'  => $count_current_license + 1
            ],
            'id'      => $id,
            'host'    => $host,
            'message' => sprintf(__('The license for host "%s" is active', 'salesloo'), $host),
        ];

        return new \WP_REST_Response($respons, 200);
    }


    public function delete(\WP_REST_Request $request)
    {
        $host          = sanitize_text_field($request->get_param('host'));
        $access = $this->get_access($request);

        if (!is_wp_error($access)) {
            salesloo_delete_access_meta($access->ID, 'license', $host);
            salesloo_delete_access_meta($access->ID, 'license_' . $host);
        }

        return new \WP_REST_Response(
            [
                'message' => __('Your license has been deleted!', 'salesloo'),
                'status' => 200
            ],
            200
        );
    }

    private function get_access($request)
    {
        $purchase_code = sanitize_text_field($request->get_param('purchase_code'));
        $id            = sanitize_text_field($request->get_param('id'));

        $item_id = salesloo_get_item_by_license_id($id);

        $query = "WHERE item_id = $item_id AND code = '$purchase_code'";

        $access = Access::leftJoin('salesloo_order', ['salesloo_access.order_id', 'salesloo_order.ID', '='])
            ->select(
                ['salesloo_access.*'],
                ['salesloo_order.code'],
                ['salesloo_order.user_id'],
                ['salesloo_order.product_id'],
                ['salesloo_order.status'],
                ['salesloo_order.expired_at'],
            )
            ->query($query)
            ->first();

        return $access->ID > 0 ? $access : new \WP_Error('error', __('Invalid purchase code', 'salesloo'));
    }
}
