<?php
namespace Bot\Commands\AdminCommands;

use Bot\Services\RateService;
use Longman\TelegramBot\Commands\AdminCommand;
use Longman\TelegramBot\Entities\ServerResponse;
use Longman\TelegramBot\Request;
use Bot\Database;
use PDO;

class AdminratesCommand extends AdminCommand
{
    protected $name = 'adminrates';
    protected $description = 'Manage buy/sell rates and fees';
    protected $usage = '/adminrates set-rate USDT buy 109.50';
    protected $version = '1.0.0';

    private RateService $rateService;

    public function __construct($telegram, $update)
    {
        parent::__construct($telegram, $update);
        $this->rateService = new RateService();
    }

    public function execute(): ServerResponse
    {
        $message = $this->getMessage();
        $text = trim($message->getText(true) ?? '');
        if ($text === '') {
            return $this->replyUsage();
        }
        $parts = preg_split('/\s+/', $text);
        $command = strtolower(array_shift($parts));

        try {
            switch ($command) {
                case 'set-rate':
                    return $this->handleSetRate($parts);
                case 'set-fee':
                    return $this->handleSetFee($parts);
                case 'list':
                    return $this->handleList();
                default:
                    return $this->replyUsage();
            }
        } catch (\Throwable $e) {
            return Request::sendMessage([
                'chat_id' => $message->getChat()->getId(),
                'text'    => 'Error: ' . $e->getMessage(),
            ]);
        }
    }

    private function handleSetRate(array $parts): ServerResponse
    {
        if (count($parts) !== 3) {
            return $this->replyUsage();
        }
        [$currency, $side, $price] = $parts;
        $side = strtolower($side);
        if (!in_array($side, ['buy', 'sell'], true)) {
            throw new \InvalidArgumentException('Side must be buy or sell.');
        }
        $this->rateService->setRate($currency, $side, (float) $price);
        return Request::sendMessage([
            'chat_id' => $this->getMessage()->getChat()->getId(),
            'text'    => sprintf('Rate updated: %s %s = %.4f', strtoupper($currency), strtoupper($side), (float) $price),
        ]);
    }

    private function handleSetFee(array $parts): ServerResponse
    {
        if (count($parts) < 3) {
            return $this->replyUsage();
        }
        [$currency, $service, $network] = $parts;
        $this->rateService->setFees($currency, (float) $service, (float) $network);
        return Request::sendMessage([
            'chat_id' => $this->getMessage()->getChat()->getId(),
            'text'    => sprintf('Fees updated: %s service %.2f%% network %.4f', strtoupper($currency), (float) $service, (float) $network),
        ]);
    }

    private function handleList(): ServerResponse
    {
        $pdo = Database::connection();
        $stmt = $pdo->query(
            'SELECT r.currency, r.rate_buy, r.rate_sell, f.service_fee_percent, f.network_fee_flat
             FROM rates r
             LEFT JOIN fees f ON r.currency = f.currency
             ORDER BY r.currency'
        );
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        if (!$rows) {
            $text = 'No rates configured.';
        } else {
            $lines = [];
            foreach ($rows as $row) {
                $lines[] = sprintf(
                    '%s | buy %.4f | sell %.4f | fee %.2f%% | network %.4f',
                    $row['currency'],
                    $row['rate_buy'],
                    $row['rate_sell'],
                    $row['service_fee_percent'] ?? 0,
                    $row['network_fee_flat'] ?? 0
                );
            }
            $text = implode("\n", $lines);
        }
        return Request::sendMessage([
            'chat_id' => $this->getMessage()->getChat()->getId(),
            'text'    => $text,
        ]);
    }

    private function replyUsage(): ServerResponse
    {
        $help = "Usage:\n".
            " `/adminrates set-rate USDT buy 109.50` \n".
            " `/adminrates set-rate USDT sell 108.90` \n".
            " `/adminrates set-fee USDT 0.5 0.0` \n".
            " `/adminrates list` ";
        return Request::sendMessage([
            'chat_id' => $this->getMessage()->getChat()->getId(),
            'text'    => $help,
        ]);
    }
}
