# ==== CREATED AND OWNED BY askme360 (HIPL) ====
"""Gemini generateContent REST API (v1beta) with optional Google Search grounding."""
from __future__ import annotations

import os
from typing import Any, Dict, List, Optional

import requests

GEMINI_MODEL_DEFAULT = "gemini-3-flash-preview"
GEMINI_BASE = "https://generativelanguage.googleapis.com/v1beta/models"


def resolve_gemini_api_key(config: Optional[Dict[str, Any]] = None) -> Optional[str]:
    """API key from agent config, env, app settings, then initial_config.txt (gemini_api_key, GEMINI_API_KEY, GOOGLE_API_KEY)."""
    if config:
        for k in ("gemini_api_key", "google_api_key", "GEMINI_API_KEY", "GOOGLE_API_KEY"):
            v = config.get(k)
            if v and str(v).strip():
                return str(v).strip()
    for env in ("GEMINI_API_KEY", "GOOGLE_API_KEY"):
        v = os.getenv(env, "").strip()
        if v:
            return v
    try:
        from app.core.config import get_initial_config, settings

        key = (getattr(settings, "GEMINI_API_KEY", None) or "").strip()
        if key:
            return key
        cfg = get_initial_config()
        gkey = (
            (cfg.get("gemini_api_key") or cfg.get("GEMINI_API_KEY") or cfg.get("GOOGLE_API_KEY") or "")
            .strip()
        )
        if gkey:
            return gkey
    except Exception:
        pass
    return None


def _extract_text_from_gemini_response(data: Dict[str, Any]) -> str:
    parts_out: List[str] = []
    for cand in data.get("candidates") or []:
        content = cand.get("content") or {}
        for part in content.get("parts") or []:
            if part.get("thought") is True:
                continue
            t = part.get("text")
            if t:
                parts_out.append(t)
    if parts_out:
        return "\n".join(parts_out).strip()
    pf = data.get("promptFeedback") or {}
    br = pf.get("blockReason")
    if br:
        raise RuntimeError(f"Gemini blocked content: {br}")
    err = data.get("error") or {}
    if err.get("message"):
        raise RuntimeError(str(err.get("message")))
    raise RuntimeError("Gemini returned no text in candidates")


def gemini_generate_content(
    *,
    user_text: str,
    api_key: str,
    system_instruction: Optional[str] = None,
    model: str = GEMINI_MODEL_DEFAULT,
    google_search: bool = True,
    timeout: int = 300,
    force_native_gemini: bool = False,
) -> str:
    """
    POST .../models/{model}:generateContent with google_search tool.

    Uses a single user turn (REST shape from Google docs) and merges system text into the
    prompt body — avoids systemInstruction + tools edge cases on some API versions.
    Auth: x-goog-api-key header (recommended in official docs).

    When ``oci_call`` is enabled in ``initial_config.txt`` (with OIC URL and env credentials),
    this function uses the OIC Anthropic integration only and does not call Gemini.

    Set ``force_native_gemini=True`` to always call the Gemini REST API (e.g. LLMService
    fallback after Qwen/OIC/OpenAI so this path does not recurse into OIC again).
    """
    from app.services.llm_service import (
        call_oic_anthropic_user_prompt,
        oic_anthropic_integration_enabled,
    )

    if oic_anthropic_integration_enabled() and not force_native_gemini:
        _ = (api_key, model, google_search)
        if system_instruction:
            full_text = f"{system_instruction.strip()}\n\n---\n\n{user_text.strip()}"
        else:
            full_text = user_text.strip()
        return call_oic_anthropic_user_prompt(full_text, timeout_s=float(min(timeout, 600)))

    url = f"{GEMINI_BASE}/{model}:generateContent"
    if system_instruction:
        full_text = f"{system_instruction.strip()}\n\n---\n\n{user_text.strip()}"
    else:
        full_text = user_text.strip()

    body: Dict[str, Any] = {
        "contents": [{"parts": [{"text": full_text}]}],
    }
    if google_search:
        body["tools"] = [{"google_search": {}}]

    headers = {
        "Content-Type": "application/json",
        "x-goog-api-key": api_key,
    }

    r = requests.post(url, json=body, headers=headers, timeout=timeout)
    if not r.ok:
        raise RuntimeError(f"Gemini API error {r.status_code}: {r.text[:2000]}")
    return _extract_text_from_gemini_response(r.json())