<?php
namespace Domain\Order;

class OrderAdminService
{
    private OrderRepository $orders;

    public function __construct(OrderRepository $orders)
    {
        $this->orders = $orders;
    }

    public function details(int $orderId): array
    {
        return $this->orders->findForAdmin($orderId);
    }

    public function statuses(): array
    {
        return $this->orders->orderStatuses();
    }

    /**
     * @return array{items: array<int, array<string, mixed>>, total: int}
     */
    public function listForAdmin(
        array $filters,
        string $sortColumn = 'date_order',
        string $sortDir = 'DESC',
        int $page = 1,
        int $perPage = 15
    ): array {
        return $this->orders->listForAdmin($filters, $sortColumn, $sortDir, $page, $perPage);
    }

    public function nextOrderId(int $orderId): ?int
    {
        return $this->orders->nextOrderId($orderId);
    }

    public function prevOrderId(int $orderId): ?int
    {
        return $this->orders->prevOrderId($orderId);
    }

    public function saveNotes(int $orderId, string $notes): bool
    {
        return $this->orders->saveNotes($orderId, $notes);
    }

    public function saveOrderByAdmin(array $input): bool
    {
        $saved = $this->orders->saveOrderByAdmin(
            (int)($input['order_id'] ?? 0),
            (string)($input['client_name'] ?? ''),
            (string)($input['client_surname'] ?? ''),
            (string)($input['client_street'] ?? ''),
            (string)($input['client_postal_code'] ?? ''),
            (string)($input['client_city'] ?? ''),
            (string)($input['client_email'] ?? ''),
            (string)($input['firm_name'] ?? ''),
            (string)($input['firm_street'] ?? ''),
            (string)($input['firm_postal_code'] ?? ''),
            (string)($input['firm_city'] ?? ''),
            (string)($input['firm_nip'] ?? ''),
            (int)($input['transport_id'] ?? 0),
            (string)($input['inpost_paczkomat'] ?? ''),
            (int)($input['payment_method_id'] ?? 0)
        );

        return $saved;
    }

    public function changeStatus(int $orderId, int $status, bool $sendEmail): array
    {
        $order = new \shop\Order($orderId);
        $response = $order->update_status($status, $sendEmail ? 1 : 0);

        return is_array($response) ? $response : ['result' => false];
    }

    public function resendConfirmationEmail(int $orderId): bool
    {
        $order = new \shop\Order($orderId);

        return (bool)$order->order_resend_confirmation_email();
    }

    public function setOrderAsUnpaid(int $orderId): bool
    {
        $order = new \shop\Order($orderId);

        return (bool)$order->set_as_unpaid();
    }

    public function setOrderAsPaid(int $orderId, bool $sendMail): bool
    {
        $order = new \shop\Order($orderId);
        if (!$order->set_as_paid()) {
            return false;
        }

        $order->update_status(4, $sendMail ? 1 : 0);

        return true;
    }

    public function sendOrderToApilo(int $orderId): bool
    {
        global $mdb;

        if ($orderId <= 0) {
            return false;
        }

        $order = $this->orders->findForAdmin($orderId);
        if (empty($order) || empty($order['apilo_order_id'])) {
            return false;
        }

        $integrationsRepository = new \Domain\Integrations\IntegrationsRepository( $mdb );
        $accessToken = $integrationsRepository -> apiloGetAccessToken();
        if (!$accessToken) {
            return false;
        }

        $newStatus = 8;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://projectpro.apilo.com/rest/api/orders/' . $order['apilo_order_id'] . '/status/');
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
            'id' => (int)$order['apilo_order_id'],
            'status' => (int)\front\factory\ShopStatuses::get_apilo_status_id($newStatus),
        ]));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $accessToken,
            'Accept: application/json',
            'Content-Type: application/json',
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $apiloResultRaw = curl_exec($ch);
        $apiloResult = json_decode((string)$apiloResultRaw, true);

        if (!is_array($apiloResult) || (int)($apiloResult['updates'] ?? 0) !== 1) {
            curl_close($ch);
            return false;
        }

        $query = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'pp_shop_orders' AND COLUMN_NAME != 'id'";
        $columns = $mdb->query($query)->fetchAll(\PDO::FETCH_COLUMN);
        $columnsList = implode(', ', $columns);
        $mdb->query('INSERT INTO pp_shop_orders (' . $columnsList . ') SELECT ' . $columnsList . ' FROM pp_shop_orders pso WHERE pso.id = ' . $orderId);
        $newOrderId = (int)$mdb->id();

        $query = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'pp_shop_order_products' AND COLUMN_NAME != 'id' AND COLUMN_NAME != 'order_id'";
        $columns = $mdb->query($query)->fetchAll(\PDO::FETCH_COLUMN);
        $columnsList = implode(', ', $columns);
        $mdb->query('INSERT INTO pp_shop_order_products (order_id, ' . $columnsList . ') SELECT ' . $newOrderId . ', ' . $columnsList . ' FROM pp_shop_order_products psop WHERE psop.order_id = ' . $orderId);

        $query = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'pp_shop_order_statuses' AND COLUMN_NAME != 'id' AND COLUMN_NAME != 'order_id'";
        $columns = $mdb->query($query)->fetchAll(\PDO::FETCH_COLUMN);
        $columnsList = implode(', ', $columns);
        $mdb->query('INSERT INTO pp_shop_order_statuses (order_id, ' . $columnsList . ') SELECT ' . $newOrderId . ', ' . $columnsList . ' FROM pp_shop_order_statuses psos WHERE psos.order_id = ' . $orderId);

        $mdb->delete('pp_shop_orders', ['id' => $orderId]);
        $mdb->delete('pp_shop_order_products', ['order_id' => $orderId]);
        $mdb->delete('pp_shop_order_statuses', ['order_id' => $orderId]);

        $mdb->update('pp_shop_orders', ['apilo_order_id' => null], ['id' => $newOrderId]);

        curl_close($ch);

        return true;
    }

    public function toggleTrustmateSend(int $orderId): array
    {
        $newValue = $this->orders->toggleTrustmateSend($orderId);
        if ($newValue === null) {
            return [
                'result' => false,
            ];
        }

        return [
            'result' => true,
            'trustmate_send' => $newValue,
        ];
    }

    public function deleteOrder(int $orderId): bool
    {
        return $this->orders->deleteOrder($orderId);
    }
}