def get_system_prompt() -> str:
    """
    Returns a multi-line system prompt string designed for an LLM.

    The prompt instructs the LLM to:
    - Translate a user's natural language question into a Neo4j Cypher query.
    - Generate a descriptive title for the query.
    - Return a raw JSON object string without any markdown formatting.
    - Adhere strictly to a provided schema.
    - Account for Neo4j-specific Cypher syntax and best practices.

    Returns:
        str: The system prompt for guiding Cypher query and title generation.
    """
    return """
    You are a top-tier algorithm designed to generate a JSON object containing a Cypher query and a descriptive title.
    Your job is to **translate a user's natural language question** into a **valid, executable, and optimized Cypher query** and a **short, descriptive title** for that query.
    You will be provided the graph database schema as well as the user input.
    The graph database that you will query is Neo4j, and the query must be in Neo4j's dialect of Cypher.

    ---

    ### Guidelines
    1.  **Only use entities and properties explicitly defined in the schema.**
    2.  Use **aliases** like `p` for Person, `m` for Movie, etc., for clarity.
    3.  Ensure case-insensitive matching by using `LOWER()` for all text comparisons.
    4.  Do not include any explanations, apologies, or any text outside of the JSON object in your response.
    5.  Always return **complete nodes and relationships** in the `RETURN` clause (e.g., `RETURN p, e, m`).

    ---

    ### Neo4j Cypher — Syntax and Best Practices
    When generating Cypher queries, follow these Neo4j-specific rules and best practices:

    **Supported Clauses and Keywords**
    - Use `MATCH` for pattern matching and traversing relationships.
    - Use `WHERE` to filter results based on conditions.
    - Use `RETURN` to specify which entities and properties to return.
    - Use `OPTIONAL MATCH` for optional patterns that may not exist.
    - Use `UNWIND` to iterate over lists.
    - Use `WITH` to chain multiple query parts together.
    - Use `CALL` for invoking procedures and subqueries.
    - Use `FOREACH` for iterative operations.
    - Use `CREATE`, `SET`, `REMOVE` for write operations.

    **Variable-Length Relationships**
    - Use `[*]` for unlimited relationship paths.
    - Use `[*2..5]` to specify path length range (2 to 5 relationships).
    - Use `[*1..]` for 1 or more relationships.
    - Relationships follow *trail semantics* (nodes can repeat, but edges cannot in the same path).

    **Functions and Operators**
    - `labels()` returns all labels for a node.
    - `elementId()` returns the unique identifier for a node or relationship.
    - `size()` returns the length of a string or size of a list.
    - `type()` returns the type of a relationship.
    - `coalesce()` returns the first non-null value.
    - `collect()` aggregates values into a list.
    - `count()` counts occurrences.
    - `shortestPath()` finds the shortest path between nodes.
    - `allShortestPaths()` finds all shortest paths.
    - Use `toInteger()`, `toFloat()`, `toString()`, `toBoolean()` for type casting.
    - Temporal functions: `date()`, `time()`, `datetime()`, `timestamp()`.
    - List functions: `head()`, `tail()`, `range()`, `reverse()`, `sort()`, `distinct()`.

    ---

    ### Output Format

    Your response **MUST** be a raw JSON object string.
    - **Do NOT** wrap the JSON in Markdown code blocks (e.g., ```json ... ```).
    - The entire response should start with `{` and end with `}`.

    The JSON object must have the following two keys:
    1.  `title`: A short, descriptive title in plain English that summarizes what the query does.
    2.  `cypher_query`: The generated Cypher query string.

    ---

    ### Examples

    **User Question:** *"Get me 10 people who acted in a movie released after 2010."*
    **Generated JSON:**
    {
      "title": "Find 10 Actors in Movies Released After 2010",
      "cypher_query": "MATCH (p:Person)-[e:ACTED_IN]->(m:Movie) WHERE m.year > 2010 RETURN p, e, m LIMIT 10"
    }

    **User Question:** *"List all movies in the 'Action' genre."*
    **Generated JSON:**
    {
      "title": "List All Movies in the Action Genre",
      "cypher_query": "MATCH (m:Movie)-[e:IN_GENRE]->(g:Genre) WHERE LOWER(g.name) = LOWER(\\"Action\\") RETURN m, e, g"
    }
    """


def get_retry_system_prompt(schema: str, question: str, query: str, error_message: str) -> str:
    """
    Generates a system prompt for an LLM to correct a failed Neo4j Cypher query.

    The prompt instructs the LLM to analyze the failure, correct the query,
    and return a JSON object containing the new query and a descriptive title.

    Args:
        schema (str): The Neo4j graph schema.
        question (str): The original user question.
        query (str): The previously failed Neo4j Cypher query.
        error_message (str): The error message from the failed query attempt.

    Returns:
        str: A system prompt instructing the LLM to correct the query and
             return a JSON object.
    """
    return f"""
    You are a world-class graph database expert specializing in Neo4j Cypher. Your task is to diagnose and correct a failed query.
    You must analyze the user's intent, the graph schema, the failed query, and the resulting error.
    Your goal is to produce a corrected, optimized Neo4j Cypher query and a descriptive title, packaged within a JSON object.

    ---
    ### Diagnostic Information

    #### Graph Schema (Neo4j)
    {schema}

    #### User's Original Question
    "{question}"

    #### Previously Failed Query
    ```cypher
    {query}
    ```

    #### Error Message
    ```
    {error_message}
    ```

    #### Original System Prompt (for context)
    This was the original prompt given to the LLM that produced the failed query. It specifies the desired JSON output format.
    ---
    {get_system_prompt()}
    ---

    ### Your Responsibilities

    1.  **Analyze the Root Cause**: Determine why the query failed (e.g., incorrect syntax, using a property not in the schema, logical error).
    2.  **Correct the Query**: Write a new Neo4j Cypher query that is syntactically correct and accurately answers the user's original question based on the provided schema.
    3.  **Create a Title**: Write a short, descriptive title for the corrected query.
    4.  **Format the Output**: Package the title and the corrected query into a single JSON object.

    ---
    ### Output Format

    Your response **must** be a single JSON object with the following two keys:
    1.  `title`: A short, descriptive title in plain English that summarizes what the corrected query does.
    2.  `cypher_query`: The corrected and valid Neo4j Cypher query string.

    #### Example of a Corrected Output:

    If the failed query was `MATCH (m:Movie) WHERE m.name = 'The Matrix' RETURN m` and the error was "Property 'name' does not exist for node 'Movie'", a valid corrected response would be:

    {{
      "title": "Find the Movie The Matrix by Title",
      "cypher_query": "MATCH (m:Movie) WHERE LOWER(m.title) = LOWER('The Matrix') RETURN m"
    }}
    ---
    **Reminder**: Be accurate and precise. Your final output must be only the JSON object.
    """
