<?php

declare(strict_types=1);

namespace App\Models;

use Core\Database;

final class VoucherModel
{
    private Database $db;

    public function __construct()
    {
        $this->db = Database::getInstance();
    }

    public function all(int $page = 1, int $perPage = ITEMS_PER_PAGE, array $filters = []): array
    {
        $offset = ($page - 1) * $perPage;
        $where  = ['1=1'];
        $params = [];

        if (!empty($filters['search'])) {
            $where[]  = '(v.code LIKE ? OR v.description LIKE ?)';
            $params[] = '%' . $filters['search'] . '%';
            $params[] = '%' . $filters['search'] . '%';
        }
        if (isset($filters['is_active']) && $filters['is_active'] !== '') {
            $where[]  = 'v.is_active = ?';
            $params[] = (int) $filters['is_active'];
        }

        $params[] = $perPage;
        $params[] = $offset;

        return $this->db->fetchAll(
            "SELECT v.*, u.name AS created_by_name
               FROM vouchers v
               LEFT JOIN users u ON u.id = v.created_by
              WHERE " . implode(' AND ', $where) . "
              ORDER BY v.created_at DESC
              LIMIT ? OFFSET ?",
            $params
        );
    }

    public function count(array $filters = []): int
    {
        $where  = ['1=1'];
        $params = [];

        if (!empty($filters['search'])) {
            $where[]  = '(code LIKE ? OR description LIKE ?)';
            $params[] = '%' . $filters['search'] . '%';
            $params[] = '%' . $filters['search'] . '%';
        }
        if (isset($filters['is_active']) && $filters['is_active'] !== '') {
            $where[]  = 'is_active = ?';
            $params[] = (int) $filters['is_active'];
        }

        return (int) $this->db->fetchValue(
            "SELECT COUNT(*) FROM vouchers WHERE " . implode(' AND ', $where), $params
        );
    }

    public function find(int $id): ?array
    {
        return $this->db->fetchOne("SELECT * FROM vouchers WHERE id = ?", [$id]);
    }

    public function codeExists(string $code, int $excludeId = 0): bool
    {
        return (int) $this->db->fetchValue(
            "SELECT COUNT(*) FROM vouchers WHERE code = ? AND id != ?",
            [strtoupper($code), $excludeId]
        ) > 0;
    }

    public function create(array $data): int
    {
        return $this->db->insert('vouchers', $data);
    }

    public function update(int $id, array $data): void
    {
        $this->db->update('vouchers', $data, ['id' => $id]);
    }

    public function delete(int $id): void
    {
        $this->db->delete('vouchers', ['id' => $id]);
    }

    public function toggle(int $id): bool
    {
        $current = (int) $this->db->fetchValue(
            "SELECT is_active FROM vouchers WHERE id = ?", [$id]
        );
        $this->db->update('vouchers', ['is_active' => $current ? 0 : 1], ['id' => $id]);
        return !$current;
    }

    public function usageHistory(int $voucherId): array
    {
        return $this->db->fetchAll(
            "SELECT vu.*, u.name AS user_name, u.email,
                    o.order_number, o.total_amount
               FROM voucher_usages vu
               JOIN users u ON u.id = vu.user_id
               LEFT JOIN orders o ON o.id = vu.order_id
              WHERE vu.voucher_id = ?
              ORDER BY vu.used_at DESC",
            [$voucherId]
        );
    }
}
