"""
管理 API 处理器
提供项目映射和 API 密钥管理功能
"""

import secrets
from datetime import datetime, timedelta
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from sqlalchemy.orm import Session

from app.database import get_db
from app.models.api_key import APIKey
from app.models.project_mapping import ProjectMapping
from app.auth import get_current_user

router = APIRouter(prefix="/api/admin", tags=["admin"])

# API 密钥相关模型
class APIKeyResponse(BaseModel):
    id: int
    name: str
    key_prefix: str
    created_at: datetime
    last_used: datetime
    is_active: bool

    class Config:
        from_attributes = True

class CreateAPIKeyRequest(BaseModel):
    name: str

class CreateAPIKeyResponse(BaseModel):
    id: int
    name: str
    key: str
    created_at: datetime

# 项目映射相关模型
class ProjectMappingRequest(BaseModel):
    repository_name: str
    default_job: str
    branch_jobs: Optional[List[dict]] = []
    branch_patterns: Optional[List[dict]] = []

class ProjectMappingResponse(BaseModel):
    id: int
    repository_name: str
    default_job: str
    branch_jobs: List[dict]
    branch_patterns: List[dict]
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True

# API 密钥管理端点
@router.get("/api-keys", response_model=List[APIKeyResponse])
async def list_api_keys(
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """列出所有 API 密钥"""
    try:
        api_keys = db.query(APIKey).order_by(APIKey.created_at.desc()).all()
        return api_keys
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to list API keys: {str(e)}")

@router.post("/api-keys", response_model=CreateAPIKeyResponse)
async def create_api_key(
    request: CreateAPIKeyRequest,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """创建新的 API 密钥"""
    try:
        # 生成 API 密钥
        api_key = secrets.token_urlsafe(32)
        key_prefix = api_key[:8]  # 显示前8位作为前缀
        
        # 创建数据库记录
        db_api_key = APIKey(
            name=request.name,
            key_hash=api_key,  # 实际应用中应该哈希存储
            key_prefix=key_prefix,
            created_at=datetime.utcnow(),
            last_used=datetime.utcnow(),
            is_active=True
        )
        
        db.add(db_api_key)
        db.commit()
        db.refresh(db_api_key)
        
        return CreateAPIKeyResponse(
            id=db_api_key.id,
            name=db_api_key.name,
            key=api_key,  # 只在创建时返回完整密钥
            created_at=db_api_key.created_at
        )
        
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Failed to create API key: {str(e)}")

@router.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)
):
    """删除 API 密钥"""
    try:
        api_key = db.query(APIKey).filter(APIKey.id == key_id).first()
        if not api_key:
            raise HTTPException(status_code=404, detail="API key not found")
        
        db.delete(api_key)
        db.commit()
        
        return {"message": "API key deleted successfully"}
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Failed to delete API key: {str(e)}")

@router.post("/api-keys/{key_id}/revoke")
async def revoke_api_key(
    key_id: int,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """撤销 API 密钥"""
    try:
        api_key = db.query(APIKey).filter(APIKey.id == key_id).first()
        if not api_key:
            raise HTTPException(status_code=404, detail="API key not found")
        
        api_key.is_active = False
        db.commit()
        
        return {"message": "API key revoked successfully"}
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Failed to revoke API key: {str(e)}")

# 项目映射管理端点
@router.get("/projects", response_model=List[ProjectMappingResponse])
async def list_project_mappings(
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """列出所有项目映射"""
    try:
        mappings = db.query(ProjectMapping).order_by(ProjectMapping.created_at.desc()).all()
        return mappings
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to list project mappings: {str(e)}")

@router.post("/projects", response_model=ProjectMappingResponse)
async def create_project_mapping(
    request: ProjectMappingRequest,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """创建项目映射"""
    try:
        # 检查是否已存在
        existing = db.query(ProjectMapping).filter(
            ProjectMapping.repository_name == request.repository_name
        ).first()
        
        if existing:
            raise HTTPException(status_code=400, detail="Project mapping already exists")
        
        # 创建新映射
        mapping = ProjectMapping(
            repository_name=request.repository_name,
            default_job=request.default_job,
            branch_jobs=request.branch_jobs or [],
            branch_patterns=request.branch_patterns or [],
            created_at=datetime.utcnow(),
            updated_at=datetime.utcnow()
        )
        
        db.add(mapping)
        db.commit()
        db.refresh(mapping)
        
        return mapping
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Failed to create project mapping: {str(e)}")

@router.get("/projects/{repository_name}", response_model=ProjectMappingResponse)
async def get_project_mapping(
    repository_name: str,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """获取项目映射"""
    try:
        mapping = db.query(ProjectMapping).filter(
            ProjectMapping.repository_name == repository_name
        ).first()
        
        if not mapping:
            raise HTTPException(status_code=404, detail="Project mapping not found")
        
        return mapping
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get project mapping: {str(e)}")

@router.delete("/projects/{repository_name}")
async def delete_project_mapping(
    repository_name: str,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """删除项目映射"""
    try:
        mapping = db.query(ProjectMapping).filter(
            ProjectMapping.repository_name == repository_name
        ).first()
        
        if not mapping:
            raise HTTPException(status_code=404, detail="Project mapping not found")
        
        db.delete(mapping)
        db.commit()
        
        return {"message": "Project mapping deleted successfully"}
        
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Failed to delete project mapping: {str(e)}")

# 统计信息端点
@router.get("/stats")
async def get_admin_stats(
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user)
):
    """获取管理统计信息"""
    try:
        # API 密钥统计
        total_keys = db.query(APIKey).count()
        active_keys = db.query(APIKey).filter(APIKey.is_active == True).count()
        
        # 最近使用的密钥
        recent_keys = db.query(APIKey).filter(
            APIKey.last_used >= datetime.utcnow() - timedelta(days=7)
        ).count()
        
        # 项目映射统计
        total_mappings = db.query(ProjectMapping).count()
        
        return {
            "api_keys": {
                "total": total_keys,
                "active": active_keys,
                "recently_used": recent_keys
            },
            "project_mappings": {
                "total": total_mappings
            }
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get admin stats: {str(e)}") 