<?php

/**
 * Copyright © Resurs Bank AB. All rights reserved.
 * See LICENSE for license details.
 */

declare(strict_types=1);

namespace Resursbank\MerchantApi\Repository;

use DateTime;
use Db;
use JsonException;
use PrestaShopDatabaseException;
use ReflectionException;
use Resursbank\Ecom\Exception\AttributeCombinationException;
use Resursbank\Ecom\Exception\Validation\IllegalTypeException;
use Resursbank\Ecom\Lib\Model\PaymentHistory\Event;
use Resursbank\Ecom\Lib\Model\PaymentHistory\Entry;
use Resursbank\Ecom\Lib\Model\PaymentHistory\EntryCollection;
use Resursbank\Ecom\Lib\Model\PaymentHistory\Result;
use Resursbank\Ecom\Lib\Model\PaymentHistory\User;

/**
 * Frontend repository implementation for payment history.
 */
class PaymentHistory
{
    public const TABLE_NAME = _DB_PREFIX_ . 'resursbank_payment_history';

    /**
     * Create a new payment history entry using simple SQL statement.
     *
     * @param int $resursbankOrderId
     * @param string $event
     * @param string $user
     * @param string|null $extra
     * @param string|null $statusFrom
     * @param string|null $statusTo
     * @param string|null $result
     * @param string|null $userReference
     * @return void
     */
    public static function create(
        int $resursbankOrderId,
        string $event,
        string $user,
        ?string $extra,
        ?string $statusFrom,
        ?string $statusTo,
        ?string $result,
        ?string $userReference
    ): void {
        $extra = $extra !== null ? "'$extra'" : 'NULL';
        $statusFrom = $statusFrom !== null ? "'$statusFrom'" : 'NULL';
        $statusTo = $statusTo !== null ? "'$statusTo'" : 'NULL';
        $result = $result !== null ? "'$result'" : 'NULL';
        $userReference = $userReference !== null ? "'$userReference'" : 'NULL';
        $createdAt = (new DateTime())->format('Y-m-d H:i:s');

        // Insert into [PREFIX]resursbank_payment_history table as raw query.
        $sql = "INSERT INTO " . self::TABLE_NAME . " (resursbank_order_id, event, user, extra, status_from, status_to, result, user_reference, created_at) VALUES ('$resursbankOrderId', '$event', '$user', $extra, $statusFrom, $statusTo, $result, $userReference, '$createdAt')";

        // Execute raw query.
        Db::getInstance()->execute(sql: $sql);
    }


    /**
     * Filter records from [PREFIX]resursbank_payment_history table using "resursbank_order_id" and "event".
     *
     * This will is used to give the complete history attached to a payment, or to check if a specific event has
     * occurred for a specific payment.
     *
     * @param string $mapiId
     * @param int $resursbankOrderId
     * @param Event|null $event
     *
     * @return EntryCollection
     * @throws AttributeCombinationException
     * @throws IllegalTypeException
     * @throws JsonException
     * @throws PrestaShopDatabaseException
     * @throws ReflectionException
     */
    public static function find(
        string $mapiId,
        int $resursbankOrderId,
        ?Event $event = null
    ): EntryCollection {
        //
        // Use Db to resolve data from history table.
        $sql = "SELECT * FROM " . self::TABLE_NAME . " WHERE resursbank_order_id = '$resursbankOrderId'";

        if (!is_null($event)) {
            $sql .= " AND event = '$event->value'";
        }

        $db = Db::getInstance();
        $data = $db->query(sql:$sql);

        // Convert raw SQL response to EntryCollection.
        $entries = [];

        foreach ($data as $row) {
            $entries[] = new Entry(
                paymentId: $mapiId,
                event: $row['event'] !== null ? Event::from($row['event']) : null,
                user: $row['user'] !== null ? User::from($row['user']) : null,
                time: strtotime($row['created_at']),
                result: $row['result'] !== null ? Result::from($row['result']) : null,
                extra: $row['extra'],
                previousOrderStatus: $row['status_from'],
                currentOrderStatus: $row['status_to'],
                reference: "# $resursbankOrderId",
                userReference: $row['user_reference']
            );
        }

        return new EntryCollection(data: $entries);
    }
}
