from fastapi import FastAPI, APIRouter, HTTPException
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 pydantic import BaseModel, Field, ConfigDict, EmailStr
from typing import List, Optional
import uuid
from datetime import datetime, timezone

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()

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

# Models
class StatusCheck(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    client_name: str
    timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

class StatusCheckCreate(BaseModel):
    client_name: str

class Product(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str
    name: str
    category: str
    price: float
    original_price: Optional[float] = None
    discount: Optional[int] = None
    image: str
    tags: List[str] = []
    style: Optional[str] = None
    in_stock: bool = True
    stock_quantity: Optional[int] = None

class CartItem(BaseModel):
    model_config = ConfigDict(extra="ignore")
    product_id: str
    quantity: int

class CartItemCreate(BaseModel):
    product_id: str
    quantity: int = 1

class Cart(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    items: List[CartItem] = []
    created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

class EmailSubscription(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    email: EmailStr
    subscribed_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
    discount_code: str = "WELCOME150"

class EmailSubscriptionCreate(BaseModel):
    email: EmailStr

class Testimonial(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str
    name: str
    rating: int
    review: str
    avatar: Optional[str] = None

# Mock Data
PRODUCTS = [
    {
        "id": "p1",
        "name": "Pearl Drop Earrings",
        "category": "jewelry",
        "price": 29.99,
        "original_price": 49.99,
        "discount": 40,
        "image": "https://images.unsplash.com/photo-1535632066927-ab7c9ab60908?w=500",
        "tags": ["trending", "best-seller"],
        "style": "minimal",
        "in_stock": True,
        "stock_quantity": 5
    },
    {
        "id": "p2",
        "name": "Gold Chain Necklace",
        "category": "jewelry",
        "price": 45.99,
        "original_price": 65.99,
        "discount": 30,
        "image": "https://images.unsplash.com/photo-1599643478518-a784e5dc4c8f?w=500",
        "tags": ["trending"],
        "style": "elegant",
        "in_stock": True,
        "stock_quantity": 8
    },
    {
        "id": "p3",
        "name": "Leather Crossbody Bag",
        "category": "handbags",
        "price": 89.99,
        "original_price": 129.99,
        "discount": 31,
        "image": "https://images.unsplash.com/photo-1548036328-c9fa89d128fa?w=500",
        "tags": ["best-seller"],
        "style": "everyday",
        "in_stock": True,
        "stock_quantity": 3
    },
    {
        "id": "p4",
        "name": "Crystal Bracelet Set",
        "category": "jewelry",
        "price": 34.99,
        "original_price": 54.99,
        "discount": 36,
        "image": "https://images.unsplash.com/photo-1611652022419-a9419f74343d?w=500",
        "tags": ["trending", "new"],
        "style": "party",
        "in_stock": True,
        "stock_quantity": 12
    },
    {
        "id": "p5",
        "name": "Vintage Cat-Eye Sunglasses",
        "category": "sunglasses",
        "price": 55.99,
        "original_price": 79.99,
        "discount": 30,
        "image": "https://images.unsplash.com/photo-1511499767150-a48a237f0083?w=500",
        "tags": ["trending"],
        "style": "premium",
        "in_stock": True,
        "stock_quantity": 7
    },
    {
        "id": "p6",
        "name": "Rose Gold Watch",
        "category": "watches",
        "price": 125.99,
        "original_price": 175.99,
        "discount": 28,
        "image": "https://images.unsplash.com/photo-1524592094714-0f0654e20314?w=500",
        "tags": ["best-seller", "premium"],
        "style": "elegant",
        "in_stock": True,
        "stock_quantity": 4
    },
    {
        "id": "p7",
        "name": "Silk Hair Scrunchie Set",
        "category": "hair-accessories",
        "price": 18.99,
        "original_price": 28.99,
        "discount": 34,
        "image": "https://images.unsplash.com/photo-1597314190535-f59dfb1c03cd?w=500",
        "tags": ["new", "trending"],
        "style": "everyday",
        "in_stock": True,
        "stock_quantity": 20
    },
    {
        "id": "p8",
        "name": "Statement Hoop Earrings",
        "category": "jewelry",
        "price": 39.99,
        "original_price": 59.99,
        "discount": 33,
        "image": "https://images.unsplash.com/photo-1630019852942-f89202989a59?w=500",
        "tags": ["trending", "party"],
        "style": "party",
        "in_stock": True,
        "stock_quantity": 6
    }
]

TESTIMONIALS = [
    {
        "id": "t1",
        "name": "Sneha Kapoor",
        "rating": 5,
        "review": "Loved the quality, looks premium! Got so many compliments at my friend's wedding.",
        "avatar": "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=100"
    },
    {
        "id": "t2",
        "name": "Riya Sharma",
        "rating": 5,
        "review": "Got so many compliments! The earrings are exactly as shown in the pictures.",
        "avatar": "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100"
    },
    {
        "id": "t3",
        "name": "Priya Patel",
        "rating": 5,
        "review": "Fast delivery and beautiful packaging. Will definitely order again!",
        "avatar": "https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=100"
    },
    {
        "id": "t4",
        "name": "Ananya Singh",
        "rating": 5,
        "review": "Best accessories store! The quality is amazing for the price.",
        "avatar": "https://images.unsplash.com/photo-1531746020798-e6953c6e8e04?w=100"
    }
]

# Routes
@api_router.get("/")
async def root():
    return {"message": "TrendNexa Accessories API"}

@api_router.post("/status", response_model=StatusCheck)
async def create_status_check(input: StatusCheckCreate):
    status_dict = input.model_dump()
    status_obj = StatusCheck(**status_dict)
    doc = status_obj.model_dump()
    doc['timestamp'] = doc['timestamp'].isoformat()
    _ = await db.status_checks.insert_one(doc)
    return status_obj

@api_router.get("/status", response_model=List[StatusCheck])
async def get_status_checks():
    status_checks = await db.status_checks.find({}, {"_id": 0}).to_list(1000)
    for check in status_checks:
        if isinstance(check['timestamp'], str):
            check['timestamp'] = datetime.fromisoformat(check['timestamp'])
    return status_checks

# Product Routes
@api_router.get("/products", response_model=List[Product])
async def get_products(category: Optional[str] = None, style: Optional[str] = None):
    products = PRODUCTS
    if category:
        products = [p for p in products if p["category"] == category]
    if style:
        products = [p for p in products if p.get("style") == style]
    return products

@api_router.get("/products/{product_id}", response_model=Product)
async def get_product(product_id: str):
    product = next((p for p in PRODUCTS if p["id"] == product_id), None)
    if not product:
        raise HTTPException(status_code=404, detail="Product not found")
    return product

@api_router.get("/products/trending/list", response_model=List[Product])
async def get_trending_products():
    return [p for p in PRODUCTS if "trending" in p.get("tags", [])]

@api_router.get("/products/new-arrivals/list", response_model=List[Product])
async def get_new_arrivals():
    return PRODUCTS[:8]

# Cart Routes
@api_router.post("/cart")
async def create_cart():
    cart = Cart()
    doc = cart.model_dump()
    doc['created_at'] = doc['created_at'].isoformat()
    doc['updated_at'] = doc['updated_at'].isoformat()
    await db.carts.insert_one(doc)
    return {"cart_id": cart.id}

@api_router.get("/cart/{cart_id}")
async def get_cart(cart_id: str):
    cart = await db.carts.find_one({"id": cart_id}, {"_id": 0})
    if not cart:
        raise HTTPException(status_code=404, detail="Cart not found")
    
    # Enrich cart items with product details
    enriched_items = []
    for item in cart.get("items", []):
        product = next((p for p in PRODUCTS if p["id"] == item["product_id"]), None)
        if product:
            enriched_items.append({
                **item,
                "product": product
            })
    
    return {
        "id": cart["id"],
        "items": enriched_items,
        "total": sum(item["product"]["price"] * item["quantity"] for item in enriched_items)
    }

@api_router.post("/cart/{cart_id}/items")
async def add_to_cart(cart_id: str, item: CartItemCreate):
    cart = await db.carts.find_one({"id": cart_id}, {"_id": 0})
    if not cart:
        # Create new cart if doesn't exist
        cart = Cart(id=cart_id)
        doc = cart.model_dump()
        doc['created_at'] = doc['created_at'].isoformat()
        doc['updated_at'] = doc['updated_at'].isoformat()
        await db.carts.insert_one(doc)
        cart = doc
    
    items = cart.get("items", [])
    existing_item = next((i for i in items if i["product_id"] == item.product_id), None)
    
    if existing_item:
        existing_item["quantity"] += item.quantity
    else:
        items.append({"product_id": item.product_id, "quantity": item.quantity})
    
    await db.carts.update_one(
        {"id": cart_id},
        {"$set": {"items": items, "updated_at": datetime.now(timezone.utc).isoformat()}}
    )
    
    return {"message": "Item added to cart", "items": items}

@api_router.put("/cart/{cart_id}/items/{product_id}")
async def update_cart_item(cart_id: str, product_id: str, quantity: int):
    cart = await db.carts.find_one({"id": cart_id}, {"_id": 0})
    if not cart:
        raise HTTPException(status_code=404, detail="Cart not found")
    
    items = cart.get("items", [])
    item = next((i for i in items if i["product_id"] == product_id), None)
    
    if not item:
        raise HTTPException(status_code=404, detail="Item not found in cart")
    
    if quantity <= 0:
        items = [i for i in items if i["product_id"] != product_id]
    else:
        item["quantity"] = quantity
    
    await db.carts.update_one(
        {"id": cart_id},
        {"$set": {"items": items, "updated_at": datetime.now(timezone.utc).isoformat()}}
    )
    
    return {"message": "Cart updated", "items": items}

@api_router.delete("/cart/{cart_id}/items/{product_id}")
async def remove_from_cart(cart_id: str, product_id: str):
    cart = await db.carts.find_one({"id": cart_id}, {"_id": 0})
    if not cart:
        raise HTTPException(status_code=404, detail="Cart not found")
    
    items = [i for i in cart.get("items", []) if i["product_id"] != product_id]
    
    await db.carts.update_one(
        {"id": cart_id},
        {"$set": {"items": items, "updated_at": datetime.now(timezone.utc).isoformat()}}
    )
    
    return {"message": "Item removed from cart"}

# Email Subscription
@api_router.post("/subscribe")
async def subscribe_email(subscription: EmailSubscriptionCreate):
    # Check if email already exists
    existing = await db.subscriptions.find_one({"email": subscription.email}, {"_id": 0})
    if existing:
        return {"message": "Already subscribed!", "discount_code": "WELCOME150"}
    
    sub = EmailSubscription(email=subscription.email)
    doc = sub.model_dump()
    doc['subscribed_at'] = doc['subscribed_at'].isoformat()
    await db.subscriptions.insert_one(doc)
    
    return {"message": "Successfully subscribed!", "discount_code": sub.discount_code}

# Testimonials
@api_router.get("/testimonials", response_model=List[Testimonial])
async def get_testimonials():
    return TESTIMONIALS

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

app.add_middleware(
    CORSMiddleware,
    allow_credentials=True,
    allow_origins=os.environ.get('CORS_ORIGINS', '*').split(','),
    allow_methods=["*"],
    allow_headers=["*"],
)

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

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