<?php

/*
 * @component UserPoints
 * @copyright Copyright (C) 2015-2022 Bernard Gilly - Adrien Roussel - Martin Brampton
 * @license : GNU/GPL
 * @Website : https://remository.com
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Language\Text;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Uri\Uri;
use BlackSheepResearch\Component\UserPoints\Site\UserPoints;
use BlackSheepResearch\Component\UserPoints\Site\Problems\Rule;
use BlackSheepResearch\Component\UserPoints\Site\Problems\SQL;

class plgEshopUserpoints extends CMSPlugin {

    protected $autoloadLanguage = true;

    public function __construct(&$subject, $config = array()) {
        parent::__construct($subject, $config);

        // Load the admin language file on the frontend
        $lang = Factory::getLanguage();
        $lang->load('plg_eshop_userpoints', JPATH_ADMINISTRATOR);
    }

    public function onAfterCompleteOrder($order) {
        if (!class_exists(UserPoints::class)) {
            Factory::getApplication()->enqueueMessage(Text::_('PLG_ESHOP_USERPOINTS_ERROR_LOADING_USERPOINTS'), 'error');
            return false;
        }
        if (!$order || !isset($order->total)) {
            return false;
        }
        // Get database connection
        $db = SQL::getInstance();

        // Get order details
        $query = $db->getQuery(true)
            ->select('*')
            ->from($db->quoteName('#__eshop_ordertotals'))
            ->where($db->quoteName('order_id') . ' = ' . (int) $order->id);

        $order_totals = $db->setQuery($query)->loadObjectList();

        if (!$order_totals) {
            return false;
        }

        $sub_total = $shipping = $vat_total = $vat_rate = $eco_tax = $order_total = 0.0;

        foreach ($order_totals as $one_total) {
            switch ($one_total->name) {
                case 'sub_total': $sub_total = $one_total->value;
                    break;
                case 'shipping': $shipping = $one_total->value;
                    break;
                case 'tax':
                    if (substr($one_total->title, 0, 3) == 'VAT') {
                        $vat_total = $one_total->value;
                        $vat_rate = $this->getVatRate($one_total->title);
                    } elseif (substr($one_total->title, 0, 3) == 'Eco') {
                        $eco_tax = $one_total->value;
                    }
                    break;
                case 'total': $order_total = $one_total->value;
            }
        }

        // Add your userpoints logic here
        // Example: Award points based on order total
        $points_value = $order_total;
        if (!$this->params->get('include_shipping', 0)) {
            $points_value -= $shipping * (1.0 + $vat_rate);
            $vat_total -= ($shipping * $vat_rate);
        }
        if (!$this->params->get('include_vat', 0)) {
            $points_value -= $vat_total;
        }
        if (!$this->params->get('include_eco', 0)) {
            $points_value -= $eco_tax;
        }

        if ($points_value > 0.0) {
            $keyreference = UserPoints::buildKeyreference('up_eshop_order', $order->id);
            UserPoints::newpoints('up_eshop_order', '', $keyreference, '', $points_value);
        }

        return true;
    }

    private function getVatRate($vatString) {
        if (preg_match('/\(([\d.]+)%\)/', $vatString, $matches)) {
            return floatval($matches[1]) / 100;
        }
        return 0;
    }

    public function onGetMyCoupons() {
        if (!class_exists(UserPoints::class)) {
            Factory::getApplication()->enqueueMessage(Text::_('PLG_ESHOP_USERPOINTS_ERROR_LOADING_USERPOINTS'), 'error');
            return false;
        }
        $rule = Rule::withRuleName('up_eshop_buypoints');
        if (!$rule->published) {
            return false;
        }
        $user = UserPoints::getUser();
        // Get database connection
        $db = SQL::getInstance();
        // Get coupons
        $query = $db->getQuery(true)
            ->select('c.*')
            ->from($db->quoteName('#__eshop_coupons', 'c'))
            ->leftJoin(
                $db->quoteName('#__eshop_couponhistory', 'h') .
                ' ON ' . $db->quoteName('h.coupon_id') . ' = ' . $db->quoteName('c.id')
            )
            ->where($db->quoteName('c.created_by') . ' = ' . (int) $user->id)
            ->where($db->quoteName('h.coupon_id') . ' IS NULL');

        $coupons = $db->setQuery($query)->loadObjectList();
        $coupon_html = '';
        foreach ($coupons as $coupon) {
            $type = $coupon->coupon_type == 'P' ? Text::_('PLG_ESHOP_USERPOINTS_PERCENT') : Text::_('PLG_ESHOP_USERPOINTS_FIXED');
            $suffix = $coupon->coupon_type == 'P' ? '%' : '';
            $coupon_html .= <<<COUPON_HTML

        <tr>
            <td headers="categorylist_header_title" class="list-title">EShop</td>
            <td headers="categorylist_header_title" class="list-title">$coupon->coupon_name</td>
            <td headers="categorylist_header_title" class="list-title">$coupon->coupon_code</td>
            <td headers="categorylist_header_title" class="list-title">$type</td>
            <td headers="categorylist_header_title" class="list-title">$coupon->coupon_value$suffix</td>
            <td headers="categorylist_header_title" class="list-title">$coupon->coupon_end_date</td>
        </tr>

COUPON_HTML;
        }
        return <<<COUPON_TABLE

        <table class="category table table-striped table-bordered table-hover">
            <thead>
                <tr>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_SYSTEM'))}</th>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_DESCRIPTION'))}</th>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_CODE'))}</th>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_TYPE'))}</th>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_VALUE'))}</th>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_USE_BEFORE'))}</th>
               </tr>
            </thead>
            <tbody>
                $coupon_html
            </tbody>
        </table>
        {$this->getPurchaseOptionsHtml()}

COUPON_TABLE;
    }

    protected function getPurchaseOptionsHtml() {
        $html = <<<OPTIONS_HTML

        <div class="coupon-purchase-options mt-4">
            <h3>{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_AVAILABLE_COUPONS'))}</h3>
            <table class="category table table-striped table-bordered table-hover">
                <thead>
                    <tr>
                        <th>{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_DESCRIPTION'))}</th>
                        <th>{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_TYPE'))}</th>
                        <th>{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_VALUE'))}</th>
                        <th>{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_POINTS_REQUIRED'))}</th>
                        <th>{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_ACTION'))}</th>
                    </tr>
                </thead>
                <tbody>

OPTIONS_HTML;

        // Get current site URL
        $uri = Uri::getInstance();
        $baseUrl = $uri->toString(array('scheme', 'host', 'port'));

        // Loop through the four coupon options
        for ($i = 1; $i <= 4; $i++) {
            $id = $this->params->get('coupon' . $i . '_id');
            $type = $this->params->get('coupon' . $i . '_type');
            $value = $this->params->get('coupon' . $i . '_value');
            $points = $this->params->get('coupon' . $i . '_points');

            // Only show if all values are set
            if ($id && $type && $value && $points) {
                $typeText = ($type == 'P') ? Text::_('PLG_ESHOP_USERPOINTS_PERCENT') : Text::_('PLG_ESHOP_USERPOINTS_FIXED');
                $valueText = ($type == 'P') ? $value . '%' : number_format($value, 2);
                $description = ($type == 'P') ?
                    Text::_('PLG_ESHOP_USERPOINTS_PERCENT_DISCOUNT') :
                    Text::_('PLG_ESHOP_USERPOINTS_FIXED_DISCOUNT');

                // Build purchase URL
                $purchaseUrl = $baseUrl .
                    '/index.php?option=com_userpoints&view=Plugin&trigger=onBuyEshopCoupon&redirect=Account&pointitem=' .
                    urlencode($id);
                $html .= <<<PURCHASE_OPTION

                <tr>
                    <td>{$this->showtext(htmlspecialchars($description))}</td>
                    <td>{$this->showtext(htmlspecialchars($typeText))}</td>
                    <td>{$this->showtext(htmlspecialchars($valueText))}</td>
                    <td>{$this->showtext(htmlspecialchars($points))}</td>
                    <td>
                        <a href="{$this->showtext(htmlspecialchars($purchaseUrl))}"
                           class="btn btn-primary btn-sm">
                            {$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_PURCHASE_WITH_POINTS'))}
                        </a>
                    </td>
                </tr>

PURCHASE_OPTION;
            }
        }

        $html .= '</tbody></table></div>';

        return $html;
    }

    public function onGetMyReviews() {
        if (!class_exists(UserPoints::class)) {
            Factory::getApplication()->enqueueMessage(Text::_('PLG_ESHOP_USERPOINTS_ERROR_LOADING_USERPOINTS'), 'error');
            return false;
        }
        $rule = Rule::withRuleName('up_eshop_review');
        if (!$rule->published) {
            return false;
        }
        $user = UserPoints::getUser();
        // Get database connection
        $db = SQL::getInstance();
        // Get reviews
        $query = "SELECT r.id, published, created_date, product_name, email FROM `#__eshop_reviews` AS r "
            . " INNER JOIN `#__eshop_productdetails` AS d on r.product_id = d.product_id "
            . " WHERE `email` = {$db->quote($user->email)}";
        $reviews = (array) $db->setQuery($query)->loadObjectList();
        if ($rule->published) {
            foreach ($reviews as $review) {
                if ($review->published) {
                    $keyreference = UserPoints::buildKeyreference($rule->plugin_function, "$review->id.$review->email");
                    UserPoints::newpoints($rule->plugin_function, '', $keyreference);
                }
            }
        }
        $review_html = '';
        foreach ($reviews as $review) {
            $published = $review->published ? Text::_('JYES') : Text::_('JNO');
            $review_html .= <<<REVIEW_HTML

        <tr>
            <td headers="categorylist_header_title" class="list-title">EShop</td>
            <td headers="categorylist_header_title" class="list-title">$review->created_date</td>
            <td headers="categorylist_header_title" class="list-title">$review->product_name</td>
            <td headers="categorylist_header_title" class="list-title">$published</td>
        </tr>

REVIEW_HTML;
        }
        return <<<REVIEW_TABLE

        <table class="category table table-striped table-bordered table-hover">
            <thead>
                <tr>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_SYSTEM'))}</th>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_DATE_REVIEWED'))}</th>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_REVIEW_NAME'))}</th>
                    <th id="categorylist_header_id">{$this->showtext(Text::_('PLG_ESHOP_USERPOINTS_PUBLISHED'))}</th>
               </tr>
            </thead>
            <tbody>
                $review_html
            </tbody>
        </table>

REVIEW_TABLE;
    }

    public function onBuyEshopCoupon() {
        // Exit if UserPoints class doesn't exist
        if (!class_exists(UserPoints::class)) {
            Factory::getApplication()->enqueueMessage(Text::_('PLG_ESHOP_USERPOINTS_ERROR_LOADING_USERPOINTS'), 'error');
            return false;
        }

        $app = Factory::getApplication();
        $user = UserPoints::getUser();
        $pointitem = $app->input->getString('pointitem', '');

        try {
            // Get the coupon configuration matching this ID
            $couponConfig = $this->getCouponConfig($pointitem);
            if (!$couponConfig) {
                throw new Exception(Text::_('PLG_ESHOP_USERPOINTS_INVALID_COUPON_CONFIG'));
            }

            // Try to deduct points using UserPoints API
            if (!UserPoints::newpoints('up_eshop_buypoints', '', '', '', -$couponConfig->points)) {
                throw new Exception(Text::_('PLG_ESHOP_USERPOINTS_POINTS_DEDUCTION_ERROR'));
            }

            // Create coupon in EShop
            $this->createEshopCoupon($couponConfig, $user->id);

            $app->enqueueMessage(Text::_('PLG_ESHOP_USERPOINTS_COUPON_CREATED'));
        } catch (Exception $e) {
            $app->enqueueMessage($e->getMessage(), 'error');
        }

        // Redirect back
        $redirect = $app->input->get('redirect', 'Account');
        $app->redirect("index.php?option=com_userpoints&view=$redirect");
    }

    protected function getCouponConfig($pointitem) {
        // Check each coupon configuration for matching ID
        for ($i = 1; $i <= 4; $i++) {
            $id = $this->params->get('coupon' . $i . '_id');
            if ($id === $pointitem) {
                return (object) [
                        'id' => $id,
                        'type' => $this->params->get('coupon' . $i . '_type'),
                        'value' => $this->params->get('coupon' . $i . '_value'),
                        'points' => $this->params->get('coupon' . $i . '_points')
                ];
            }
        }
        return null;
    }

    protected function createEshopCoupon($config, $userId) {
        $db = SQL::getInstance();

        // Generate unique coupon code
        $code = $this->generateCouponCode();

        // Set expiry date to 1 year from now
        $validTo = Factory::getDate('now +1 year')->toSql();
        $validFrom = Factory::getDate('now -1 day')->toSql();
        $today = Factory::getDate()->toSql();

        // Create new coupon record
        $coupon = new stdClass();
        $coupon->coupon_name = Text::_('PLG_ESHOP_USERPOINTS_COUPON_FROM_POINTS');
        $coupon->coupon_code = $code;
        $coupon->coupon_type = $config->type;
        $coupon->coupon_value = $config->value;
        $coupon->coupon_min_total = 0.0;
        $coupon->coupon_start_date = $validFrom;
        $coupon->coupon_end_date = $validTo;
        $coupon->coupon_times = 1;
        $coupon->coupon_used = 0;
        $coupon->coupon_per_customer = 1;
        $coupon->published = 1;
        $coupon->created_date = $today;
        $coupon->created_by = $userId;
        $coupon->modified_date = $today;
        $coupon->modified_by = $userId;
        $coupon->checked_out = 0;

        // Insert the coupon
        $db->insertObject('#__eshop_coupons', $coupon);

        // return $db->insertid();
    }

    protected function generateCouponCode($length = 8) {
        $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $code = '';

        do {
            $code = '';
            for ($i = 0; $i < $length; $i++) {
                $code .= $characters[rand(0, strlen($characters) - 1)];
            }

            // Check if code already exists
            $db = SQL::getInstance();
            $query = $db->getQuery(true)
                ->select('COUNT(*)')
                ->from('#__eshop_coupons')
                ->where('coupon_code = ' . $db->quote($code));

            $db->setQuery($query);
        } while ($db->loadResult() > 0);

        return $code;
    }

    private function showtext(string $text): string {
        return $text;
    }
}
