import os
from fastapi import APIRouter, HTTPException
from typing import List, Dict, Any, Optional
from datetime import datetime, timedelta
from modules.logger_tool import initialise_logger
from modules.database.tools import neo4j_driver_tools as driver_tools

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

@router.get("/get-calendar-structure")
async def get_calendar_structure(db_name: str) -> Dict[str, Any]:
    """
    Get the complete calendar structure including years, months, weeks, and days.
    """
    try:
        # Get all calendar nodes in a single query
        query = """
        // Match all calendar-related nodes
        MATCH (y:CalendarYear)
        OPTIONAL MATCH (y)-[:YEAR_INCLUDES_MONTH]->(m:CalendarMonth)
        OPTIONAL MATCH (m)-[:MONTH_INCLUDES_DAY]->(d:CalendarDay)
        OPTIONAL MATCH (w:CalendarWeek)-[:WEEK_INCLUDES_DAY]->(d)
        WITH y, m, w, d
        ORDER BY y.date, m.date, w.date, d.date

        // Collect all nodes with dates converted to strings
        RETURN {
            years: collect(DISTINCT {
                id: y.uuid_string,
                path: y.node_storage_path,
                date: toString(y.date),
                __primarylabel__: 'CalendarYear'
            }),
            months: collect(DISTINCT {
                id: m.uuid_string,
                path: m.node_storage_path,
                date: toString(m.date),
                __primarylabel__: 'CalendarMonth'
            }),
            weeks: collect(DISTINCT {
                id: w.uuid_string,
                path: w.node_storage_path,
                date: toString(w.date),
                __primarylabel__: 'CalendarWeek'
            }),
            days: collect(DISTINCT {
                id: d.uuid_string,
                path: d.node_storage_path,
                date: toString(d.date),
                week_id: w.uuid_string,
                month_id: m.uuid_string,
                __primarylabel__: 'CalendarDay'
            })
        } as structure
        """

        with driver_tools.get_session(database=db_name) as session:
            result = session.run(query)
            record = result.single()
            if not record:
                raise HTTPException(status_code=404, detail="Calendar structure not found")
            
            structure = record["structure"]
            
            # Find current day using string comparison
            today = datetime.now().strftime("%Y-%m-%d")
            current_day = next(
                (day["id"] for day in structure["days"] 
                 if day["date"] == today),
                structure["days"][0]["id"] if structure["days"] else None
            )

            return {
                "status": "success",
                "structure": {
                    "years": structure["years"],
                    "months": structure["months"],
                    "weeks": structure["weeks"],
                    "days": structure["days"],
                    "currentDay": current_day
                }
            }

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

@router.get("/get-calendar-days")
async def get_calendar_days(db_name: str, start_date: str, end_date: str) -> Dict[str, Any]:
    """
    Get all calendar days in a date range.
    """
    try:
        query = """
        MATCH (d:CalendarDay)
        WHERE date(d.date) >= date($start_date) AND date(d.date) <= date($end_date)
        OPTIONAL MATCH (w:CalendarWeek)-[:WEEK_INCLUDES_DAY]->(d)
        OPTIONAL MATCH (m:CalendarMonth)-[:MONTH_INCLUDES_DAY]->(d)
        RETURN {
            id: d.uuid_string,
            path: d.node_storage_path,
            date: d.date,
            week_id: w.uuid_string,
            month_id: m.uuid_string,
            __primarylabel__: 'CalendarDay'
        } as day
        ORDER BY d.date
        """

        with driver_tools.get_session(database=db_name) as session:
            result = session.run(query, start_date=start_date, end_date=end_date)
            days = [record["day"] for record in result]

            return {
                "status": "success",
                "days": days
            }

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

@router.get("/get-calendar-weeks")
async def get_calendar_weeks(db_name: str, start_date: str, end_date: str) -> Dict[str, Any]:
    """
    Get all calendar weeks in a date range.
    """
    try:
        query = """
        MATCH (w:CalendarWeek)-[:WEEK_INCLUDES_DAY]->(d:CalendarDay)
        WHERE date(w.date) >= date($start_date) AND date(w.date) <= date($end_date)
        WITH w, collect(d) as days
        RETURN {
            id: w.uuid_string,
            path: w.node_storage_path,
            date: w.date,
            day_ids: [day in days | day.uuid_string],
            __primarylabel__: 'CalendarWeek'
        } as week
        ORDER BY w.date
        """

        with driver_tools.get_session(database=db_name) as session:
            result = session.run(query, start_date=start_date, end_date=end_date)
            weeks = [record["week"] for record in result]

            return {
                "status": "success",
                "weeks": weeks
            }

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

@router.get("/get-calendar-months")
async def get_calendar_months(db_name: str, start_date: str, end_date: str) -> Dict[str, Any]:
    """
    Get all calendar months in a date range.
    """
    try:
        query = """
        MATCH (m:CalendarMonth)-[:MONTH_INCLUDES_DAY]->(d:CalendarDay)
        WHERE date(m.date) >= date($start_date) AND date(m.date) <= date($end_date)
        WITH m, collect(d) as days
        RETURN {
            id: m.uuid_string,
            path: m.node_storage_path,
            date: m.date,
            day_ids: [day in days | day.uuid_string],
            __primarylabel__: 'CalendarMonth'
        } as month
        ORDER BY m.date
        """

        with driver_tools.get_session(database=db_name) as session:
            result = session.run(query, start_date=start_date, end_date=end_date)
            months = [record["month"] for record in result]

            return {
                "status": "success",
                "months": months
            }

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

@router.get("/get-calendar-years")
async def get_calendar_years(db_name: str) -> Dict[str, Any]:
    """
    Get all calendar years.
    """
    try:
        query = """
        MATCH (y:CalendarYear)-[:YEAR_INCLUDES_MONTH]->(m:CalendarMonth)
        WITH y, collect(m) as months
        RETURN {
            id: y.uuid_string,
            path: y.node_storage_path,
            date: y.date,
            month_ids: [month in months | month.uuid_string],
            __primarylabel__: 'CalendarYear'
        } as year
        ORDER BY y.date
        """

        with driver_tools.get_session(database=db_name) as session:
            result = session.run(query)
            years = [record["year"] for record in result]

            return {
                "status": "success",
                "years": years
            }

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