from fastapi import FastAPI, APIRouter, HTTPException, Depends, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from dotenv import load_dotenv
from starlette.middleware.cors import CORSMiddleware
from motor.motor_asyncio import AsyncIOMotorClient
from a2wsgi import ASGIMiddleware
import certifi
import os
import logging
from pathlib import Path
from pydantic import BaseModel, Field, ConfigDict
from typing import List, Optional
import uuid
from datetime import datetime, timezone, timedelta
import jwt
import bcrypt

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

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

# JWT settings
JWT_SECRET = os.environ.get('JWT_SECRET', 'estate-logic-secret-key-2024')
JWT_ALGORITHM = "HS256"
JWT_EXPIRATION_HOURS = 24

# Create the main app
app = FastAPI()
api_router = APIRouter(prefix="/api")
security = HTTPBearer()

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

# ==================== MODELS ====================

# Auth Models
class UserLogin(BaseModel):
    email: str
    password: str

class UserResponse(BaseModel):
    id: str
    name: str
    email: str
    role: str
    avatar: Optional[str] = None

class LoginResponse(BaseModel):
    token: str
    user: UserResponse

# Property Models
class Property(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    name: str
    location: str
    total_units: int
    occupied_units: int
    monthly_income: int
    status: str  # "optimized", "active", "attention"
    image: Optional[str] = None
    created_at: str = Field(default_factory=lambda: datetime.now(timezone.utc).isoformat())

# Unit Models
class Unit(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    property_id: str
    name: str
    unit_type: str  # "premium", "standard", "studio"
    floor: int
    tenant_name: Optional[str] = None
    tenant_since: Optional[str] = None
    status: str  # "occupied", "vacant", "maintenance"
    rent_status: Optional[str] = None  # "paid", "overdue", "pending"
    last_inspection: Optional[str] = None
    image: Optional[str] = None

class UnitCreate(BaseModel):
    property_id: str
    name: str
    unit_type: str
    floor: int
    tenant_name: Optional[str] = None
    tenant_since: Optional[str] = None
    status: str = "vacant"
    rent_status: Optional[str] = None
    image: Optional[str] = None

# Invoice Models
class Invoice(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    tenant_name: str
    tenant_initials: str
    property_name: str
    unit_name: str
    due_date: str
    amount: int
    status: str  # "paid", "overdue", "pending"
    phone: Optional[str] = None
    created_at: str = Field(default_factory=lambda: datetime.now(timezone.utc).isoformat())

class InvoiceCreate(BaseModel):
    tenant_name: str
    property_name: str
    unit_name: str
    due_date: str
    amount: int
    status: str = "pending"
    phone: Optional[str] = None

# Maintenance Models
class MaintenanceTicket(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    ticket_number: str
    title: str
    description: str
    property_name: str
    unit_name: str
    priority: str  # "urgent", "medium", "routine"
    status: str  # "new", "in_progress", "resolved"
    assigned_to: Optional[str] = None
    assigned_avatar: Optional[str] = None
    progress: int = 0
    image: Optional[str] = None
    created_at: str = Field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
    resolved_at: Optional[str] = None

class MaintenanceTicketCreate(BaseModel):
    title: str
    description: str
    property_name: str
    unit_name: str
    priority: str = "medium"
    image: Optional[str] = None

class MaintenanceTicketUpdate(BaseModel):
    title: Optional[str] = None
    description: Optional[str] = None
    priority: Optional[str] = None
    status: Optional[str] = None
    assigned_to: Optional[str] = None
    progress: Optional[int] = None

# Transaction Models
class Transaction(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    transaction_id: str
    property_name: str
    date: str
    category: str  # "rent_payment", "maintenance", "taxes", "utilities"
    status: str  # "completed", "processing", "failed"
    amount: int  # positive for income, negative for expense
    created_at: str = Field(default_factory=lambda: datetime.now(timezone.utc).isoformat())

# Activity Models
class Activity(BaseModel):
    model_config = ConfigDict(extra="ignore")
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    type: str  # "lease", "maintenance", "payment"
    title: str
    description: str
    time_ago: str
    created_at: str = Field(default_factory=lambda: datetime.now(timezone.utc).isoformat())

# ==================== AUTH HELPERS ====================

def create_jwt_token(user_id: str, email: str, role: str) -> str:
    payload = {
        "sub": user_id,
        "email": email,
        "role": role,
        "exp": datetime.now(timezone.utc) + timedelta(hours=JWT_EXPIRATION_HOURS)
    }
    return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)

def verify_jwt_token(token: str) -> dict:
    try:
        payload = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
        return payload
    except jwt.ExpiredSignatureError:
        raise HTTPException(status_code=401, detail="Token expired")
    except jwt.InvalidTokenError:
        raise HTTPException(status_code=401, detail="Invalid token")

async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)):
    payload = verify_jwt_token(credentials.credentials)
    return payload

# ==================== DUMMY USERS ====================

DUMMY_USERS = [
    {
        "id": "user-001",
        "name": "Alex Graham",
        "email": "gomes@property.com",
        "password": "admin123",
        "role": "super_admin",
        "avatar": "https://images.unsplash.com/photo-1560250097-0b93528c311a?w=100&h=100&fit=crop"
    },
    {
        "id": "user-002",
        "name": "Marcus Chen",
        "email": "marcus@estatelogic.com",
        "password": "admin123",
        "role": "senior_admin",
        "avatar": "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop"
    }
]

# ==================== AUTH ROUTES ====================

@api_router.post("/auth/login", response_model=LoginResponse)
async def login(credentials: UserLogin):
    for user in DUMMY_USERS:
        if user["email"] == credentials.email and user["password"] == credentials.password:
            token = create_jwt_token(user["id"], user["email"], user["role"])
            return LoginResponse(
                token=token,
                user=UserResponse(
                    id=user["id"],
                    name=user["name"],
                    email=user["email"],
                    role=user["role"],
                    avatar=user["avatar"]
                )
            )
    raise HTTPException(status_code=401, detail="Invalid email or password")

@api_router.get("/auth/me", response_model=UserResponse)
async def get_me(current_user: dict = Depends(get_current_user)):
    for user in DUMMY_USERS:
        if user["id"] == current_user["sub"]:
            return UserResponse(
                id=user["id"],
                name=user["name"],
                email=user["email"],
                role=user["role"],
                avatar=user["avatar"]
            )
    raise HTTPException(status_code=404, detail="User not found")

# ==================== PROPERTY ROUTES ====================

@api_router.get("/properties", response_model=List[Property])
async def get_properties():
    properties = await db.properties.find({}, {"_id": 0}).to_list(100)
    return properties

@api_router.get("/properties/{property_id}", response_model=Property)
async def get_property(property_id: str):
    property_doc = await db.properties.find_one({"id": property_id}, {"_id": 0})
    if not property_doc:
        raise HTTPException(status_code=404, detail="Property not found")
    return property_doc

@api_router.post("/properties", response_model=Property)
async def create_property(property_data: Property):
    doc = property_data.model_dump()
    await db.properties.insert_one(doc)
    return property_data

# ==================== UNIT ROUTES ====================

@api_router.get("/units", response_model=List[Unit])
async def get_units(property_id: Optional[str] = None, status: Optional[str] = None, unit_type: Optional[str] = None):
    query = {}
    if property_id:
        query["property_id"] = property_id
    if status:
        query["status"] = status
    if unit_type:
        query["unit_type"] = unit_type
    units = await db.units.find(query, {"_id": 0}).to_list(500)
    return units

@api_router.get("/units/{unit_id}", response_model=Unit)
async def get_unit(unit_id: str):
    unit = await db.units.find_one({"id": unit_id}, {"_id": 0})
    if not unit:
        raise HTTPException(status_code=404, detail="Unit not found")
    return unit

@api_router.post("/units", response_model=Unit)
async def create_unit(unit_data: UnitCreate):
    unit = Unit(**unit_data.model_dump())
    doc = unit.model_dump()
    await db.units.insert_one(doc)
    return unit

@api_router.put("/units/{unit_id}", response_model=Unit)
async def update_unit(unit_id: str, updates: dict):
    result = await db.units.update_one({"id": unit_id}, {"$set": updates})
    if result.matched_count == 0:
        raise HTTPException(status_code=404, detail="Unit not found")
    unit = await db.units.find_one({"id": unit_id}, {"_id": 0})
    return unit

# ==================== INVOICE ROUTES ====================

@api_router.get("/invoices", response_model=List[Invoice])
async def get_invoices(status: Optional[str] = None):
    query = {}
    if status:
        query["status"] = status
    invoices = await db.invoices.find(query, {"_id": 0}).to_list(500)
    return invoices

@api_router.post("/invoices", response_model=Invoice)
async def create_invoice(invoice_data: InvoiceCreate):
    initials = "".join([n[0].upper() for n in invoice_data.tenant_name.split()[:2]])
    invoice = Invoice(
        tenant_initials=initials,
        **invoice_data.model_dump()
    )
    doc = invoice.model_dump()
    await db.invoices.insert_one(doc)
    return invoice

@api_router.put("/invoices/{invoice_id}", response_model=Invoice)
async def update_invoice(invoice_id: str, updates: dict):
    result = await db.invoices.update_one({"id": invoice_id}, {"$set": updates})
    if result.matched_count == 0:
        raise HTTPException(status_code=404, detail="Invoice not found")
    invoice = await db.invoices.find_one({"id": invoice_id}, {"_id": 0})
    return invoice

# ==================== MAINTENANCE ROUTES ====================

@api_router.get("/maintenance", response_model=List[MaintenanceTicket])
async def get_maintenance_tickets(status: Optional[str] = None, priority: Optional[str] = None):
    query = {}
    if status:
        query["status"] = status
    if priority:
        query["priority"] = priority
    tickets = await db.maintenance.find(query, {"_id": 0}).to_list(500)
    return tickets

@api_router.post("/maintenance", response_model=MaintenanceTicket)
async def create_maintenance_ticket(ticket_data: MaintenanceTicketCreate):
    # Generate ticket number
    count = await db.maintenance.count_documents({})
    ticket_number = f"#MT-{8840 + count}"
    
    ticket = MaintenanceTicket(
        ticket_number=ticket_number,
        status="new",
        **ticket_data.model_dump()
    )
    doc = ticket.model_dump()
    await db.maintenance.insert_one(doc)
    return ticket

@api_router.put("/maintenance/{ticket_id}", response_model=MaintenanceTicket)
async def update_maintenance_ticket(ticket_id: str, updates: MaintenanceTicketUpdate):
    update_dict = {k: v for k, v in updates.model_dump().items() if v is not None}
    if updates.status == "resolved":
        update_dict["resolved_at"] = datetime.now(timezone.utc).isoformat()
    
    result = await db.maintenance.update_one({"id": ticket_id}, {"$set": update_dict})
    if result.matched_count == 0:
        raise HTTPException(status_code=404, detail="Ticket not found")
    ticket = await db.maintenance.find_one({"id": ticket_id}, {"_id": 0})
    return ticket

# ==================== TRANSACTION ROUTES ====================

@api_router.get("/transactions", response_model=List[Transaction])
async def get_transactions(category: Optional[str] = None, limit: int = 50):
    query = {}
    if category:
        query["category"] = category
    transactions = await db.transactions.find(query, {"_id": 0}).sort("date", -1).to_list(limit)
    return transactions

# ==================== ACTIVITY ROUTES ====================

@api_router.get("/activities", response_model=List[Activity])
async def get_activities(limit: int = 10):
    activities = await db.activities.find({}, {"_id": 0}).sort("created_at", -1).to_list(limit)
    return activities

# ==================== ANALYTICS ROUTES ====================

@api_router.get("/analytics/dashboard")
async def get_dashboard_analytics():
    # Calculate metrics from database
    properties = await db.properties.find({}, {"_id": 0}).to_list(100)
    units = await db.units.find({}, {"_id": 0}).to_list(500)
    invoices = await db.invoices.find({}, {"_id": 0}).to_list(500)
    
    total_revenue = sum(p.get("monthly_income", 0) for p in properties)
    total_units = sum(p.get("total_units", 0) for p in properties)
    occupied_units = sum(p.get("occupied_units", 0) for p in properties)
    occupancy_rate = (occupied_units / total_units * 100) if total_units > 0 else 0
    
    pending_invoices = [i for i in invoices if i.get("status") in ["pending", "overdue"]]
    pending_amount = sum(i.get("amount", 0) for i in pending_invoices)
    
    return {
        "total_revenue": total_revenue,
        "revenue_change": 12.4,
        "residential_revenue": int(total_revenue * 0.62),
        "commercial_revenue": int(total_revenue * 0.38),
        "occupancy_rate": round(occupancy_rate, 1),
        "vacant_units": total_units - occupied_units,
        "total_properties": len(properties),
        "pending_payments": pending_amount,
        "overdue_count": len([i for i in invoices if i.get("status") == "overdue"])
    }

@api_router.get("/analytics/financial")
async def get_financial_analytics():
    transactions = await db.transactions.find({}, {"_id": 0}).to_list(500)
    
    total_revenue = sum(t.get("amount", 0) for t in transactions if t.get("amount", 0) > 0)
    total_expenses = abs(sum(t.get("amount", 0) for t in transactions if t.get("amount", 0) < 0))
    net_profit = total_revenue - total_expenses
    profit_margin = (net_profit / total_revenue * 100) if total_revenue > 0 else 0
    
    # Calculate expense breakdown
    expense_categories = {}
    for t in transactions:
        if t.get("amount", 0) < 0:
            cat = t.get("category", "other")
            expense_categories[cat] = expense_categories.get(cat, 0) + abs(t.get("amount", 0))
    
    # Monthly data for chart
    monthly_data = [
        {"month": "Jan", "revenue": 85000000, "expense": 32000000},
        {"month": "Feb", "revenue": 92000000, "expense": 35000000},
        {"month": "Mar", "revenue": 145000000, "expense": 78000000},
        {"month": "Apr", "revenue": 110000000, "expense": 45000000},
        {"month": "May", "revenue": 125000000, "expense": 52000000},
        {"month": "Jun", "revenue": 135000000, "expense": 48000000},
    ]
    
    return {
        "total_revenue": total_revenue if total_revenue > 0 else 1420500000,
        "total_expenses": total_expenses if total_expenses > 0 else 485200000,
        "net_profit": net_profit if net_profit != 0 else 935300000,
        "profit_margin": round(profit_margin, 1) if profit_margin > 0 else 65.8,
        "revenue_change": 12,
        "expense_change": -4,
        "profit_change": 8,
        "expense_breakdown": expense_categories if expense_categories else {
            "maintenance": 45,
            "taxes": 25,
            "staff": 15,
            "marketing": 15
        },
        "monthly_data": monthly_data
    }

@api_router.get("/analytics/billing")
async def get_billing_analytics():
    invoices = await db.invoices.find({}, {"_id": 0}).to_list(500)
    
    total_collections = sum(i.get("amount", 0) for i in invoices if i.get("status") == "paid")
    outstanding = sum(i.get("amount", 0) for i in invoices if i.get("status") in ["pending", "overdue"])
    overdue_count = len([i for i in invoices if i.get("status") == "overdue"])
    
    collection_efficiency = (total_collections / (total_collections + outstanding) * 100) if (total_collections + outstanding) > 0 else 92
    
    return {
        "total_collections": total_collections if total_collections > 0 else 1450000000,
        "collections_change": 12.5,
        "outstanding_receivables": outstanding if outstanding > 0 else 285400000,
        "overdue_count": overdue_count if overdue_count > 0 else 14,
        "collection_efficiency": round(collection_efficiency, 0) if collection_efficiency else 92,
        "projected_revenue": 1520000000,
        "reminders_sent": 142,
        "response_rate": 68
    }

@api_router.get("/analytics/units")
async def get_units_analytics():
    units = await db.units.find({}, {"_id": 0}).to_list(500)
    
    total = len(units)
    occupied = len([u for u in units if u.get("status") == "occupied"])
    vacant = len([u for u in units if u.get("status") == "vacant"])
    maintenance = len([u for u in units if u.get("status") == "maintenance"])
    
    occupancy_rate = (occupied / total * 100) if total > 0 else 94.2
    
    return {
        "total_units": total if total > 0 else 142,
        "occupancy_rate": round(occupancy_rate, 1),
        "occupied": occupied,
        "vacant": vacant,
        "under_maintenance": maintenance if maintenance > 0 else 8,
        "change": 12
    }

# ==================== SEED DATA ====================

async def seed_database():
    # Check if already seeded
    existing = await db.properties.count_documents({})
    if existing > 0:
        logger.info("Database already seeded")
        return
    
    logger.info("Seeding database...")
    
    # Seed Properties
    properties = [
        Property(
            id="prop-001",
            name="Gading Serpong Loft",
            location="Tangerang, Banten",
            total_units=24,
            occupied_units=24,
            monthly_income=320000000,
            status="optimized",
            image="https://images.unsplash.com/photo-1667238324671-c2fe726f6084?w=400&h=300&fit=crop"
        ),
        Property(
            id="prop-002",
            name="Kemang Residence",
            location="South Jakarta, DKI",
            total_units=40,
            occupied_units=34,
            monthly_income=580000000,
            status="active",
            image="https://images.unsplash.com/photo-1772103628874-1b084bdae27b?w=400&h=300&fit=crop"
        ),
        Property(
            id="prop-003",
            name="Pakuwon Tower",
            location="Surabaya, East Java",
            total_units=56,
            occupied_units=48,
            monthly_income=420000000,
            status="active",
            image="https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?w=400&h=300&fit=crop"
        ),
        Property(
            id="prop-004",
            name="Pondok Indah Heights",
            location="South Jakarta, DKI",
            total_units=32,
            occupied_units=30,
            monthly_income=650000000,
            status="optimized",
            image="https://images.unsplash.com/photo-1545324418-cc1a3fa10c00?w=400&h=300&fit=crop"
        )
    ]
    
    for prop in properties:
        await db.properties.insert_one(prop.model_dump())
    
    # Seed Units
    units = [
        Unit(id="unit-001", property_id="prop-001", name="Suite 402-A", unit_type="premium", floor=4, 
             tenant_name="Elena Rodriguez", tenant_since="Oct 2023", status="occupied", rent_status="paid",
             last_inspection="Jan 12, 2024", image="https://images.unsplash.com/photo-1502672260266-1c1ef2d93688?w=100&h=100&fit=crop"),
        Unit(id="unit-002", property_id="prop-001", name="Studio 105", unit_type="studio", floor=1,
             status="vacant", last_inspection="Feb 01, 2024", image="https://images.unsplash.com/photo-1522708323590-d24dbb6b0267?w=100&h=100&fit=crop"),
        Unit(id="unit-003", property_id="prop-002", name="Penthouse 802", unit_type="premium", floor=8,
             tenant_name="Liam Henderson", tenant_since="Moving Out Mar 15", status="maintenance", rent_status="overdue",
             last_inspection="Mar 04, 2024", image="https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?w=100&h=100&fit=crop"),
        Unit(id="unit-004", property_id="prop-001", name="Suite 204-C", unit_type="standard", floor=2,
             tenant_name="Sarah Jenkins", tenant_since="Jan 2024", status="occupied", rent_status="paid",
             last_inspection="Feb 28, 2024", image="https://images.unsplash.com/photo-1493809842364-78817add7ffb?w=100&h=100&fit=crop"),
        Unit(id="unit-005", property_id="prop-003", name="Unit 12A", unit_type="standard", floor=12,
             tenant_name="Budi Pratama", tenant_since="Jun 2023", status="occupied", rent_status="paid",
             last_inspection="Jan 15, 2024"),
        Unit(id="unit-006", property_id="prop-002", name="B-04-02", unit_type="standard", floor=4,
             tenant_name="Sari Wijaya", tenant_since="Aug 2023", status="occupied", rent_status="overdue",
             last_inspection="Feb 10, 2024"),
    ]
    
    for unit in units:
        await db.units.insert_one(unit.model_dump())
    
    # Seed Invoices
    invoices = [
        Invoice(id="inv-001", tenant_name="Budi Pratama", tenant_initials="BP", property_name="Pakuwon Tower",
                unit_name="Unit 12A", due_date="May 15, 2024", amount=45000000, status="paid", phone="6281234567890"),
        Invoice(id="inv-002", tenant_name="Sari Wijaya", tenant_initials="SW", property_name="Signature Park",
                unit_name="B-04-02", due_date="May 20, 2024", amount=12500000, status="overdue", phone="6281234567891"),
        Invoice(id="inv-003", tenant_name="Andi Kusuma", tenant_initials="AK", property_name="Sudirman Mansion",
                unit_name="Penthouse", due_date="May 28, 2024", amount=85000000, status="pending", phone="6281234567892"),
        Invoice(id="inv-004", tenant_name="Dewi Rahayu", tenant_initials="DR", property_name="District 8",
                unit_name="T2-08-E", due_date="May 12, 2024", amount=22000000, status="paid", phone="6281234567893"),
        Invoice(id="inv-005", tenant_name="Elena Rodriguez", tenant_initials="ER", property_name="Gading Serpong Loft",
                unit_name="Suite 402-A", due_date="Jun 01, 2024", amount=35000000, status="pending", phone="6281234567894"),
    ]
    
    for invoice in invoices:
        await db.invoices.insert_one(invoice.model_dump())
    
    # Seed Maintenance Tickets
    maintenance_tickets = [
        MaintenanceTicket(
            id="maint-001", ticket_number="#MT-8842", title="Water Leak in HVAC",
            description="Tenant reports active dripping from ceiling unit in Unit 4B. Risk of floor damage.",
            property_name="Skyline Heights", unit_name="Apt 402", priority="urgent", status="new",
            image="https://images.pexels.com/photos/6419128/pexels-photo-6419128.jpeg?w=200&h=150&fit=crop"
        ),
        MaintenanceTicket(
            id="maint-002", ticket_number="#MT-8839", title="Exterior Lighting Failure",
            description="South entrance motion sensors not triggering. Technician currently on site.",
            property_name="Oakwood Plaza", unit_name="Exterior", priority="medium", status="in_progress",
            assigned_to="Technician On-Site", progress=65,
            assigned_avatar="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=50&h=50&fit=crop"
        ),
        MaintenanceTicket(
            id="maint-003", ticket_number="#MT-8845", title="Broken Window Lock",
            description="Safety latch on master bedroom window is jammed. Needs replacement.",
            property_name="Pinecrest Gardens", unit_name="Unit 12", priority="routine", status="new"
        ),
        MaintenanceTicket(
            id="maint-004", ticket_number="#MT-8835", title="Kitchen Counter Crack",
            description="Surface epoxy repair scheduled. Resident notified of the time slot.",
            property_name="The Modernist", unit_name="Apt 104", priority="routine", status="in_progress",
            progress=30
        ),
        MaintenanceTicket(
            id="maint-005", ticket_number="#MT-8872", title="Smoke Detector Battery",
            description="Resolved by facility manager. Batteries replaced in all bedrooms.",
            property_name="Skyline Heights", unit_name="Apt 301", priority="routine", status="resolved",
            resolved_at=datetime.now(timezone.utc).isoformat()
        ),
        MaintenanceTicket(
            id="maint-006", ticket_number="#MT-8818", title="Clogged Sink Repair",
            description="Plumbing service cleared main line. No further issues reported.",
            property_name="The Modernist", unit_name="Apt 502", priority="medium", status="resolved",
            resolved_at=datetime.now(timezone.utc).isoformat()
        ),
    ]
    
    for ticket in maintenance_tickets:
        await db.maintenance.insert_one(ticket.model_dump())
    
    # Seed Transactions
    transactions = [
        Transaction(id="tx-001", transaction_id="#TX-90210", property_name="Emerald Peak Residences",
                   date="Mar 14, 2024", category="rent_payment", status="completed", amount=125000000),
        Transaction(id="tx-002", transaction_id="#TX-90211", property_name="Sapphire Heights B-02",
                   date="Mar 12, 2024", category="maintenance", status="completed", amount=-15500000),
        Transaction(id="tx-003", transaction_id="#TX-90212", property_name="The Grand Plaza",
                   date="Mar 10, 2024", category="utilities", status="processing", amount=-42200000),
        Transaction(id="tx-004", transaction_id="#TX-90213", property_name="Pakuwon Tower",
                   date="Mar 08, 2024", category="rent_payment", status="completed", amount=85000000),
        Transaction(id="tx-005", transaction_id="#TX-90214", property_name="Kemang Residence",
                   date="Mar 05, 2024", category="taxes", status="completed", amount=-28000000),
    ]
    
    for tx in transactions:
        await db.transactions.insert_one(tx.model_dump())
    
    # Seed Activities
    activities = [
        Activity(id="act-001", type="lease", title="New Lease Signed",
                description="Gading Serpong Loft - Unit 8A", time_ago="2 hours ago"),
        Activity(id="act-002", type="maintenance", title="Maintenance Alert",
                description="Water leakage reported at Kemang Residence", time_ago="3 hours ago"),
        Activity(id="act-003", type="payment", title="Payment Received",
                description="Rp 17,500,000 - Unit 402, Pondok Indah", time_ago="Yesterday"),
    ]
    
    for activity in activities:
        await db.activities.insert_one(activity.model_dump())
    
    logger.info("Database seeded successfully!")

# ==================== STARTUP EVENT ====================

@app.on_event("startup")
async def startup_event():
    await seed_database()

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

# ==================== ROOT ROUTE ====================

@api_router.get("/")
async def root():
    return {"message": "Estate Logic API v1.0"}

# 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=["*"],
)

# cPanel Python App (Passenger) expects a WSGI callable named "application".
application = ASGIMiddleware(app)

if __name__ == "__main__":
    import uvicorn

    uvicorn.run(
        "server:app",
        host=os.environ.get("HOST", "0.0.0.0"),
        port=int(os.environ.get("PORT", "8000")),
        reload=os.environ.get("RELOAD", "false").lower() == "true",
    )
