<?php

namespace App\Models;

use App\Libraries\YemscanService;
use CodeIgniter\Model;

class YemTransactionModel extends Model
{
    protected $table         = 'yem_transactions';
    protected $primaryKey    = 'id';
    protected $allowedFields = [
        'hash', 'from_uid', 'to_uid', 'value', 'reason', 'asset',
        'from_curr', 'to_curr', 'status', 'status_updated_at', 'created_at',
    ];
    protected $useTimestamps = false;

    /**
     * Normalize hash to 0x-prefixed lowercase (for tolerant matching).
     */
    private function normalizeHash(string $hash): string
    {
        $hash = strtolower(trim($hash));
        if ($hash === '') {
            return '';
        }
        return strpos($hash, '0x') === 0 ? $hash : '0x' . $hash;
    }

    /**
     * Get all YEM transactions, newest first.
     */
    public function getAllOrderByCreatedDesc(int $limit = 500): array
    {
        return $this->orderBy('created_at', 'DESC')->findAll($limit);
    }

    /**
     * Update status for a transaction by hash.
     */
    public function updateStatusByHash(string $hash, string $status): bool
    {
        $normalized = $this->normalizeHash($hash);
        $withoutPrefix = strpos($normalized, '0x') === 0 ? substr($normalized, 2) : $normalized;
        return (bool) $this->groupStart()
            ->where('LOWER(hash)', $normalized)
            ->orWhere('LOWER(hash)', $withoutPrefix)
            ->groupEnd()
            ->set([
            'status' => $status,
            'status_updated_at' => date('Y-m-d H:i:s'),
        ])->update();
    }

    /**
     * Find by hash.
     */
    public function getByHash(string $hash): ?array
    {
        $normalized = $this->normalizeHash($hash);
        $withoutPrefix = strpos($normalized, '0x') === 0 ? substr($normalized, 2) : $normalized;
        $row = $this->groupStart()
            ->where('LOWER(hash)', $normalized)
            ->orWhere('LOWER(hash)', $withoutPrefix)
            ->groupEnd()
            ->first();
        return $row ? (array) $row : null;
    }

    /**
     * One-time migration per run: rows incorrectly stored as "success" become "confirmed"
     * (matches YEMScan / consumer-facing status vocabulary).
     */
    private function normalizeLegacySuccessToConfirmed(): int
    {
        $this->where('status', 'success')->set([
            'status' => 'confirmed',
            'status_updated_at' => date('Y-m-d H:i:s'),
        ])->update();

        return (int) $this->db->affectedRows();
    }

    /**
     * Refresh statuses of recorded transactions from YEMScan API.
     * Returns the number of rows updated (legacy success→confirmed + pending reconciled from API).
     */
    public function refreshStatuses(YemscanService $yemscanService, int $limit = 100): int
    {
        $updated = $this->normalizeLegacySuccessToConfirmed();

        $transactions = $this->where('status', 'pending')
            ->orderBy('created_at', 'DESC')
            ->findAll($limit);
        $hashes = array_values(array_unique(array_filter(array_map(function ($hash) {
            return $this->normalizeHash((string) $hash);
        }, array_column($transactions, 'hash')))));
        if (empty($hashes)) {
            return $updated;
        }
        $result = $yemscanService->getTransactionStatuses($hashes);
        if (!empty($result['success']) && !empty($result['statuses'])) {
            foreach ($result['statuses'] as $hash => $status) {
                // Align with YEMScan: confirmed | failed | leave pending for not_found / unknown.
                $mapped = $status === 'confirmed' ? 'confirmed' : ($status === 'failed' ? 'failed' : 'pending');
                if ($mapped === 'pending') {
                    continue;
                }
                if ($this->updateStatusByHash($hash, $mapped)) {
                    $updated++;
                }
            }
        }
        return $updated;
    }
}
