#!/usr/bin/env python
"""
This module provides the InstructLabProvider class for enhancing text generation through an AI service. It utilizes the
requests library to send POST requests to an AI model server, with configurations fetched from environment variables.

The main functionality is encapsulated in the improve_text method, which takes a prompt and text, sends a request to
the AI service, and returns the improved text. An AiError exception is raised in case of request failures, detailing
the issue.

Classes:
- InstructLabProvider: A class for improving text using an AI model.

Attributes:
- url (str): The URL of the AI model server.
- model (str): The identifier of the AI model used for text generation.

Methods:
- __init__(self): Initializes the class with AI-related environment variables.
- improve_text(self, prompt: str, text: str) -> str: Improves the provided text using the AI model and returns the
enhanced text.

Exceptions:
- AiError: Raised when the POST request to the AI service fails, indicating a service issue.
"""

# pylint: disable=too-few-public-methods

import requests

from jira_creator.core.env_fetcher import EnvFetcher
from jira_creator.exceptions.exceptions import AiError
from jira_creator.providers.ai_provider import AIProvider


class InstructLabProvider(AIProvider):
    """
    This class provides a way to interact with an AI model hosted on a specified URL for improving text generation.

    Attributes:
    - url (str): The URL of the AI model server.
    - model (str): The name or identifier of the AI model used for text generation.

    Methods:
    - __init__(self): Initializes the class instance with AI-related environment variables.
    - improve_text(self, prompt: str, text: str) -> str: Sends a POST request to a specified URL with a given prompt
    and text to improve the text using a specific model. It then returns the improved text obtained from the response.
    Raises AiError if the POST request fails, providing details of the failure.
    """

    def __init__(self) -> None:
        """
        Initialize the class instance with AI-related environment variables.
        Arguments:
        - self: The class instance to be initialized.
        Return: None
        """
        self.url: str = EnvFetcher.get("JIRA_AI_URL")
        self.model: str = EnvFetcher.get("JIRA_AI_MODEL")

    def improve_text(self, prompt: str, text: str) -> str:
        """
        Sends a POST request to a specified URL with a given prompt and text to improve the text using a specific model.
        It then returns the improved text obtained from the response.

        Arguments:
        - prompt (str): The initial prompt to provide context for improving the text.
        - text (str): The text to be improved based on the provided prompt.

        Return:
        str: The improved text generated by the AI model in response to the provided prompt and text.

        Exceptions:
        - AiError: Raised when the POST request to the URL fails, indicating an issue with the AI service.
        """
        full_prompt: str = f"{prompt}\n\n{text}"
        response: requests.Response = requests.post(
            self.url,
            json={
                "model": self.model,
                "prompt": full_prompt,
                "stream": False,
                "options": {"temperature": 0.3},
            },
            timeout=60,
        )
        if response.status_code == 200:
            raw_content = response.json().get("response", "")
            return self.extract_content(raw_content)
        raise AiError(f"InstructLab request failed: {response.status_code} - {response.text}")

    def analyze_error(self, prompt: str, error_context: str) -> str:
        """
        Analyze a JIRA API error and suggest code-level fixes.

        Arguments:
        - prompt (str): The system prompt for error analysis.
        - error_context (str): JSON-formatted error context.

        Return:
        - str: Markdown-formatted analysis with root cause, proposed fix, and workarounds.

        Exceptions:
        - AiError: Raised when the POST request to the URL fails.
        """
        full_prompt = f"{prompt}\n\nAnalyze this error:\n\n{error_context}"
        response: requests.Response = requests.post(
            self.url,
            json={
                "model": self.model,
                "prompt": full_prompt,
                "stream": False,
                "options": {"temperature": 0.3},
            },
            timeout=120,
        )
        if response.status_code == 200:
            return response.json().get("response", "").strip()
        raise AiError(f"InstructLab request failed: {response.status_code} - {response.text}")

    def analyze_and_fix_error(self, prompt: str, error_context: str) -> str:
        """
        Analyze an error and return a structured fix proposal in JSON format.

        Arguments:
        - prompt (str): The system prompt for error analysis and fix generation.
        - error_context (str): JSON-formatted error context.

        Return:
        - str: JSON-formatted fix proposal.

        Exceptions:
        - AiError: Raised when the POST request to the URL fails.
        """
        full_prompt = f"{prompt}\n\nAnalyze this error and propose a fix:\n\n{error_context}"
        response: requests.Response = requests.post(
            self.url,
            json={
                "model": self.model,
                "prompt": full_prompt,
                "stream": False,
                "options": {"temperature": 0.3},
            },
            timeout=120,
        )
        if response.status_code == 200:
            return response.json().get("response", "").strip()
        raise AiError(f"InstructLab request failed: {response.status_code} - {response.text}")
