<?php
namespace Bot\Commands\AdminCommands;

use Bot\Database;
use Bot\Localization;
use Bot\Services\OrderService;
use Bot\Services\StateService;
use Longman\TelegramBot\Commands\AdminCommand;
use Longman\TelegramBot\Entities\ServerResponse;
use Longman\TelegramBot\Request;
use PDO;

class AdminordersCommand extends AdminCommand
{
    protected $name = 'adminorders';
    protected $description = 'Review buy orders and payment proofs';
    protected $usage = '/adminorders pending';
    protected $version = '1.0.0';

    private OrderService $orderService;
    private StateService $stateService;
    private PDO $pdo;

    public function __construct($telegram, $update)
    {
        parent::__construct($telegram, $update);
        $this->orderService = new OrderService();
        $this->stateService = new StateService();
        $this->pdo = Database::connection();
    }

    public function execute(): ServerResponse
    {
        $message = $this->getMessage();
        $text = trim($message->getText(true) ?? '');
        if ($text === '') {
            return $this->replyUsage();
        }
        [$command, $payload] = array_pad(explode(' ', $text, 2), 2, '');
        $command = strtolower($command);
        return match ($command) {
            'pending',
            'list'    => $this->handleList(),
            'showall' => $this->handleShowAll(),
            'approve' => $this->handleApprove($payload),
            'reject'  => $this->handleReject($payload),
            'ask'     => $this->handleAsk($payload),
            'view'    => $this->handleView($payload),
            default   => $this->replyUsage(),
        };
    }

    private function handleList(): ServerResponse
    {
        $stmt = $this->pdo->query(
            "SELECT id, user_id, amount, currency, payment_status, payment_method_snapshot, type
             FROM orders
             WHERE payment_status IN ('waiting_proof','under_review','awaiting_txid','awaiting_crypto_confirm')
             ORDER BY id ASC"
        );
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        if (!$rows) {
            return $this->sendAdminReply('No pending orders.');
        }
        $lines = [];
        foreach ($rows as $row) {
            $lines[] = sprintf(
                '#%d %s user:%d %s %s status:%s via %s',
                $row['id'],
                strtoupper($row['type']),
                $row['user_id'],
                number_format($row['amount'], 2),
                strtoupper($row['currency']),
                $row['payment_status'],
                $row['payment_method_snapshot'] ?? 'N/A'
            );
        }
        return $this->sendAdminReply(implode("\n", $lines));
    }

    private function handleShowAll(): ServerResponse
    {
        $stmt = $this->pdo->query(
            "SELECT id, user_id, amount, currency, status, payment_status
             FROM orders
             WHERE status <> 'completed'
             ORDER BY id DESC
             LIMIT 20"
        );
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        if (!$rows) {
            return $this->sendAdminReply('No open orders.');
        }
        $lines = [];
        foreach ($rows as $row) {
            $lines[] = sprintf(
                '#%d user:%d %s %s order:%s payment:%s',
                $row['id'],
                $row['user_id'],
                number_format($row['amount'], 2),
                strtoupper($row['currency']),
                $row['status'],
                $row['payment_status']
            );
        }
        return $this->sendAdminReply(implode("\n", $lines));
    }

    private function handleApprove(string $payload): ServerResponse
    {
        $orderId = trim($payload);
        if (!ctype_digit($orderId)) {
            return $this->sendAdminReply('Usage: `/adminorders approve <order_id>` ');
        }
        $order = $this->getOrderWithUser((int) $orderId);
        if (!$order) {
            return $this->sendAdminReply('😏Order not found.');
        }
        $this->orderService->updatePaymentStatus((int) $orderId, 'approved');
        $this->notifyUser(
            $order,
            Localization::t($order['language'], 'payment_approved_message', [$orderId])
        );
        return $this->sendAdminReply("✅ Order #{$orderId} approved.");
    }

    private function handleReject(string $payload): ServerResponse
    {
        [$orderId, $reason] = array_map('trim', explode(' ', $payload, 2) + ['', '']);
        if (!ctype_digit($orderId) || $reason === '') {
            return $this->sendAdminReply('Usage: `/adminorders reject <order_id> <reason>` ');
        }
        $order = $this->getOrderWithUser((int) $orderId);
        if (!$order) {
            return $this->sendAdminReply('😏Order not found.');
        }
        $this->orderService->updatePaymentStatus((int) $orderId, 'rejected', $reason);
        $this->stateService->setState((int) $order['user_id'], 'await_payment_proof', ['order_id' => (int) $orderId]);
        $this->notifyUser(
            $order,
            Localization::t($order['language'], 'payment_rejected_reason', [$reason])
        );
        return $this->sendAdminReply("😢 Order #{$orderId} marked as rejected.");
    }

