# main.py - FastAPI application for TNA system

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from typing import Dict, List, Optional
import json
import logging
from datetime import datetime
import uvicorn

# Import our core TNA system
from tna_core import (
    create_tna_system,
    process_department_analysis,
    process_skills_and_courses_analysis,
    IntegratedTNASystem
)

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# FastAPI app
app = FastAPI(
    title="Training Needs Analysis (TNA) System",
    description="Comprehensive TNA system with department inference, skill analysis, and course recommendations",
    version="1.0.0",
    docs_url="/docs",
    redoc_url="/redoc"
)

# =====================================
# PYDANTIC MODELS FOR API
# =====================================

class OrganizationDepartment(BaseModel):
    id: int = Field(..., description="Department ID")
    name: str = Field(..., description="Department name")

class DepartmentRequest(BaseModel):
    user_prompt: str = Field(..., description="User's business goal or challenge")
    organization_departments: List[OrganizationDepartment] = Field(..., description="List of organization departments")

class DepartmentResponse(BaseModel):
    identified_department: str = Field(..., description="Identified department name")
    department_id: int = Field(..., description="Department ID (0 if no match)")

class FilteredSkill(BaseModel):
    skill_id: int = Field(..., description="Skill ID")
    skill_name: str = Field(..., description="Skill name")
    skill_level: Optional[str] = Field(None, description="Skill level")
    skill_count: Optional[int] = Field(None, description="Number of employees with this skill")

class AllSkill(BaseModel):
    skill_id: int = Field(..., description="Skill ID")
    skill_name: str = Field(..., description="Skill name")

class OfflineCourse(BaseModel):
    course_id: str = Field(..., description="Course ID")
    course_name: str = Field(..., description="Course name")
    short_description: str = Field(..., description="Short course description")
    description: str = Field(..., description="Full course description")
    skills: List[str] = Field(default=[], description="Course skill tags")

class SkillAnalysisRequest(BaseModel):
    user_query: str = Field(..., description="User's business goal or challenge")
    admin_name: str = Field(..., description="Organization/admin name")
    department_name: str = Field(..., description="Department name")
    filtered_skills: List[FilteredSkill] = Field(..., description="Current department skills")
    all_skills_data: List[AllSkill] = Field(..., description="All organizational skills")
    offline_courses: List[OfflineCourse] = Field(..., description="Available offline courses")

class SkillMatch(BaseModel):
    user_skill: str = Field(..., description="User required skill")
    course_skill: str = Field(..., description="Course taught skill")
    confidence: float = Field(..., description="Match confidence score")

class InferredSkill(BaseModel):
    skill_name: str = Field(..., description="Inferred skill name")
    skill_level: str = Field(..., description="Skill level")

class CourseRecommendation(BaseModel):
    course_id: str = Field(..., description="Course ID")
    name: str = Field(..., description="Course name")
    matched_skills: List[str] = Field(..., description="Skills that matched user needs")
    justification: str = Field(..., description="LLM justification for recommendation")
    inferred_skills: List[InferredSkill] = Field(..., description="Skills inferred from course")
    skill_matches: List[SkillMatch] = Field(..., description="Detailed skill matches")

class SkillAndCourseResponse(BaseModel):
    skill_analysis: str = Field(..., description="Strategic skill analysis report")
    courses_offline: List[CourseRecommendation] = Field(..., description="Recommended offline courses")

class HealthResponse(BaseModel):
    status: str
    timestamp: str
    system_info: Dict[str, str]

class ErrorResponse(BaseModel):
    error: str
    detail: str
    timestamp: str

# =====================================
# GLOBAL TNA SYSTEM INSTANCE
# =====================================

# Initialize the TNA system once at startup
tna_system: Optional[IntegratedTNASystem] = None

@app.on_event("startup")
async def startup_event():
    """Initialize TNA system on startup"""
    global tna_system
    try:
        logger.info("Initializing TNA system...")
        tna_system = create_tna_system()
        logger.info("TNA system initialized successfully")
    except Exception as e:
        logger.error(f"Failed to initialize TNA system: {e}")
        raise

@app.on_event("shutdown")
async def shutdown_event():
    """Cleanup on shutdown"""
    logger.info("TNA system shutting down...")

# =====================================
# FASTAPI ENDPOINTS
# =====================================

@app.get("/", tags=["Root"])
async def root():
    """Root endpoint with API information"""
    return {
        "message": "Training Needs Analysis (TNA) System API",
        "version": "1.0.0",
        "description": "Comprehensive TNA system with department inference, skill analysis, and course recommendations",
        "endpoints": {
            "department_analysis": "/analyze/department",
            "skills_and_courses": "/analyze/skills-and-courses",
            "health_check": "/health",
            "documentation": "/docs"
        }
    }

