<?php
declare(strict_types=1);

require_once __DIR__ . '/../config/database.php';

class Order
{
    public function create(array $payload): int
    {
        $stmt = db()->prepare(
            'INSERT INTO orders (order_tracking_id, customer_name,customer_phone,customer_address,total_amount,status,payment_status,payment_ref,payment_authority,gateway,tracking_code,shipping_amount,discount_amount)
             VALUES (:order_tracking_id, :customer_name,:customer_phone,:customer_address,:total_amount,:status,:payment_status,:payment_ref,:payment_authority,:gateway,:tracking_code,:shipping_amount,:discount_amount)'
        );
        $stmt->execute($payload);
        return (int)db()->lastInsertId();
    }

    public function addItem(int $orderId, array $item): bool
    {
        $stmt = db()->prepare(
            'INSERT INTO order_items (order_id,product_id,product_tracking_code,product_title,quantity,price)
             VALUES (:order_id,:product_id,:product_tracking_code,:product_title,:quantity,:price)'
        );
        return $stmt->execute([
            'order_id' => $orderId,
            'product_id' => $item['product_id'],
            'product_tracking_code' => $item['product_tracking_code'] ?? null,
            'product_title' => $item['product_title'],
            'quantity' => $item['quantity'],
            'price' => $item['price'],
        ]);
    }

    public function latest(int $limit = 20): array
    {
        $stmt = db()->prepare('SELECT * FROM orders ORDER BY id DESC LIMIT :lim');
        $stmt->bindValue(':lim', $limit, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll();
    }

    public function find(int $orderId): ?array
    {
        $stmt = db()->prepare('SELECT * FROM orders WHERE id = :id LIMIT 1');
        $stmt->execute(['id' => $orderId]);
        $row = $stmt->fetch();
        return $row ?: null;
    }

    public function findByAuthority(string $authority): ?array
    {
        $stmt = db()->prepare('SELECT * FROM orders WHERE payment_authority = :authority LIMIT 1');
        $stmt->execute(['authority' => $authority]);
        $row = $stmt->fetch();
        return $row ?: null;
    }

    public function findByPublicTracking(string $trackingId, string $phone): ?array
    {
        $stmt = db()->prepare(
            'SELECT * FROM orders WHERE order_tracking_id = :tid AND customer_phone = :phone LIMIT 1'
        );
        $stmt->execute(['tid' => $trackingId, 'phone' => $phone]);
        $row = $stmt->fetch();
        return $row ?: null;
    }

    public function markAuthority(int $orderId, string $authority): void
    {
        $stmt = db()->prepare('UPDATE orders SET payment_authority = :authority WHERE id = :id');
        $stmt->execute([
            'authority' => $authority,
            'id' => $orderId,
        ]);
    }

    public function markPaid(int $orderId, string $refId, string $authority): void
    {
        $stmt = db()->prepare('UPDATE orders SET payment_status = :payment_status, status = :status, payment_ref = :payment_ref, payment_authority = :authority WHERE id = :id');
        $stmt->execute([
            'payment_status' => 'paid',
            'status' => 'paid',
            'payment_ref' => $refId,
            'authority' => $authority,
            'id' => $orderId,
        ]);
    }

    public function markFailed(int $orderId, string $reason, ?string $authority = null): void
    {
        $stmt = db()->prepare('UPDATE orders SET payment_status = :payment_status, status = :status, payment_ref = :payment_ref, payment_authority = COALESCE(:authority,payment_authority) WHERE id = :id');
        $stmt->execute([
            'payment_status' => 'failed',
            'status' => 'failed',
            'payment_ref' => $reason,
            'authority' => $authority,
            'id' => $orderId,
        ]);
    }

    public function items(int $orderId): array
    {
        $stmt = db()->prepare('SELECT * FROM order_items WHERE order_id = :order_id ORDER BY id ASC');
        $stmt->execute(['order_id' => $orderId]);
        return $stmt->fetchAll();
    }

    public function updateStatus(int $orderId, string $status, ?string $trackingCode = null): void
    {
        $stmt = db()->prepare('UPDATE orders SET status = :status, tracking_code = COALESCE(:tracking_code, tracking_code) WHERE id = :id');
        $stmt->execute([
            'status' => $status,
            'tracking_code' => $trackingCode,
            'id' => $orderId,
        ]);
    }

    public function findForTracking(int $orderId, string $phone): ?array
    {
        $stmt = db()->prepare('SELECT * FROM orders WHERE id = :id AND customer_phone = :phone LIMIT 1');
        $stmt->execute([
            'id' => $orderId,
            'phone' => $phone,
        ]);
        $row = $stmt->fetch();
        return $row ?: null;
    }
}
