"""
Zoe - Real Estate Agent

"""

from typing import Optional, Dict, Any, List
from dataclasses import dataclass
from datetime import datetime
import os
import json
import requests
from loguru import logger
from swarms import Agent
from swarm_models import OpenAIChat
from dotenv import load_dotenv
from enum import Enum

# Configure loguru logger
logger.add(
    "logs/real_estate_agent_{time}.log",
    rotation="500 MB",
    retention="10 days",
    level="INFO",
    format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}",
)


class PropertyType(str, Enum):
    """Enum for property types"""

    OFFICE = "office"
    RETAIL = "retail"
    INDUSTRIAL = "industrial"
    MIXED_USE = "mixed-use"
    LAND = "land"


@dataclass
class PropertyListing:
    """Data class for commercial property listings"""

    property_id: str
    address: str
    city: str
    state: str
    zip_code: str
    price: float
    square_footage: float
    property_type: PropertyType
    zoning: str
    listing_date: datetime
    lat: float
    lng: float
    description: Optional[str] = None
    features: Optional[List[str]] = None
    images: Optional[List[str]] = None


class PropertyRadarAPI:
    """Client for PropertyRadar API integration"""

    def __init__(self, api_key: str):
        """Initialize PropertyRadar API client

        Args:
            api_key (str): PropertyRadar API key
        """
        self.api_key = api_key
        self.base_url = "https://api.propertyradar.com/v1"
        self.session = requests.Session()
        self.session.headers.update(
            {
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json",
            }
        )

    def search_properties(
        self,
        max_price: float = 10_000_000,
        property_types: List[PropertyType] = None,
        location: Dict[str, Any] = None,
        min_sqft: Optional[float] = None,
        max_sqft: Optional[float] = None,
        page: int = 1,
        limit: int = 20,
    ) -> List[PropertyListing]:
        """
        Search for commercial properties using PropertyRadar API

        Args:
            max_price (float): Maximum property price
            property_types (List[PropertyType]): Types of properties to search for
            location (Dict[str, Any]): Location criteria (city, county, or coordinates)
            min_sqft (Optional[float]): Minimum square footage
            max_sqft (Optional[float]): Maximum square footage
            page (int): Page number for pagination
            limit (int): Number of results per page

        Returns:
            List[PropertyListing]: List of matching properties
        """
        try:
            # Build the query parameters
            params = {
                "price_max": max_price,
                "property_types": (
                    [pt.value for pt in property_types]
                    if property_types
                    else None
                ),
                "page": page,
                "limit": limit,
                "for_sale": True,
                "state": "FL",  # Florida only
                "commercial_property": True,
            }

            # Add location parameters
            if location:
                params.update(location)

            # Add square footage filters
            if min_sqft:
                params["square_feet_min"] = min_sqft
            if max_sqft:
                params["square_feet_max"] = max_sqft

            # Make the API request
            response = self.session.get(
                f"{self.base_url}/properties",
                params={
                    k: v for k, v in params.items() if v is not None
                },
            )
            response.raise_for_status()

            # Parse the response
            properties_data = response.json()

            # Convert to PropertyListing objects
            return [
                PropertyListing(
                    property_id=prop["id"],
                    address=prop["address"],
                    city=prop["city"],
                    state=prop["state"],
                    zip_code=prop["zip_code"],
                    price=float(prop["price"]),
                    square_footage=float(prop["square_feet"]),
                    property_type=PropertyType(prop["property_type"]),
                    zoning=prop["zoning"],
                    listing_date=datetime.fromisoformat(
                        prop["list_date"]
                    ),
                    lat=float(prop["latitude"]),
                    lng=float(prop["longitude"]),
                    description=prop.get("description"),
                    features=prop.get("features", []),
                    images=prop.get("images", []),
                )
                for prop in properties_data["results"]
            ]

        except requests.RequestException as e:
            logger.error(f"Error fetching properties: {str(e)}")
            raise


