from fastapi import APIRouter, HTTPException
from typing import Dict, Any
from modules.database.tools import neo4j_driver_tools as driver_tools
from modules.logger_tool import initialise_logger
from neo4j.time import DateTime, Date
import os
from datetime import datetime

logger = initialise_logger(__name__, os.getenv("LOG_LEVEL"), os.getenv("LOG_PATH"), 'default', True)
router = APIRouter()

def convert_neo4j_values(value: Any) -> Any:
    """Convert Neo4j types to JSON-serializable types."""
    if isinstance(value, DateTime):
        return value.isoformat()  # Convert to ISO format string
    elif isinstance(value, Date):
        return value.isoformat()  # Convert Date to ISO format string
    elif isinstance(value, dict):
        return {k: convert_neo4j_values(v) for k, v in value.items()}
    elif isinstance(value, list):
        return [convert_neo4j_values(v) for v in value]
    return value

def get_default_node_week(db_name: str) -> Dict[str, Any]:
    """Get the current week node."""
    # Get today's date
    today = datetime.now()
    
    # Find the calendar week node that contains today's date
    query = """
    MATCH (w:CalendarWeek)
    WHERE date(w.start_date) <= date($today) AND date($today) <= date(w.start_date) + duration('P7D')
    RETURN w
    """
    
    with driver_tools.get_session(database=db_name) as session:
        result = session.run(query, today=today.strftime('%Y-%m-%d'))
        week_node = result.single()
        
        if not week_node:
            raise HTTPException(status_code=404, detail="No default node found for context: week")
            
        node = week_node["w"]
        node_data = dict(node)
        converted_data = convert_neo4j_values(node_data)
        
        return {
            "status": "success",
            "node": {
                "id": node["uuid_string"],
                "path": node["path"],
                "type": "CalendarWeek",
                "label": node.get("title", "Calendar Week"),
                "data": converted_data
            }
        }

def get_default_node_month(db_name: str) -> Dict[str, Any]:
    """Get the current month node."""
    # Get today's date
    today = datetime.now()
    
    # Find the calendar month node for the current month
    query = """
    MATCH (m:CalendarMonth)
    WHERE m.year = $year AND m.month = $month
    RETURN m
    """
    
    with driver_tools.get_session(database=db_name) as session:
        result = session.run(query, year=str(today.year), month=str(today.month))
        month_node = result.single()
        
        if not month_node:
            raise HTTPException(status_code=404, detail="No default node found for context: month")
            
        node = month_node["m"]
        node_data = dict(node)
        converted_data = convert_neo4j_values(node_data)
        
        return {
            "status": "success",
            "node": {
                "id": node["uuid_string"],
                "path": node["path"],
                "type": "CalendarMonth",
                "label": node.get("title", "Calendar Month"),
                "data": converted_data
            }
        }

@router.get("/debug-list-nodes")
async def debug_list_nodes(db_name: str) -> Dict[str, Any]:
    """Debug endpoint to list all nodes in a database."""
    try:
        with driver_tools.get_session(database=db_name) as session:
            query = """
            MATCH (n)
            RETURN labels(n) as labels, n.uuid_string as uuid, n.user_name as name, n.cc_username as username
            LIMIT 20
            """
            result = session.run(query)
            nodes = []
            for record in result:
                nodes.append({
                    "labels": list(record["labels"]),
                    "uuid": record["uuid"],
                    "name": record["name"],
                    "username": record["username"]
                })
            
            return {
                "status": "success",
                "db_name": db_name,
                "node_count": len(nodes),
                "nodes": nodes
            }
    except Exception as e:
        return {
            "status": "error",
            "db_name": db_name,
            "error": str(e)
        }

