<?php
// Prevent direct access
if (count(get_included_files()) === 1) {
    http_response_code(403);
    exit('Forbidden');
}

/**
 * RubroService — helpers Gemini enfocados en clasificación de rubros.
 *
 * Dos llamadas rápidas a Gemini que devuelven SOLO JSON:
 *
 *   inferir_rubro($nombre)         → {rubro, especialidad, confianza}
 *   sugerir_servicios($rubro, $esp) → [{nombre, duracion_min, precio_sugerido}]
 *
 * Estas llamadas se usan desde FunctionDispatcher al procesar las tools
 * 'inferir_rubro' y 'sugerir_servicios' del onboarding, o pueden llamarse
 * directamente desde PHP cuando se necesite clasificar en batch.
 */
class RubroService {

    private const RUBROS_CANONICOS = ['barberia', 'odontologia', 'belleza', 'general'];

    /**
     * Clasifica un negocio por su nombre.
     *
     * @param  string $nombre Nombre del negocio
     * @return array{rubro:string, especialidad:string|null, confianza:float}
     */
    public static function inferirRubro(string $nombre): array {
        $nombre = trim($nombre);
        if ($nombre === '') {
            return ['rubro' => 'general', 'especialidad' => null, 'confianza' => 0.0];
        }

        $prompt = <<<PROMPT
Clasificá el negocio por su nombre. Devolvé SOLO JSON válido, sin markdown, sin texto extra.

Rubros posibles: barberia, odontologia, belleza, general

Reglas:
- "barberia" = barbería, peluquería masculina, barber shop
- "odontologia" = consultorio dental, clínica dental, odontología (cualquier especialidad)
- "belleza" = salón de belleza, spa, estética, nail bar, peluquería femenina
- "general" = cualquier otro negocio con citas

Formato exacto:
{"rubro":"barberia|odontologia|belleza|general","especialidad":"<frase corta en español|null>","confianza":0.0}

confianza: 0.0 a 1.0 según qué tan seguro estás del rubro.
especialidad: descripción corta si hay algo específico (ej. "odontología pediátrica", "barbería afro"), o null.

Nombre: "{$nombre}"
PROMPT;

        $raw = self::callGeminiJson($prompt);
        return self::parseRubroResponse($raw);
    }

    /**
     * Sugiere servicios típicos para un rubro dado, anclados a las semillas de config/rubros.php.
     * Si el rubro no tiene semillas (general) o la especialidad aporta contexto extra, Gemini
     * puede generar servicios adicionales relevantes.
     *
     * @param  string      $rubro      Rubro canónico
     * @param  string|null $especialidad Especialidad libre (puede ser null)
     * @return array  Lista de [{nombre, duracion_min, precio_sugerido}]
     */
    public static function sugerirServicios(string $rubro, ?string $especialidad = null): array {
        $rubros  = require dirname(__DIR__, 2) . '/config/rubros.php';
        $semillas = $rubros[$rubro]['servicios_semilla'] ?? [];

        // Si hay semillas suficientes (≥4), devolverlas directamente sin llamar a Gemini
        if (count($semillas) >= 4) {
            return $semillas;
        }

        // Para rubro general o sin semillas: llamar a Gemini para generar servicios
        $espCtx = $especialidad ? " (especialidad: $especialidad)" : '';
        $semillasJson = json_encode($semillas, JSON_UNESCAPED_UNICODE);

        $prompt = <<<PROMPT
Generá 4 a 6 servicios típicos y reales para un negocio de rubro "{$rubro}"{$espCtx}.

Si hay servicios semilla, mantenelos y completá hasta 6 si hace falta.
Semillas: {$semillasJson}

Devolvé SOLO JSON válido, sin markdown, sin texto extra.
Formato exacto:
[{"nombre":"Nombre del servicio","duracion_min":30,"precio_sugerido":null}]

- duracion_min: número entero en minutos, o null si no aplica
- precio_sugerido: número en dólares o null (dejar null siempre que no sea obvio)
- Máximo 6 servicios
PROMPT;

        $raw = self::callGeminiJson($prompt);
        return self::parseServiciosResponse($raw, $semillas);
    }

