from fastapi import FastAPI, APIRouter, HTTPException, Query
from dotenv import load_dotenv
from starlette.middleware.cors import CORSMiddleware
from motor.motor_asyncio import AsyncIOMotorClient
import os
import logging
from pathlib import Path
from typing import List, Optional
from datetime import datetime

from models import (
    Article, ArticleCreate, ArticleUpdate,
    Category, CategoryCreate,
    Comment, CommentCreate,
    ContactMessage, ContactMessageCreate
)
from seed_data import seed_articles, seed_categories, seed_comments

ROOT_DIR = Path(__file__).parent
load_dotenv(ROOT_DIR / '.env')

# MongoDB connection
mongo_url = os.environ['MONGO_URL']
client = AsyncIOMotorClient(mongo_url)
db = client[os.environ['DB_NAME']]

# Create the main app without a prefix
app = FastAPI(title="inMotion Blog API")

# Create a router with the /api prefix
api_router = APIRouter(prefix="/api")

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


# ==================== ARTICLES ENDPOINTS ====================

@api_router.get("/articles", response_model=List[Article])
async def get_articles(
    category: Optional[str] = None,
    search: Optional[str] = None,
    featured: Optional[bool] = None,
    limit: Optional[int] = None
):
    """Get all articles with optional filters"""
    query = {}
    
    if category and category != "all":
        query["category"] = category
    
    if search:
        query["$or"] = [
            {"title": {"$regex": search, "$options": "i"}},
            {"excerpt": {"$regex": search, "$options": "i"}},
            {"content": {"$regex": search, "$options": "i"}}
        ]
    
    if featured is not None:
        query["featured"] = featured
    
    cursor = db.articles.find(query).sort("publishedAt", -1)
    
    if limit:
        cursor = cursor.limit(limit)
    
    articles = await cursor.to_list(1000)
    return [Article(**article) for article in articles]


@api_router.get("/articles/featured", response_model=List[Article])
async def get_featured_articles():
    """Get featured articles"""
    articles = await db.articles.find({"featured": True}).sort("publishedAt", -1).to_list(100)
    return [Article(**article) for article in articles]


@api_router.get("/articles/{slug}", response_model=Article)
async def get_article_by_slug(slug: str):
    """Get article by slug"""
    article = await db.articles.find_one({"slug": slug})
    if not article:
        raise HTTPException(status_code=404, detail="Artigo não encontrado")
    return Article(**article)


@api_router.post("/articles", response_model=Article)
async def create_article(article_data: ArticleCreate):
    """Create new article"""
    # Check if slug already exists
    existing = await db.articles.find_one({"slug": article_data.slug})
    if existing:
        raise HTTPException(status_code=400, detail="Slug já existe")
    
    article = Article(**article_data.dict())
    await db.articles.insert_one(article.dict())
    
    # Update category count
    await db.categories.update_one(
        {"name": article.category},
        {"$inc": {"count": 1}}
    )
    
    return article


@api_router.put("/articles/{article_id}", response_model=Article)
async def update_article(article_id: str, article_data: ArticleUpdate):
    """Update article"""
    article = await db.articles.find_one({"id": article_id})
    if not article:
        raise HTTPException(status_code=404, detail="Artigo não encontrado")
    
    update_data = {k: v for k, v in article_data.dict().items() if v is not None}
    update_data["updatedAt"] = datetime.utcnow()
    
    await db.articles.update_one(
        {"id": article_id},
        {"$set": update_data}
    )
    
    updated_article = await db.articles.find_one({"id": article_id})
    return Article(**updated_article)


@api_router.delete("/articles/{article_id}")
async def delete_article(article_id: str):
    """Delete article"""
    article = await db.articles.find_one({"id": article_id})
    if not article:
        raise HTTPException(status_code=404, detail="Artigo não encontrado")
    
    # Delete associated comments
    await db.comments.delete_many({"articleId": article_id})
    
    # Update category count
    await db.categories.update_one(
        {"name": article["category"]},
        {"$inc": {"count": -1}}
    )
    
    await db.articles.delete_one({"id": article_id})
    return {"message": "Artigo eliminado com sucesso"}


# ==================== CATEGORIES ENDPOINTS ====================

@api_router.get("/categories", response_model=List[Category])
async def get_categories():
    """Get all categories"""
    categories = await db.categories.find().to_list(100)
    return [Category(**category) for category in categories]