@app.post(
    "/analyze/department",
    response_model=DepartmentResponse,
    tags=["Department Analysis"],
    summary="Analyze Department",
    description="Identify the most relevant department based on user prompt and organization departments"
)
async def analyze_department(request: DepartmentRequest):
    """
    Endpoint for department inference (Problem Statement 1)
    
    This endpoint analyzes the user's business goal and maps it to the most relevant
    department in the organization using AI-powered department inference and 
    similarity matching with a 96% threshold.
    """
    try:
        if not tna_system:
            raise HTTPException(status_code=500, detail="TNA system not initialized")
        
        logger.info(f"Processing department analysis for prompt: '{request.user_prompt}'")
        
        # Convert Pydantic models to dictionaries for core system
        departments_dict = [
            {"id": dept.id, "name": dept.name} 
            for dept in request.organization_departments
        ]
        
        # Process using core system
        result = process_department_analysis(
            tna_system,
            request.user_prompt,
            departments_dict
        )
        
        logger.info(f"Department analysis completed: {result['identified_department']} (ID: {result['department_id']})")
        
        return DepartmentResponse(
            identified_department=result['identified_department'],
            department_id=result['department_id']
        )
        
    except Exception as e:
        logger.error(f"Error in department analysis: {e}")
        raise HTTPException(
            status_code=500,
            detail=f"Error in department analysis: {str(e)}"
        )

@app.post(
    "/analyze/skills-and-courses",
    response_model=SkillAndCourseResponse,
    tags=["Skills & Courses Analysis"],
    summary="Analyze Skills and Recommend Courses",
    description="Perform comprehensive skill gap analysis and course recommendations"
)
async def analyze_skills_and_courses(request: SkillAnalysisRequest):
    """
    Endpoint for skill analysis and course recommendation (Problem Statements 2 & 3)
    
    This endpoint performs:
    1. Two-step LLM skill analysis with field identification
    2. Intelligent organizational skill filtering
    3. External skill gap filling
    4. Four-step course recommendation pipeline
    5. Strategic report generation
    
    Returns a strategic skill analysis report and recommended courses with detailed
    skill matches and justifications.
    """
    try:
        if not tna_system:
            raise HTTPException(status_code=500, detail="TNA system not initialized")
        
        logger.info(f"Processing skill and course analysis for: '{request.user_query}'")
        
        # Convert Pydantic models to dictionaries for core system
        filtered_skills_dict = [
            {
                "skill_id": skill.skill_id,
                "skill_name": skill.skill_name,
                "skill_level": skill.skill_level,
                "skill_count": skill.skill_count
            }
            for skill in request.filtered_skills
        ]
        
        all_skills_dict = [
            {"skill_id": skill.skill_id, "skill_name": skill.skill_name}
            for skill in request.all_skills_data
        ]
        
        courses_dict = [
            {
                "course_id": course.course_id,
                "course_name": course.course_name,
                "short_description": course.short_description,
                "description": course.description,
                "skills": course.skills
            }
            for course in request.offline_courses
        ]
        
        # Process using core system
        result = process_skills_and_courses_analysis(
            tna_system,
            request.user_query,
            request.admin_name,
            request.department_name,
            filtered_skills_dict,
            all_skills_dict,
            courses_dict
        )
        
        logger.info(f"Skill and course analysis completed: {len(result['courses_offline'])} courses recommended")
        
        # Convert result to Pydantic models
        course_recommendations = []
        for course in result['courses_offline']:
            course_recommendations.append(CourseRecommendation(
                course_id=course['course_id'],
                name=course['name'],
                matched_skills=course['matched_skills'],
                justification=course['justification'],
                inferred_skills=[
                    InferredSkill(skill_name=skill['skill_name'], skill_level=skill['skill_level'])
                    for skill in course['inferred_skills']
                ],
                skill_matches=[
                    SkillMatch(
                        user_skill=match['user_skill'],
                        course_skill=match['course_skill'],
                        confidence=match['confidence']
                    )
                    for match in course['skill_matches']
                ]
            ))
        
        return SkillAndCourseResponse(
            skill_analysis=result['skill_analysis'],
            courses_offline=course_recommendations
        )
        
    except Exception as e:
        logger.error(f"Error in skill and course analysis: {e}")
        raise HTTPException(
            status_code=500,
            detail=f"Error in skill and course analysis: {str(e)}"
        )