"""FastAPI application for NoticeCard server."""

from pathlib import Path
from typing import List
from fastapi import FastAPI, HTTPException, Depends, Request
from fastapi.responses import HTMLResponse, StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
import json

from .models import Card, get_session_maker, init_db
from .schemas import CardCreate, CardUpdate, CardResponse
from .templates import get_index_html

# Global variables for database
_session_maker = None
_db_path = None


def get_db():
    """Dependency to get database session."""
    if _session_maker is None:
        raise RuntimeError("Database not initialized")
    db = _session_maker()
    try:
        yield db
    finally:
        db.close()


def create_app(db_path: str) -> FastAPI:
    """Create and configure FastAPI application."""
    global _session_maker, _db_path
    
    _db_path = db_path
    engine = init_db(db_path)
    _session_maker = get_session_maker(engine)
    
    app = FastAPI(
        title="NoticeCard API",
        description="RESTful API for managing notice cards with web UI",
        version="0.1.0",
        docs_url="/docs",
        redoc_url="/redoc",
        openapi_url="/openapi.json"
    )
    
    # Add CORS middleware
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    
    # API Routes
    @app.get("/", response_class=HTMLResponse, include_in_schema=False)
    async def root():
        """Serve the main web UI."""
        return get_index_html()
    
    @app.post("/mcp", include_in_schema=False)
    async def mcp_endpoint(request: Request):
        """MCP streaming endpoint for tool calls."""
        body = await request.json()
        method = body.get("method")
        params = body.get("params", {})
        request_id = body.get("id")
        
        async def stream_response():
            try:
                if method == "initialize":
                    result = {
                        "jsonrpc": "2.0",
                        "id": request_id,
                        "result": {
                            "protocolVersion": "2024-11-05",
                            "capabilities": {
                                "tools": {}
                            },
                            "serverInfo": {
                                "name": "noticecard",
                                "version": "0.2.0"
                            }
                        }
                    }
                    yield json.dumps(result) + "\n"
                
                elif method == "tools/list":
                    result = {
                        "jsonrpc": "2.0",
                        "id": request_id,
                        "result": {
                            "tools": [
                                {
                                    "name": "create_card",
                                    "description": "创建新卡片",
                                    "inputSchema": {
                                        "type": "object",
                                        "properties": {
                                            "title": {"type": "string", "description": "卡片标题"},
                                            "description": {"type": "string", "description": "卡片描述（可选）"}
                                        },
                                        "required": ["title"]
                                    }
                                },
                                {
                                    "name": "list_cards",
                                    "description": "获取所有卡片",
                                    "inputSchema": {
                                        "type": "object",
                                        "properties": {
                                            "skip": {"type": "number", "description": "跳过数量", "default": 0},
                                            "limit": {"type": "number", "description": "限制数量", "default": 100}
                                        }
                                    }
                                },
                                {
                                    "name": "get_card",
                                    "description": "获取指定卡片",
                                    "inputSchema": {
                                        "type": "object",
                                        "properties": {
                                            "card_id": {"type": "number", "description": "卡片ID"}
                                        },
                                        "required": ["card_id"]
                                    }
                                },
                                {
                                    "name": "update_card",
                                    "description": "更新卡片",
                                    "inputSchema": {
                                        "type": "object",
                                        "properties": {
                                            "card_id": {"type": "number", "description": "卡片ID"},
                                            "title": {"type": "string", "description": "新标题（可选）"},
                                            "description": {"type": "string", "description": "新描述（可选）"}
                                        },
                                        "required": ["card_id"]
                                    }
                                },
                                {
                                    "name": "delete_card",
                                    "description": "删除卡片",
                                    "inputSchema": {
                                        "type": "object",
                                        "properties": {
                                            "card_id": {"type": "number", "description": "卡片ID"}
                                        },
                                        "required": ["card_id"]
                                    }
                                }
                            ]
                        }
                    }
                    yield json.dumps(result) + "\n"
                
                elif method == "tools/call":
                    tool_name = params.get("name")
                    tool_args = params.get("arguments", {})
                    db = next(get_db())
                    
                    try:
                        if tool_name == "create_card":
                            card = Card(**tool_args)
                            db.add(card)
                            db.commit()
                            db.refresh(card)
                            result = {
                                "jsonrpc": "2.0",
                                "id": request_id,
                                "result": {
                                    "content": [{
                                        "type": "text",
                                        "text": f"✅ 创建成功！\nID: {card.id}\n标题: {card.title}\n描述: {card.description or '无'}"
                                    }]
                                }
                            }
                        
                        elif tool_name == "list_cards":
                            skip = int(tool_args.get("skip", 0))
                            limit = int(tool_args.get("limit", 100))
                            cards = db.query(Card).order_by(Card.created_at.desc()).offset(skip).limit(limit).all()
                            cards_text = "\n".join([f"[{c.id}] {c.title}" for c in cards])
                            result = {
                                "jsonrpc": "2.0",
                                "id": request_id,
                                "result": {
                                    "content": [{
                                        "type": "text",
                                        "text": f"📋 共 {len(cards)} 张卡片:\n\n{cards_text}" if cards else "📭 暂无卡片"
                                    }]
                                }
                            }
                        
                        elif tool_name == "get_card":
                            card_id = int(tool_args["card_id"])
                            card = db.query(Card).filter(Card.id == card_id).first()
                            if not card:
                                result = {
                                    "jsonrpc": "2.0",
                                    "id": request_id,
                                    "result": {
                                        "content": [{
                                            "type": "text",
                                            "text": f"❌ 未找到卡片 {card_id}"
                                        }]
                                    }
                                }
                            else:
                                result = {
                                    "jsonrpc": "2.0",
                                    "id": request_id,
                                    "result": {
                                        "content": [{
                                            "type": "text",
                                            "text": f"📄 卡片详情\n\nID: {card.id}\n标题: {card.title}\n描述: {card.description or '无'}\n创建时间: {card.created_at}\n更新时间: {card.updated_at}"
                                        }]
                                    }
                                }
                        
                        elif tool_name == "update_card":
                            card_id = int(tool_args.pop("card_id"))
                            card = db.query(Card).filter(Card.id == card_id).first()
                            if not card:
                                result = {
                                    "jsonrpc": "2.0",
                                    "id": request_id,
                                    "result": {
                                        "content": [{
                                            "type": "text",
                                            "text": f"❌ 未找到卡片 {card_id}"
                                        }]
                                    }
                                }
                            else:
                                for key, value in tool_args.items():
                                    if hasattr(card, key):
                                        setattr(card, key, value)
                                db.commit()
                                db.refresh(card)
                                result = {
                                    "jsonrpc": "2.0",
                                    "id": request_id,
                                    "result": {
                                        "content": [{
                                            "type": "text",
                                            "text": f"✅ 更新成功！\nID: {card.id}\n标题: {card.title}"
                                        }]
                                    }
                                }
                        
                        elif tool_name == "delete_card":
                            card_id = int(tool_args["card_id"])
                            card = db.query(Card).filter(Card.id == card_id).first()
                            if not card:
                                result = {
                                    "jsonrpc": "2.0",
                                    "id": request_id,
                                    "result": {
                                        "content": [{
                                            "type": "text",
                                            "text": f"❌ 未找到卡片 {card_id}"
                                        }]
                                    }
                                }
                            else:
                                db.delete(card)
                                db.commit()
                                result = {
                                    "jsonrpc": "2.0",
                                    "id": request_id,
                                    "result": {
                                        "content": [{
                                            "type": "text",
                                            "text": f"✅ 删除成功！ID: {card_id}"
                                        }]
                                    }
                                }
                        
                        else:
                            result = {
                                "jsonrpc": "2.0",
                                "id": request_id,
                                "error": {
                                    "code": -32601,
                                    "message": f"Unknown tool: {tool_name}"
                                }
                            }
                        
                        yield json.dumps(result) + "\n"
                    
                    finally:
                        db.close()
                
                else:
                    result = {
                        "jsonrpc": "2.0",
                        "id": request_id,
                        "error": {
                            "code": -32601,
                            "message": f"Unknown method: {method}"
                        }
                    }
                    yield json.dumps(result) + "\n"
            
            except Exception as e:
                error_result = {
                    "jsonrpc": "2.0",
                    "id": request_id,
                    "error": {
                        "code": -32603,
                        "message": str(e)
                    }
                }
                yield json.dumps(error_result) + "\n"
        
        return StreamingResponse(
            stream_response(),
            media_type="application/json",
            headers={
                "Cache-Control": "no-cache",
                "X-Accel-Buffering": "no"
            }
        )
    
    @app.get(
        "/cards/",
        response_model=List[CardResponse],
        tags=["Cards"],
        summary="List all cards",
        description="Retrieve all cards ordered by creation date (newest first)"
    )
    async def list_cards(
        skip: int = 0,
        limit: int = 100,
        db: Session = Depends(get_db)
    ):
        """Get all cards with pagination support."""
        cards = db.query(Card).order_by(Card.created_at.desc()).offset(skip).limit(limit).all()
        return cards
    
    @app.get(
        "/cards/{card_id}",
        response_model=CardResponse,
        tags=["Cards"],
        summary="Get a card",
        description="Retrieve a specific card by its ID",
        responses={404: {"description": "Card not found"}}
    )
    async def get_card(card_id: int, db: Session = Depends(get_db)):
        """Get a specific card by ID."""
        card = db.query(Card).filter(Card.id == card_id).first()
        if not card:
            raise HTTPException(status_code=404, detail=f"Card with id {card_id} not found")
        return card
    
    @app.post(
        "/cards/",
        response_model=CardResponse,
        status_code=201,
        tags=["Cards"],
        summary="Create a card",
        description="Create a new card with title and optional descriptions"
    )
    async def create_card(card_data: CardCreate, db: Session = Depends(get_db)):
        """Create a new card."""
        try:
            card = Card(**card_data.model_dump())
            db.add(card)
            db.commit()
            db.refresh(card)
            return card
        except Exception as e:
            db.rollback()
            raise HTTPException(status_code=500, detail=f"Failed to create card: {str(e)}")
    
    @app.put(
        "/cards/{card_id}",
        response_model=CardResponse,
        tags=["Cards"],
        summary="Update a card",
        description="Update an existing card's fields",
        responses={404: {"description": "Card not found"}}
    )
    async def update_card(card_id: int, card_data: CardUpdate, db: Session = Depends(get_db)):
        """Update an existing card."""
        card = db.query(Card).filter(Card.id == card_id).first()
        if not card:
            raise HTTPException(status_code=404, detail=f"Card with id {card_id} not found")
        
        try:
            update_data = card_data.model_dump(exclude_unset=True)
            for field, value in update_data.items():
                setattr(card, field, value)
            
            db.commit()
            db.refresh(card)
            return card
        except Exception as e:
            db.rollback()
            raise HTTPException(status_code=500, detail=f"Failed to update card: {str(e)}")
    
    @app.delete(
        "/cards/{card_id}",
        status_code=204,
        tags=["Cards"],
        summary="Delete a card",
        description="Delete a card by its ID",
        responses={404: {"description": "Card not found"}}
    )
    async def delete_card(card_id: int, db: Session = Depends(get_db)):
        """Delete a card."""
        card = db.query(Card).filter(Card.id == card_id).first()
        if not card:
            raise HTTPException(status_code=404, detail=f"Card with id {card_id} not found")
        
        try:
            db.delete(card)
            db.commit()
            return None
        except Exception as e:
            db.rollback()
            raise HTTPException(status_code=500, detail=f"Failed to delete card: {str(e)}")
    
    return app