@router.get("/get-default-node/{context}")
async def get_default_node(context: str, db_name: str, base_context: str | None = None) -> Dict[str, Any]:
    """Get the default node for a given context."""
    try:
        # Handle special cases for week and month
        if context == 'week':
            return get_default_node_week(db_name)
        elif context == 'month':
            return get_default_node_month(db_name)

        # Map contexts to their default node queries
        context_queries = {
            # Base Contexts
            'profile': """
                MATCH (n:User)
                RETURN n LIMIT 1
            """,
            'worker': """
                MATCH (n)
                WHERE n:SchoolAdmin OR n:Teacher OR n:Student OR n:Developer OR n:SuperAdmin
                RETURN n LIMIT 1
            """,
            'calendar': """
                MATCH (n:Calendar)
                RETURN n LIMIT 1
            """,
            'teaching': """
                MATCH (n:Teacher)
                RETURN n LIMIT 1
            """,
            'school': """
                MATCH (n:School)
                RETURN n LIMIT 1
            """,
            'department': """
                MATCH (n:Department)
                RETURN n LIMIT 1
            """,
            'class': """
                MATCH (n:Class)
                RETURN n LIMIT 1
            """,

            # Extended Contexts - Overview queries for each base context
            'overview': """
                MATCH (n)
                WHERE CASE $base_context
                    WHEN 'profile' THEN n:User
                    WHEN 'calendar' THEN n:Calendar
                    WHEN 'teaching' THEN n:Teacher
                    WHEN 'school' THEN n:School
                    WHEN 'department' THEN n:Department
                    WHEN 'class' THEN n:Class
                    ELSE false
                END
                RETURN n LIMIT 1
            """,

            # Extended Contexts - User
            'settings': """
                MATCH (n:User)
                RETURN n LIMIT 1
            """,
            'history': """
                MATCH (n:User)
                RETURN n LIMIT 1
            """,
            'journal': """
                MATCH (n:Journal)
                RETURN n LIMIT 1
            """,
            'planner': """
                MATCH (n:Planner)
                RETURN n LIMIT 1
            """,

            # Extended Contexts - Calendar
            'day': """
                MATCH (n:CalendarDay)
                WHERE date(n.date) = date()
                RETURN n LIMIT 1
            """,
            'year': """
                MATCH (n:CalendarYear)
                WHERE n.year = toString(date().year)
                RETURN n LIMIT 1
            """,

            # Extended Contexts - Teaching
            'timetable': """
                MATCH (n:UserTeacherTimetable)
                RETURN n LIMIT 1
            """,
            'classes': """
                MATCH (n:Class)
                RETURN n LIMIT 1
            """,
            'lessons': """
                MATCH (n:TimetableLesson)
                RETURN n LIMIT 1
            """,

            # Extended Contexts - School
            'departments': """
                MATCH (n:Department)
                RETURN n LIMIT 1
            """,
            'staff': """
                MATCH (n:Teacher)
                RETURN n LIMIT 1
            """,

            # Extended Contexts - Department
            'teachers': """
                MATCH (n:Teacher)
                RETURN n LIMIT 1
            """,
            'subjects': """
                MATCH (n:Subject)
                RETURN n LIMIT 1
            """,

            # Extended Contexts - Class
            'students': """
                MATCH (n:Student)
                RETURN n LIMIT 1
            """
        }

        if context not in context_queries:
            raise HTTPException(status_code=400, detail=f"Invalid context: {context}")

        query = context_queries[context]
        
        with driver_tools.get_session(database=db_name) as session:
            # For overview context, we need to pass the database name as a parameter
            params = {'db_name': db_name, 'base_context': base_context} if context == 'overview' else {}
            result = session.run(query, params)
            record = result.single()
            
            if not record:
                raise HTTPException(
                    status_code=404, 
                    detail=f"No default node found for context: {context}"
                )
            
            node = record["n"]
            node_data = dict(node)
            
            # Convert Neo4j types to JSON-serializable types
            converted_data = convert_neo4j_values(node_data)
            
            return {
                "status": "success",
                "node": {
                    "id": node["uuid_string"],
                    "path": node["path"],
                    "node_storage_path": node.get("node_storage_path", node["path"]),
                    "type": list(node.labels)[0],
                    "label": node.get("title", ""),
                    "data": converted_data
                }
            }

    except Exception as e:
        logger.error(f"Error getting default node: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))