    /**
     * Carga el bloque de conocimiento "pro" del rubro para inyectar en el system prompt.
     * Retorna el string del bloque_prompt del rubro, o un bloque genérico si no existe.
     */
    public static function bloquePrompt(string $rubro): string {
        $rubros = require dirname(__DIR__, 2) . '/config/rubros.php';
        return $rubros[$rubro]['bloque_prompt']
            ?? $rubros['general']['bloque_prompt']
            ?? '';
    }

    /**
     * Devuelve el vocabulario de un rubro (para el prompt de Vale).
     * Keys: usuario, prestador, servicio, reserva
     */
    public static function vocab(string $rubro): array {
        $rubros = require dirname(__DIR__, 2) . '/config/rubros.php';
        return $rubros[$rubro]['vocab'] ?? $rubros['general']['vocab'];
    }

    // ── Helpers privados ──────────────────────────────────────────────────────

    /**
     * Llama a Gemini con temperatura 0 y sin tools para obtener JSON puro.
     * Modelo rápido y barato para clasificación.
     */
    private static function callGeminiJson(string $prompt): string {
        $apiKey = getenv('GEMINI_API_KEY');
        if (!$apiKey) throw new RuntimeException('GEMINI_API_KEY no configurada');

        // Usar flash para estas llamadas de clasificación (más rápido y barato)
        $model = 'gemini-2.0-flash';

        $url  = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$apiKey}";
        $body = json_encode([
            'contents' => [['role' => 'user', 'parts' => [['text' => $prompt]]]],
            'generationConfig' => [
                'temperature'     => 0.0,
                'maxOutputTokens' => 512,
                'responseMimeType' => 'application/json',
            ],
        ]);

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => $body,
            CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
            CURLOPT_TIMEOUT        => 10,
        ]);
        $resp = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($code >= 400 || $resp === false) {
            throw new RuntimeException("Gemini JSON error (HTTP $code)");
        }

        $data = json_decode($resp, true);
        return $data['candidates'][0]['content']['parts'][0]['text'] ?? '{}';
    }

    private static function parseRubroResponse(string $raw): array {
        try {
            // Limpiar posible markdown que Gemini incluya a pesar de las instrucciones
            $clean = preg_replace('/^```(?:json)?\n?|\n?```$/m', '', trim($raw));
            $obj = json_decode($clean, true, 10, JSON_THROW_ON_ERROR);
        } catch (\Throwable) {
            return ['rubro' => 'general', 'especialidad' => null, 'confianza' => 0.0];
        }

        $rubro = in_array($obj['rubro'] ?? '', self::RUBROS_CANONICOS, true)
            ? $obj['rubro']
            : 'general';

        return [
            'rubro'       => $rubro,
            'especialidad' => isset($obj['especialidad']) && $obj['especialidad'] !== 'null'
                ? mb_substr(trim((string)$obj['especialidad']), 0, 120)
                : null,
            'confianza'   => max(0.0, min(1.0, (float)($obj['confianza'] ?? 0.5))),
        ];
    }

    private static function parseServiciosResponse(string $raw, array $fallback): array {
        try {
            $clean = preg_replace('/^```(?:json)?\n?|\n?```$/m', '', trim($raw));
            $arr = json_decode($clean, true, 10, JSON_THROW_ON_ERROR);
            if (!is_array($arr) || empty($arr)) return $fallback;
        } catch (\Throwable) {
            return $fallback;
        }

        $result = [];
        foreach (array_slice($arr, 0, 6) as $s) {
            if (empty($s['nombre'])) continue;
            $result[] = [
                'nombre'          => mb_substr(trim((string)$s['nombre']), 0, 120),
                'duracion_min'    => is_numeric($s['duracion_min'] ?? null) ? (int)$s['duracion_min'] : null,
                'precio_sugerido' => is_numeric($s['precio_sugerido'] ?? null) ? (float)$s['precio_sugerido'] : null,
            ];
        }
        return $result ?: $fallback;
    }
}