class CommercialRealEstateAgent:
    """Agent for searching and analyzing commercial real estate properties"""

    def __init__(
        self,
        openai_api_key: str,
        propertyradar_api_key: str,
        model_name: str = "gpt-4",
        temperature: float = 0.1,
        saved_state_path: Optional[str] = None,
    ):
        """Initialize the real estate agent

        Args:
            openai_api_key (str): OpenAI API key
            propertyradar_api_key (str): PropertyRadar API key
            model_name (str): Name of the LLM model to use
            temperature (float): Temperature setting for the LLM
            saved_state_path (Optional[str]): Path to save agent state
        """
        self.property_api = PropertyRadarAPI(propertyradar_api_key)

        # Initialize OpenAI model
        self.model = OpenAIChat(
            openai_api_key=openai_api_key,
            model_name=model_name,
            temperature=temperature,
        )

        # Initialize the agent
        self.agent = Agent(
            agent_name="Commercial-Real-Estate-Agent",
            system_prompt=self._get_system_prompt(),
            llm=self.model,
            max_loops=1,
            autosave=True,
            dashboard=False,
            verbose=True,
            saved_state_path=saved_state_path,
            context_length=200000,
            streaming_on=False,
        )

        logger.info(
            "Commercial Real Estate Agent initialized successfully"
        )

    def _get_system_prompt(self) -> str:
        """Get the system prompt for the agent"""
        return """You are a specialized commercial real estate agent assistant focused on Central Florida properties.
        Your primary responsibilities are:
        1. Search for commercial properties under $10 million
        2. Focus on properties zoned for commercial use
        3. Provide detailed analysis of property features, location benefits, and potential ROI
        4. Consider local market conditions and growth potential
        5. Verify zoning compliance and restrictions
        
        When analyzing properties, consider:
        - Current market valuations
        - Local business development plans
        - Traffic patterns and accessibility
        - Nearby amenities and businesses
        - Future development potential"""

    def search_properties(
        self,
        max_price: float = 10_000_000,
        property_types: List[PropertyType] = None,
        location: Dict[str, Any] = None,
        min_sqft: Optional[float] = None,
        max_sqft: Optional[float] = None,
    ) -> List[Dict[str, Any]]:
        """
        Search for properties and provide analysis

        Args:
            max_price (float): Maximum property price
            property_types (List[PropertyType]): Types of properties to search
            location (Dict[str, Any]): Location criteria
            min_sqft (Optional[float]): Minimum square footage
            max_sqft (Optional[float]): Maximum square footage

        Returns:
            List[Dict[str, Any]]: List of properties with analysis
        """
        try:
            # Search for properties
            properties = self.property_api.search_properties(
                max_price=max_price,
                property_types=property_types,
                location=location,
                min_sqft=min_sqft,
                max_sqft=max_sqft,
            )

            # Analyze each property
            analyzed_properties = []
            for prop in properties:
                analysis = self.agent.run(
                    f"Analyze this commercial property:\n"
                    f"Address: {prop.address}, {prop.city}, FL {prop.zip_code}\n"
                    f"Price: ${prop.price:,.2f}\n"
                    f"Square Footage: {prop.square_footage:,.0f}\n"
                    f"Property Type: {prop.property_type.value}\n"
                    f"Zoning: {prop.zoning}\n"
                    f"Description: {prop.description or 'Not provided'}"
                )

                analyzed_properties.append(
                    {"property": prop.__dict__, "analysis": analysis}
                )

            logger.info(
                f"Successfully analyzed {len(analyzed_properties)} properties"
            )
            return analyzed_properties

        except Exception as e:
            logger.error(
                f"Error in property search and analysis: {str(e)}"
            )
            raise


def main():
    """Main function to demonstrate usage"""
    load_dotenv()

    # Initialize the agent
    agent = CommercialRealEstateAgent(
        openai_api_key=os.getenv("OPENAI_API_KEY"),
        propertyradar_api_key=os.getenv("PROPERTYRADAR_API_KEY"),
        saved_state_path="real_estate_agent_state.json",
    )

    # Example search
    results = agent.search_properties(
        max_price=5_000_000,
        property_types=[PropertyType.RETAIL, PropertyType.OFFICE],
        location={"city": "Orlando", "radius_miles": 25},
        min_sqft=2000,
    )

    # Save results
    with open("search_results.json", "w") as f:
        json.dump(results, f, default=str, indent=2)


if __name__ == "__main__":
    main()