<?php
namespace Bot\Commands\AdminCommands;

use Bot\Database;
use Bot\Services\AdminActivityService;
use Bot\Services\ReferralService;
use Bot\Services\SettingService;
use Longman\TelegramBot\Commands\AdminCommand;
use Longman\TelegramBot\Entities\ServerResponse;
use Longman\TelegramBot\Request;

class AdminreferralCommand extends AdminCommand
{
    protected $name = 'adminreferral';
    protected $description = 'Manage referral settings and levels';
    protected $usage = '/adminreferral set rate 0.01';
    protected $version = '1.0.0';

    private SettingService $settings;
    private ReferralService $referrals;
    private AdminActivityService $activity;

    public function __construct($telegram, $update)
    {
        parent::__construct($telegram, $update);
        $this->settings = new SettingService();
        $this->referrals = new ReferralService();
        $this->activity = new AdminActivityService();
    }

    public function execute(): ServerResponse
    {
        $message = $this->getMessage();
        $chatId = $message->getChat()->getId();
        $text = trim($message->getText(true) ?? '');
        if ($text === '') {
            return $this->replyUsage();
        }
        [$command, $payload] = array_pad(explode(' ', $text, 2), 2, '');
        $command = strtolower($command);
        return match ($command) {
            'set'     => $this->handleSet($payload),
            'levels'  => $this->handleLevels($payload),
            'recalc'  => $this->handleRecalc($payload),
            default   => $this->replyUsage(),
        };
    }

    private function replyUsage(): ServerResponse
    {
        $text = "Referral commands:\n"
            . " `/adminreferral set rate <points_per_usd>`\n"
            . " `/adminreferral set kyc_points <points>`\n"
            . " `/adminreferral set trade_points <points>`\n"
            . " `/adminreferral levels list`\n"
            . " `/adminreferral levels add <name>|<min_verified>|<min_volume>|<multiplier>|[bonus]`\n"
            . " `/adminreferral levels delete <name>`\n"
            . " `/adminreferral recalc [user_id]`";
        return $this->sendReply($text);
    }

    private function handleSet(string $payload): ServerResponse
    {
        [$key, $value] = array_map('trim', explode(' ', $payload, 2) + ['', '']);
        if ($key === '' || $value === '' || !is_numeric($value)) {
            return $this->sendReply('Usage: `/adminreferral set <rate|kyc_points|trade_points> <value>`');
        }
        $map = [
            'rate'        => 'referral_point_rate',
            'kyc_points'  => 'referral_kyc_points',
            'trade_points'=> 'referral_trade_points',
        ];
        if (!isset($map[$key])) {
            return $this->sendReply('Unknown setting. Use rate, kyc_points, or trade_points.');
        }
        $this->settings->set($map[$key], $value);
        $this->activity->log(
            (int) $this->getMessage()->getFrom()->getId(),
            'referral_set',
            null,
            ['key' => $map[$key], 'value' => $value]
        );
        return $this->sendReply('Updated setting.');
    }

    private function handleLevels(string $payload): ServerResponse
    {
        [$sub, $rest] = array_map('trim', explode(' ', $payload, 2) + ['', '']);
        $sub = strtolower($sub);
        return match ($sub) {
            'list'  => $this->listLevels(),
            'add'   => $this->addLevel($rest),
            'delete'=> $this->deleteLevel($rest),
            default => $this->sendReply('Usage: `/adminreferral levels list|add|delete`'),
        };
    }

    private function listLevels(): ServerResponse
    {
        $levels = $this->referrals->listLevels();
        if (!$levels) {
            return $this->sendReply('No referral levels configured.');
        }
        $lines = [];
        foreach ($levels as $level) {
            $lines[] = sprintf(
                "%s — min verified %d, min volume %s, multiplier x%s",
                $level['level_name'],
                $level['min_verified'],
                $level['min_volume'],
                $level['multiplier']
            );
        }
        return $this->sendReply(implode("\n", $lines));
    }

    private function addLevel(string $payload): ServerResponse
    {
        $parts = explode('|', $payload);
        if (count($parts) < 4) {
            return $this->sendReply('Usage: `/adminreferral levels add Name|min_verified|min_volume|multiplier|[bonus]`');
        }
        [$name, $minVerified, $minVolume, $multiplier, $bonus] = array_map('trim', $parts + ['', '', '', '', '0']);
        if ($name === '' || !is_numeric($minVerified) || !is_numeric($minVolume) || !is_numeric($multiplier)) {
            return $this->sendReply('Invalid level parameters.');
        }
        $this->referrals->upsertLevel(
            $name,
            (int) $minVerified,
            (float) $minVolume,
            (float) $multiplier,
            (float) $bonus
        );
        $this->activity->log(
            (int) $this->getMessage()->getFrom()->getId(),
            'referral_level_upsert',
            null,
            ['name' => $name]
        );
        return $this->sendReply('Level saved.');
    }

    private function deleteLevel(string $name): ServerResponse
    {
        $name = trim($name);
        if ($name === '') {
            return $this->sendReply('Usage: `/adminreferral levels delete <name>`');
        }
        $this->referrals->deleteLevel($name);
        $this->activity->log(
            (int) $this->getMessage()->getFrom()->getId(),
            'referral_level_delete',
            null,
            ['name' => $name]
        );
        return $this->sendReply('Level deleted.');
    }

    private function handleRecalc(string $payload): ServerResponse
    {
        $payload = trim($payload);
        if ($payload === '') {
            $stmt = Database::connection()->query('SELECT id FROM users WHERE referrer_id IS NOT NULL');
            $ids = $stmt->fetchAll(\PDO::FETCH_COLUMN);
            foreach ($ids as $id) {
                $this->referrals->recalculateLevel((int) $id);
            }
            return $this->sendReply('Recalculated referral levels for all referrers.');
        }
        if (!ctype_digit($payload)) {
            return $this->sendReply('Usage: `/adminreferral recalc [user_id]`');
        }
        $this->referrals->recalculateLevel((int) $payload);
        return $this->sendReply('Level recalculated.');
    }

    private function sendReply(string $text): ServerResponse
    {
        return Request::sendMessage([
            'chat_id' => $this->getMessage()->getChat()->getId(),
            'text'    => $text,
        ]);
    }
}
