import toons
import httpx
import asyncio
import logging

from pydantic import BaseModel, Field
from datetime import datetime, timedelta, timezone

from app.configs.settings import settings
from langchain_openai.chat_models.base import ChatOpenAI
log = logging.getLogger(__name__)

class ReviewAnalysisSchema(BaseModel):
    overall_rating: int = Field(description="Overall rating of the hotel (1-5)", default=1, ge=1, le=5)
    problems: list[str] = Field(description="List of problems with the hotel", default=[])
    suggestions: list[str] = Field(description="List of suggestions for the hotel", default=[])
    review_analysis: str = Field(description="Review Analysis")

async def analyze_review_prompt(context: str) -> str:

    return f"""You are an expert hospitality analyst AI.
    Your task is to carefully analyze a collection of hotel reviews and extract meaningful insights.
    <CONTEXT>
    {context}
    </CONTEXT>
    
    INSTRUCTIONS:
        1. Read all reviews thoroughly.
        2. Identify overall customer sentiment (positive, negative, mixed).
        3. Determine a realistic overall rating from 1 to 5:
            - 1 = Very poor experience
            - 2 = Poor
            - 3 = Average
            - 4 = Good
            - 5 = Excellent
        4. Extract recurring or significant problems mentioned by guests.
        5. Provide actionable suggestions for the hotel to improve based on the problems.
        6. Write a concise but insightful summary analysis of the reviews.
    
    IMPORTANT GUIDELINES:
    - Base your conclusions ONLY on the provided reviews.
    - Do not hallucinate or assume missing information.
    - If no problems are mentioned, return an empty list.
    - Avoid duplicate or redundant points.
    - Keep suggestions practical and relevant.
    - The review_analysis should summarize key themes, sentiment trends, and notable patterns."""

async def get_trip_advisor_reviews():
    try:
        async with httpx.AsyncClient(timeout=60.0) as client:
            response = await client.get(
                f"https://api.content.tripadvisor.com/api/v1/location/{settings.TRIPADVISOR_LOCATION_ID}/reviews",
                params={
                    "key": settings.TRIPADVISOR_API_KEY,
                }
            )
        data = response.json().get('data', [])
        return [
            {
                "source": "TripAdvisor",
                "published_date": review.get('published_date'),
                "rating": review.get('rating'),
                "title": review.get('title'),
                "text": review.get('text'),
                "trip_type": review.get('trip_type'),
                "travel_date": review.get('travel_date'),
            }
            for review in data
        ]
    except Exception as e:
        log.error(f"Error getting trip advisor reviews: {e}")
        return []

async def filter_last_two_months_reviews(reviews: list[dict]) -> list[dict]:
    cutoff_date = datetime.now(timezone.utc) - timedelta(days=120)

    filtered_reviews = []

    for review in reviews:
        if review.get('source') == 'TripAdvisor':
            published_date_str = review.get('published_date')

            if not published_date_str:
                continue

            published_date = datetime.fromisoformat(
                published_date_str.replace("Z", "+00:00")
            )

            if published_date >= cutoff_date:
                filtered_reviews.append(review)

    return filtered_reviews

async def generate_review_analysis(context: str) -> dict:

    llm = ChatOpenAI(api_key=settings.OPENAI_API_KEY, model="gpt-5.1")
    chain = llm.with_structured_output(ReviewAnalysisSchema)
    prompt = await analyze_review_prompt(context)
    result: ReviewAnalysisSchema = await chain.ainvoke(prompt)
    return result.model_dump()

async def analyze_reviews():
    
    reviews = []

    tasks = asyncio.gather(
        get_trip_advisor_reviews(),
    )

    trip_advisor_reviews, = await tasks

    reviews.extend(trip_advisor_reviews)

    # reviews = await filter_last_two_months_reviews(reviews)
    
    context = toons.dumps(reviews)

    review_analysis = await generate_review_analysis(context)

    return review_analysis