from fastapi import FastAPI, Request, Depends, HTTPException, status
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
import os
import time
import psutil
from datetime import datetime, timedelta

# Import database models
from app.models.database import create_tables, get_db, APIKey, ProjectMapping, TriggerLog
from app.auth.middleware import auth_middleware, get_current_user
from app.config import settings

# Create FastAPI app
app = FastAPI(
    title="Gitea Webhook Ambassador",
    description="High-performance Gitea to Jenkins Webhook service",
    version="2.0.0"
)

# Add CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Create database tables
create_tables()

# Mount static files
app.mount("/static", StaticFiles(directory="app/static"), name="static")

# Set up templates
templates = Jinja2Templates(directory="app/templates")

# Startup time
start_time = datetime.now()

@app.get("/", response_class=HTMLResponse)
async def root(request: Request):
    """Root path - redirect to login page"""
    return RedirectResponse(url="/login")

@app.get("/login", response_class=HTMLResponse)
async def login_page(request: Request):
    """Login page"""
    return templates.TemplateResponse("login.html", {"request": request})

@app.get("/dashboard", response_class=HTMLResponse)
async def dashboard_page(request: Request):
    """Dashboard page"""
    return templates.TemplateResponse("dashboard.html", {"request": request})

@app.post("/api/auth/login")
async def login(request: dict):
    """Admin login"""
    admin_key = os.getenv("ADMIN_SECRET_KEY", "admin-secret-key-change-in-production")
    
    if request.get("secret_key") != admin_key:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid secret key"
        )
    
    # Generate JWT token
    token = auth_middleware.create_access_token(
        data={"sub": "admin", "role": "admin"}
    )
    
    return {"token": token}

@app.get("/api/stats")
async def get_stats(db: Session = Depends(get_db), current_user: dict = Depends(get_current_user)):
    """Get statistics"""
    try:
        # Get total number of projects
        total_projects = db.query(ProjectMapping).count()
        
        # Get total number of API keys
        total_api_keys = db.query(APIKey).count()
        
        # Get today's trigger count
        today = datetime.now().date()
        today_triggers = db.query(TriggerLog).filter(
            TriggerLog.created_at >= today
        ).count()
        
        # Get successful trigger count
        successful_triggers = db.query(TriggerLog).filter(
            TriggerLog.status == "success"
        ).count()
        
        return {
            "total_projects": total_projects,
            "total_api_keys": total_api_keys,
            "today_triggers": today_triggers,
            "successful_triggers": successful_triggers
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get statistics: {str(e)}")

@app.get("/api/keys", response_model=dict)
async def list_api_keys(db: Session = Depends(get_db), current_user: dict = Depends(get_current_user)):
    """Get all API keys (frontend compatible)"""
    try:
        keys = db.query(APIKey).order_by(APIKey.created_at.desc()).all()
        return {
            "keys": [
                {
                    "id": key.id,
                    "key": key.key,
                    "description": key.description,
                    "created_at": key.created_at.isoformat()
                }
                for key in keys
            ]
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get API keys: {str(e)}")

@app.post("/api/keys", response_model=dict)
async def create_api_key(
    request: dict,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """Create a new API key (frontend compatible)"""
    try:
        # Generate new API key
        api_key_value = auth_middleware.generate_api_key()
        
        # Save to database
        db_key = APIKey(
            key=api_key_value,
            description=request.get("description", "")
        )
        
        db.add(db_key)
        db.commit()
        db.refresh(db_key)
        
        return {
            "id": db_key.id,
            "key": db_key.key,
            "description": db_key.description,
            "created_at": db_key.created_at.isoformat()
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to create API key: {str(e)}")

@app.delete("/api/keys/{key_id}")
async def delete_api_key(
    key_id: int,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """Delete API key (frontend compatible)"""
    try:
        key = db.query(APIKey).filter(APIKey.id == key_id).first()
        
        if not key:
            raise HTTPException(status_code=404, detail="API key does not exist")
        
        db.delete(key)
        db.commit()
        
        return {"message": "API key deleted successfully"}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to delete API key: {str(e)}")

@app.get("/api/projects/", response_model=dict)
async def list_projects(db: Session = Depends(get_db), current_user: dict = Depends(get_current_user)):
    """Get all projects (frontend compatible)"""
    try:
        projects = db.query(ProjectMapping).order_by(ProjectMapping.created_at.desc()).all()
        return {
            "projects": [
                {
                    "id": project.id,
                    "name": project.repository_name.split('/')[-1],
                    "jenkinsJob": project.default_job,
                    "giteaRepo": project.repository_name,
                    "created_at": project.created_at.isoformat()
                }
                for project in projects
            ]
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get project list: {str(e)}")

@app.post("/api/projects/", response_model=dict)
async def create_project(
    request: dict,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """Create a new project (frontend compatible)"""
    try:
        # Check if project already exists
        existing_project = db.query(ProjectMapping).filter(
            ProjectMapping.repository_name == request["giteaRepo"]
        ).first()
        
        if existing_project:
            raise HTTPException(status_code=400, detail="Project already exists")
        
        # Create new project
        project = ProjectMapping(
            repository_name=request["giteaRepo"],
            default_job=request["jenkinsJob"]
        )
        
        db.add(project)
        db.commit()
        db.refresh(project)
        
        return {
            "id": project.id,
            "name": request["name"],
            "jenkinsJob": project.default_job,
            "giteaRepo": project.repository_name,
            "created_at": project.created_at.isoformat()
        }
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to create project: {str(e)}")

@app.delete("/api/projects/{project_id}")
async def delete_project(
    project_id: int,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """Delete project (frontend compatible)"""
    try:
        project = db.query(ProjectMapping).filter(ProjectMapping.id == project_id).first()
        
        if not project:
            raise HTTPException(status_code=404, detail="Project does not exist")
        
        db.delete(project)
        db.commit()
        
        return {"message": "Project deleted successfully"}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to delete project: {str(e)}")

@app.get("/health")
async def health_check():
    """Health check endpoint"""
    try:
        # Calculate uptime
        uptime = datetime.now() - start_time
        uptime_str = str(uptime).split('.')[0]  # Remove microseconds
        
        # Get memory usage
        process = psutil.Process()
        memory_info = process.memory_info()
        memory_mb = memory_info.rss / 1024 / 1024
        
        return {
            "status": "healthy",
            "version": "2.0.0",
            "uptime": uptime_str,
            "memory": f"{memory_mb:.1f} MB",
            "timestamp": datetime.now().isoformat()
        }
    except Exception as e:
        return {
            "status": "unhealthy",
            "error": str(e),
            "timestamp": datetime.now().isoformat()
        }

@app.get("/api/logs")
async def get_logs(
    startTime: str = None,
    endTime: str = None,
    level: str = None,
    query: str = None,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """Get logs (simplified version)"""
    try:
        # Here should be the real log query logic
        # Currently returns mock data
        logs = [
            {
                "timestamp": datetime.now().isoformat(),
                "level": "info",
                "message": "System running normally"
            }
        ]
        
        return {"logs": logs}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get logs: {str(e)}")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000) 