from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from twilio.rest import Client
import os
import random
from datetime import datetime, timedelta
from typing import Optional

# Add root directory to Python path
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))

from utils.database import DatabaseManager

app = FastAPI(title="SMS Service")

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

# Twilio setup
twilio_client = Client(
    os.getenv("TWILIO_ACCOUNT_SID"),
    os.getenv("TWILIO_AUTH_TOKEN")
)
TWILIO_PHONE = os.getenv("TWILIO_PHONE_NUMBER")

# Database setup
db = DatabaseManager()
otp_collection = db.get_collection("otps")

class SendOTPRequest(BaseModel):
    phone: str
    purpose: str  # signup, login, reset_password, etc.

class VerifyOTPRequest(BaseModel):
    phone: str
    otp: str
    purpose: str

def generate_otp() -> str:
    return ''.join([str(random.randint(0, 9)) for _ in range(6)])

@app.post("/send-otp")
async def send_otp(request: SendOTPRequest):
    try:
        # Generate OTP
        otp = generate_otp()
        
        # Store OTP in database
        await otp_collection.insert_one({
            "phone": request.phone,
            "otp": otp,
            "purpose": request.purpose,
            "created_at": datetime.utcnow(),
            "expires_at": datetime.utcnow() + timedelta(minutes=10),
            "verified": False
        })
        
        # Send OTP via Twilio
        message = twilio_client.messages.create(
            body=f"Your PhoneMate verification code is: {otp}. Valid for 10 minutes.",
            from_=TWILIO_PHONE,
            to=request.phone
        )
        
        return {
            "message": "OTP sent successfully",
            "phone": request.phone,
            "expires_in": "10 minutes"
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/verify-otp")
async def verify_otp(request: VerifyOTPRequest):
    try:
        # Find latest unverified OTP for the phone number and purpose
        otp_record = await otp_collection.find_one({
            "phone": request.phone,
            "otp": request.otp,
            "purpose": request.purpose,
            "verified": False,
            "expires_at": {"$gt": datetime.utcnow()}
        }, sort=[("created_at", -1)])
        
        if not otp_record:
            raise HTTPException(status_code=400, detail="Invalid or expired OTP")
        
        # Mark OTP as verified
        await otp_collection.update_one(
            {"_id": otp_record["_id"]},
            {"$set": {"verified": True}}
        )
        
        return {
            "message": "OTP verified successfully",
            "phone": request.phone
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.on_event("startup")
async def startup_event():
    # Create TTL index for automatic cleanup of expired OTPs
    otp_collection.create_index(
        "expires_at", 
        expireAfterSeconds=0
    )

@app.on_event("shutdown")
async def shutdown_event():
    db.close() 