@api_router.post("/categories", response_model=Category)
async def create_category(category_data: CategoryCreate):
    """Create new category"""
    existing = await db.categories.find_one({"slug": category_data.slug})
    if existing:
        raise HTTPException(status_code=400, detail="Categoria já existe")
    
    category = Category(**category_data.dict())
    await db.categories.insert_one(category.dict())
    return category


@api_router.delete("/categories/{category_id}")
async def delete_category(category_id: str):
    """Delete category"""
    category = await db.categories.find_one({"id": category_id})
    if not category:
        raise HTTPException(status_code=404, detail="Categoria não encontrada")
    
    await db.categories.delete_one({"id": category_id})
    return {"message": "Categoria eliminada com sucesso"}


# ==================== COMMENTS ENDPOINTS ====================

@api_router.get("/articles/{article_id}/comments", response_model=List[Comment])
async def get_comments(article_id: str):
    """Get comments for an article"""
    comments = await db.comments.find({"articleId": article_id}).sort("createdAt", -1).to_list(1000)
    return [Comment(**comment) for comment in comments]


@api_router.post("/articles/{article_id}/comments", response_model=Comment)
async def create_comment(article_id: str, comment_data: CommentCreate):
    """Create new comment"""
    # Verify article exists
    article = await db.articles.find_one({"id": article_id})
    if not article:
        raise HTTPException(status_code=404, detail="Artigo não encontrado")
    
    comment = Comment(articleId=article_id, **comment_data.dict())
    await db.comments.insert_one(comment.dict())
    return comment


# ==================== CONTACT MESSAGES ENDPOINTS ====================

@api_router.get("/messages", response_model=List[ContactMessage])
async def get_messages():
    """Get all contact messages"""
    messages = await db.messages.find().sort("createdAt", -1).to_list(1000)
    return [ContactMessage(**message) for message in messages]


@api_router.post("/messages", response_model=ContactMessage)
async def create_message(message_data: ContactMessageCreate):
    """Create new contact message"""
    message = ContactMessage(**message_data.dict())
    await db.messages.insert_one(message.dict())
    return message


@api_router.patch("/messages/{message_id}/read")
async def mark_message_as_read(message_id: str):
    """Mark message as read"""
    result = await db.messages.update_one(
        {"id": message_id},
        {"$set": {"read": True}}
    )
    
    if result.matched_count == 0:
        raise HTTPException(status_code=404, detail="Mensagem não encontrada")
    
    return {"message": "Mensagem marcada como lida"}


# ==================== SEED ENDPOINT ====================

@api_router.post("/seed")
async def seed_database():
    """Seed database with initial data"""
    # Clear existing data
    await db.articles.delete_many({})
    await db.categories.delete_many({})
    await db.comments.delete_many({})
    
    # Insert seed data
    for article_data in seed_articles:
        article = Article(**article_data)
        await db.articles.insert_one(article.dict())
    
    for category_data in seed_categories:
        category = Category(**category_data)
        await db.categories.insert_one(category.dict())
    
    for comment_data in seed_comments:
        comment = Comment(**comment_data)
        await db.comments.insert_one(comment.dict())
    
    return {"message": "Base de dados populada com sucesso"}


# ==================== ROOT ENDPOINT ====================

@api_router.get("/")
async def root():
    return {
        "message": "inMotion Blog API",
        "version": "1.0.0",
        "endpoints": {
            "articles": "/api/articles",
            "categories": "/api/categories",
            "messages": "/api/messages"
        }
    }


# Include the router in the main app
app.include_router(api_router)

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


@app.on_event("startup")
async def startup_db():
    """Initialize database on startup"""
    # Check if database is empty and seed if needed
    article_count = await db.articles.count_documents({})
    if article_count == 0:
        logger.info("Base de dados vazia, a popular com dados iniciais...")
        for article_data in seed_articles:
            article = Article(**article_data)
            await db.articles.insert_one(article.dict())
        
        for category_data in seed_categories:
            category = Category(**category_data)
            await db.categories.insert_one(category.dict())
        
        for comment_data in seed_comments:
            comment = Comment(**comment_data)
            await db.comments.insert_one(comment.dict())
        
        logger.info("Base de dados populada com sucesso!")


@app.on_event("shutdown")
async def shutdown_db_client():
    client.close()