    private function handleAsk(string $payload): ServerResponse
    {
        [$orderId, $question] = array_map('trim', explode(' ', $payload, 2) + ['', '']);
        if (!ctype_digit($orderId) || $question === '') {
            return $this->sendAdminReply('Usage: `/adminorders ask <order_id> <question>` ');
        }
        $order = $this->getOrderWithUser((int) $orderId);
        if (!$order) {
            return $this->sendAdminReply('😏Order not found.');
        }
        $stmt = $this->pdo->prepare(
            'INSERT INTO admin_messages (order_id, admin_id, question, status, created_at) VALUES (?, ?, ?, ?, NOW())'
        );
        $stmt->execute([
            (int) $orderId,
            $this->getMessage()->getFrom()->getId(),
            $question,
            'open',
        ]);
        $adminMessageId = (int) $this->pdo->lastInsertId();
        $this->stateService->setState(
            (int) $order['user_id'],
            'await_admin_response',
            ['admin_message_id' => $adminMessageId]
        );
        $this->notifyUser(
            $order,
            Localization::t($order['language'], 'admin_question_from_ops', [$question])
        );
        return $this->sendAdminReply('✅ Question sent to the user.');
    }

    private function handleView(string $payload): ServerResponse
    {
        $orderId = trim($payload);
        if (!ctype_digit($orderId)) {
            return $this->sendAdminReply('Usage: `/adminorders view <order_id>` ');
        }
        $order = $this->getOrderWithUser((int) $orderId);
        if (!$order) {
            return $this->sendAdminReply('😏Order not found.');
        }
        if (empty($order['payment_proof_file_id'])) {
            return $this->sendAdminReply('🔪No payment proof uploaded for this order.');
        }
        $caption = sprintf(
            "🔢 Order #%d\n💲 Amount: %s %s\n🫆 Status: %s\n📄 Instructions:\n%s",
            $order['id'],
            number_format($order['amount'], 2),
            strtoupper($order['currency']),
            $order['payment_status'],
            $order['payment_instructions'] ?? ''
        );
        if (!empty($order['payout_details'])) {
            $caption .= sprintf("\n🏧 Payout: %s", $order['payout_details']);
        }
        if (!empty($order['crypto_network'])) {
            $caption .= sprintf(
                "\n🌐 Network: %s\n💼 Admin wallet: %s\n🔁 TXID: %s",
                $order['crypto_network'],
                $order['crypto_deposit_address'] ?? 'N/A',
                $order['txid'] ?? 'N/A'
            );
        }
        if ($order['payment_proof_type'] === 'document') {
            Request::sendDocument([
                'chat_id'  => $this->getMessage()->getChat()->getId(),
                'document' => $order['payment_proof_file_id'],
                'caption'  => $caption,
            ]);
        } else {
            Request::sendPhoto([
                'chat_id' => $this->getMessage()->getChat()->getId(),
                'photo'   => $order['payment_proof_file_id'],
                'caption' => $caption,
            ]);
        }
        return $this->sendAdminReply('Proof preview sent above.');
    }

    private function getOrderWithUser(int $orderId): ?array
    {
        $stmt = $this->pdo->prepare(
            'SELECT o.*, u.telegram_id, u.language
             FROM orders o
             JOIN users u ON u.id = o.user_id
             WHERE o.id = ?'
        );
        $stmt->execute([$orderId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row ?: null;
    }

    private function notifyUser(array $order, string $text): void
    {
        if (empty($order['telegram_id'])) {
            return;
        }
        Request::sendMessage([
            'chat_id' => $order['telegram_id'],
            'text'    => $text,
        ]);
    }

    private function replyUsage(): ServerResponse
    {
        $text = "Order review commands:\n" .
            " `/adminorders list`        (waiting proof / under review)\n" .
            " `/adminorders showall`     (recent non-completed)\n" .
            " `/adminorders approve <order_id>` \n" .
            " `/adminorders reject <order_id> <reason>` \n" .
            " `/adminorders ask <order_id> <question>` \n" .
            " `/adminorders view <order_id>` ";
        return $this->sendAdminReply($text);
    }

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