"""Admin endpoints for the versioned AI prompt editor."""

import logging

from odoo import fields, http
from odoo.http import request

from odoo.addons.encoach_api.controllers.base import (
    _error_response,
    _get_json_body,
    _json_response,
    _paginate,
    jwt_required,
)

_logger = logging.getLogger(__name__)


def _prompt_to_dict(prompt, *, include_content=True):
    data = {
        "id": prompt.id,
        "key": prompt.key,
        "version": prompt.version,
        "title": prompt.title or "",
        "description": prompt.description or "",
        "is_active": bool(prompt.is_active),
        "variables": (prompt.variables or "").split(",") if prompt.variables else [],
        "author_id": prompt.author_id.id if prompt.author_id else None,
        "author_name": prompt.author_id.name if prompt.author_id else "",
        "activated_at": (
            fields.Datetime.to_string(prompt.activated_at) if prompt.activated_at else None
        ),
        "create_date": (
            fields.Datetime.to_string(prompt.create_date) if prompt.create_date else None
        ),
    }
    if include_content:
        data["content"] = prompt.content or ""
    return data


class EncoachAIPromptController(http.Controller):
    """Versioned prompt CRUD.

    Auth: every endpoint requires a valid JWT. The write endpoints additionally
    check for admin rights via ``res.users.has_group('base.group_system')`` so
    non-admins can read prompts but not mutate them.
    """

    # ------------------------------------------------------------------
    # GET /api/ai/prompts — list keys (latest version per key)
    # ------------------------------------------------------------------
    @http.route("/api/ai/prompts", type="http", auth="none", methods=["GET"], csrf=False)
    @jwt_required
    def list_keys(self, **kw):
        try:
            Prompt = request.env["encoach.ai.prompt"].sudo()
            # One row per key = the latest version. We fetch candidates then
            # deduplicate in Python because Odoo's ORM doesn't expose DISTINCT
            # ON ergonomically.
            search = (kw.get("search") or "").strip()
            domain = [("key", "ilike", search)] if search else []
            # Sort by key then descending version so the first occurrence per
            # key is the latest.
            all_prompts = Prompt.search(domain, order="key asc, version desc")
            seen = set()
            latest = []
            for p in all_prompts:
                if p.key in seen:
                    continue
                seen.add(p.key)
                latest.append(p)
            offset, per_page, page = _paginate(kw)
            total = len(latest)
            window = latest[offset : offset + per_page]
            items = [_prompt_to_dict(p, include_content=False) for p in window]
            # Attach version-count for the UI to show "v5 (of 7)" hints.
            counts = {}
            for p in all_prompts:
                counts[p.key] = counts.get(p.key, 0) + 1
            for entry in items:
                entry["total_versions"] = counts.get(entry["key"], 1)
            return _json_response({
                "items": items,
                "data": items,
                "total": total,
                "page": page,
                "size": per_page,
            })
        except Exception as e:
            _logger.exception("list ai prompts failed")
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # GET /api/ai/prompts/<key>/versions
    # ------------------------------------------------------------------
    @http.route(
        '/api/ai/prompts/<string:key>/versions',
        type="http", auth="none", methods=["GET"], csrf=False,
    )
    @jwt_required
    def list_versions(self, key, **kw):
        try:
            Prompt = request.env["encoach.ai.prompt"].sudo()
            prompts = Prompt.search([("key", "=", key)], order="version desc")
            if not prompts:
                return _error_response("Prompt key not found", 404)
            items = [_prompt_to_dict(p, include_content=False) for p in prompts]
            return _json_response({
                "key": key,
                "items": items,
                "data": items,
                "total": len(items),
                "page": 1,
                "size": len(items),
            })
        except Exception as e:
            _logger.exception("list prompt versions failed")
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # GET /api/ai/prompts/<int:prompt_id>
    # ------------------------------------------------------------------
    @http.route(
        '/api/ai/prompts/<int:prompt_id>',
        type="http", auth="none", methods=["GET"], csrf=False,
    )
    @jwt_required
    def get_version(self, prompt_id, **kw):
        try:
            prompt = request.env["encoach.ai.prompt"].sudo().browse(prompt_id)
            if not prompt.exists():
                return _error_response("Prompt not found", 404)
            return _json_response(_prompt_to_dict(prompt))
        except Exception as e:
            _logger.exception("get prompt failed")
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # POST /api/ai/prompts — create a new version of a key (or a new key)
    # ------------------------------------------------------------------
    @http.route("/api/ai/prompts", type="http", auth="none", methods=["POST"], csrf=False)
    @jwt_required
    def create_version(self, **kw):
        try:
            if not request.env.user.has_group("base.group_system"):
                return _error_response("Admin privileges required", 403)

            body = _get_json_body() or {}
            key = (body.get("key") or "").strip()
            content = body.get("content") or ""
            title = (body.get("title") or "").strip()
            if not key or not content.strip() or not title:
                return _error_response(
                    "key, title, and content are required", 400,
                )

            vals = {
                "key": key,
                "title": title,
                "description": body.get("description") or "",
                "content": content,
                "is_active": bool(body.get("activate", False)),
            }
            with request.env.cr.savepoint():
                prompt = request.env["encoach.ai.prompt"].sudo().create(vals)
            return _json_response(_prompt_to_dict(prompt), 201)
        except Exception as e:
            _logger.exception("create prompt version failed")
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # POST /api/ai/prompts/<id>/activate
    # ------------------------------------------------------------------
    @http.route(
        '/api/ai/prompts/<int:prompt_id>/activate',
        type="http", auth="none", methods=["POST"], csrf=False,
    )
    @jwt_required
    def activate(self, prompt_id, **kw):
        try:
            if not request.env.user.has_group("base.group_system"):
                return _error_response("Admin privileges required", 403)
            prompt = request.env["encoach.ai.prompt"].sudo().browse(prompt_id)
            if not prompt.exists():
                return _error_response("Prompt not found", 404)
            with request.env.cr.savepoint():
                prompt.write({"is_active": True})
            return _json_response(_prompt_to_dict(prompt))
        except Exception as e:
            _logger.exception("activate prompt failed")
            return _error_response(str(e), 500)

    # ------------------------------------------------------------------
    # POST /api/ai/prompts/<id>/render — dry-run render with sample variables
    # ------------------------------------------------------------------
    @http.route(
        '/api/ai/prompts/<int:prompt_id>/render',
        type="http", auth="none", methods=["POST"], csrf=False,
    )
    @jwt_required
    def render_preview(self, prompt_id, **kw):
        try:
            prompt = request.env["encoach.ai.prompt"].sudo().browse(prompt_id)
            if not prompt.exists():
                return _error_response("Prompt not found", 404)
            body = _get_json_body() or {}
            variables = body.get("variables") or {}
            if not isinstance(variables, dict):
                return _error_response("variables must be a JSON object", 400)
            rendered = prompt.render(variables)
            return _json_response({
                "rendered": rendered,
                "key": prompt.key,
                "version": prompt.version,
            })
        except Exception as e:
            _logger.exception("render prompt failed")
            return _error_response(str(e), 400)
