<?php
/**
 * Transaction Repository.
 *
 * All read/write operations against wp_tc_payment_transactions.
 * Concrete gateway classes use AbstractGateway::log_transaction() which
 * calls this class internally; direct access is reserved for admin queries.
 *
 * @package TitanCart\Modules\Payments
 */

namespace TitanCart\Modules\Payments;

use TitanCart\DB\Database;

defined( 'ABSPATH' ) || exit;

class TransactionRepository {

    private Database $db;

    public function __construct() {
        $this->db = titancart_db();
    }

    // ══════════════════════════════════════════════════════════════════════════
    // READ
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * Get all transactions for a specific order.
     *
     * @param  int $order_id
     * @return array
     */
    public function get_for_order( int $order_id ): array {
        return $this->db->getArray(
            "SELECT * FROM {$this->db->table('payment_transactions')}
             WHERE order_id = ?i
             ORDER BY created_at ASC",
            $order_id
        );
    }

    /**
     * Find a transaction row by the gateway's own transaction ID.
     *
     * @param  string $transaction_id  External ID (e.g. Stripe PaymentIntent ID).
     * @param  string $gateway         Gateway slug for disambiguation.
     * @return array|null
     */
    public function get_by_transaction_id( string $transaction_id, string $gateway = '' ): ?array {
        if ( $gateway ) {
            return $this->db->getRow(
                "SELECT * FROM {$this->db->table('payment_transactions')}
                 WHERE transaction_id = ?s AND gateway = ?s
                 ORDER BY id DESC LIMIT 1",
                $transaction_id,
                $gateway
            );
        }

        return $this->db->getRow(
            "SELECT * FROM {$this->db->table('payment_transactions')}
             WHERE transaction_id = ?s
             ORDER BY id DESC LIMIT 1",
            $transaction_id
        );
    }

    /**
     * Get the most recent completed charge for an order (used to determine
     * the transaction ID to pass to a refund).
     *
     * @param  int $order_id
     * @return array|null
     */
    public function get_latest_charge( int $order_id ): ?array {
        return $this->db->getRow(
            "SELECT * FROM {$this->db->table('payment_transactions')}
             WHERE order_id = ?i AND type = 'charge' AND status = 'completed'
             ORDER BY id DESC LIMIT 1",
            $order_id
        );
    }

    // ══════════════════════════════════════════════════════════════════════════
    // WRITE
    // ══════════════════════════════════════════════════════════════════════════

    /**
     * Insert a new transaction row.
     *
     * @param  array $data  Column → value pairs.
     * @return int  New row ID, 0 on failure.
     */
    public function create( array $data ): int {
        return $this->db->insert( 'payment_transactions', [
            'order_id'          => (int) $data['order_id'],
            'payment_method_id' => isset( $data['payment_method_id'] ) ? (int) $data['payment_method_id'] : null,
            'gateway'           => sanitize_key( $data['gateway'] ),
            'transaction_id'    => sanitize_text_field( $data['transaction_id'] ?? '' ),
            'amount'            => (float) ( $data['amount'] ?? 0 ),
            'currency'          => strtoupper( substr( $data['currency'] ?? 'USD', 0, 3 ) ),
            'type'              => in_array( $data['type'] ?? '', [ 'charge', 'refund', 'void', 'authorize', 'capture' ], true )
                                        ? $data['type']
                                        : 'charge',
            'status'            => in_array( $data['status'] ?? '', [ 'pending', 'completed', 'failed', 'refunded', 'voided' ], true )
                                        ? $data['status']
                                        : 'pending',
            'gateway_response'  => wp_json_encode( $data['gateway_response'] ?? [] ),
        ] );
    }

    /**
     * Update a transaction's status and optionally its gateway_response.
     *
     * @param  int    $row_id            The tc_payment_transactions.id.
     * @param  string $status            New status.
     * @param  array  $gateway_response  Updated raw response (optional).
     */
    public function update_status( int $row_id, string $status, array $gateway_response = [] ): void {
        $fields = [ 'status' => $status ];
        if ( $gateway_response ) {
            $fields['gateway_response'] = wp_json_encode( $gateway_response );
        }
        $this->db->update( 'payment_transactions', $fields, [ 'id' => $row_id ] );
    }
}
