<?php

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

namespace BlackSheepResearch\Component\UserPoints\Site\Problems;

defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use BlackSheepResearch\Component\UserPoints\Site\UserPoints;
use BlackSheepResearch\Component\UserPoints\Site\Problems\SQL;

class PointsDetails extends ProblemBase {

    protected static $fieldnames = [];
    protected static $fieldtypes = [];
    protected static $count = -1;
    protected static $details = [];
    protected static $tablename = '#__alpha_userpoints_details_combined';
    protected static $updatetable = '#__alpha_userpoints_details';
    protected static $keyname = 'id';

    public function __construct(int $id = 0) {
        parent::__construct();
        if ($id) {
            if (!isset(self::$details[$id])) {
                $this->getByID($id);
            }
            if (isset(self::$details[$id])) {
                $this->problem_object = self::$details[$id];
            }
        }
    }

    private function getByID(int $id) {
        $db = SQL::getInstance();
        $table = self::$tablename;
        $db->setQuery("SELECT * FROM `$table` WHERE `id`= $id");
        self::$details[$id] = $db->loadObject();
    }

    public function disable() {
        if (is_object($this->problem_object)) {
            $this->enabled = 0;
            $this->save();
        }
    }

    public function setPointsWithMax(string $referrerid, float $points) {
        $userpoints = PointsUser::withReferrerID($referrerid)->points;
        $max_points = intval(ComponentHelper::getParams('com_userpoints')->get('maximum_points', 0));
        $this->points = $max_points ? min($points, $max_points - $userpoints) : $points;
    }

    public function dataFromRule($rule, string $referrerid, float $referraluserpoints = 0.0) {
        $this->setPointsWithMax($referrerid, $referraluserpoints > 0.0 ? $referraluserpoints : $rule->points);
        $this->expire_date = UserPoints::checkRuleExpireDate($rule->rule_expire, $rule->type_expire_date);
        $this->insert_date = SQL::datetimeSQL();
        $this->rule_id = $rule->plugin_function;
        $this->approved = $rule->autoapproved;
        $this->status = $rule->autoapproved;
    }

    public static function reset() {
        self::$details = [];
    }

    public static function deleteByReferrerID(string $referrerid) {
        $db = SQL::getInstance();
        $table = self::$updatetable;
        $db->setQuery("DELETE FROM `$table` WHERE referreid = {$db->quote($referrerid)}");
        $db->execute();
    }

    public static function countUnapproved(): int {
        $db = SQL::getInstance();
        $table = self::$updatetable;
        $db->setQuery("SELECT COUNT(*) FROM `$table` WHERE approved = 0 AND status = 0 AND enabled = 1");
        return $db->loadResult();
    }

    public static function getUnapproved(): array {
        $db = SQL::getInstance();
        $db->setQuery(sprintf("SELECT id AS cid, insert_date, referreid, points AS pendingapprovalpoints, rule_name, name , username "
                        . " FROM `%s` WHERE `approved` = 0 AND `status` = 0 AND `enabled` = 1  ORDER BY `insert_date` DESC", self::$tablename));
        return self::makeProblems($db->loadObjectList());
    }

    public static function totalPoints(int $sign): float {
        // If $sign is negative, total negative points; if positive all positive points; if zero all points
        $db = SQL::getInstance();
        $table = self::$updatetable;
        $query = "SELECT SUM(points) AS totalpoints FROM `$table` WHERE ";
        $where = ['approved = 1', 'enabled = 1', 'status = 1'];
        switch (true) {
            case $sign < 0:
                $where[] = 'points < 0.0';
                break;
            case $sign > 0:
                $where[] = 'points > 0.0';
                break;
        }
        $query .= implode(' AND ', $where);
        $db->setQuery($query);
        return (float) $db->loadResult();
    }

    public static function dailyPlusPoints(string $referrerid): float {
        $db = SQL::getInstance();
        // select only positive points earned per day
        $db->setQuery(sprintf("SELECT SUM(points) FROM `%s` WHERE `referreid` = %s AND `points` > 0.0 "
                        . " AND `insert_date` LIKE '%s' AND `rule_id` != 'sysplgup_raffle' AND `enabled` != 0",
                        self::$tablename, $db->quote($referrerid), SQL::dateSQL() . '%'));
        return (float) $db->loadResult();
    }

    public static function getDateRange(): float {
        $db = SQL::getInstance();
        $query = sprintf("SELECT MIN(insert_date) AS firstdate, MAX(insert_date) AS lastdate FROM `%s` "
                . " WHERE approved = 1 AND status = 1 AND insert_date != '%s' AND enabled = 1", self::$updatetable, SQL::nulldatetimeSQL());
        $db->setQuery($query);
        $dates = $db->loadObject();
        if (!$dates) {
            return 0.0;
        }
        return floor(( strtotime($dates->lastdate) - strtotime($dates->firstdate)) / (60 * 60 * 24));
    }

    public static function setApproved(array $ids, bool $approved) {
        $db = SQL::getInstance();
        $db->setQuery(sprintf("UPDATE `%s` SET `approved` = %d WHERE id in (%s)",
                        self::$updatetable, $approved ? 1 : 0, self::listIDs($ids)));
    }

    public static function disableMany(array $ids) {
        $db = SQL::getInstance();
        $db->setQuery(sprintf("UPDATE `%s` SET `enabled` = 0 WHERE id IN (%s)", self::$updatetable, self::listIDs($ids)));
        $db->execute();
    }

    public static function disableExpired() {
        $db = SQL::getInstance();
        $query = sprintf("UPDATE `%s` SET enabled = 0 WHERE `expire_date` != '%s' AND `expire_date` <= '%s'", self::$updatetable, SQL::nulldatetimeSQL(), SQL::datetimeSQL());
        $db->setQuery($query);
        $db->execute();
    }
}
