from fastapi import FastAPI, Request, Depends
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.templating import Jinja2Templates
from app.core.database import init_db, get_db
from app.routes import (
    auth, customers, list_customers, technician, settings, voucher_agents,
    vouchers, payments, users, billing, devices, customer_management, reports,
    ops, service_packages,
)
from app.core.security import get_current_user
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import func, select
import uvicorn
import os
import asyncio
from dotenv import load_dotenv
from app.core.status_monitor import monitor_loop

app = FastAPI(title="BestWeb Billing")
status_monitor_task = None
app.add_middleware(GZipMiddleware, minimum_size=500, compresslevel=5)

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
load_dotenv(os.path.join(BASE_DIR, ".env"))
load_dotenv(os.path.join(BASE_DIR, "app", ".env"), override=False)
app.mount("/static", StaticFiles(directory=os.path.join(BASE_DIR, "static")), name="static")
templates = Jinja2Templates(directory=os.path.join(BASE_DIR, "app", "templates"))

for router in (
    auth.router, customers.router, list_customers.router, technician.router,
    settings.router, voucher_agents.router, vouchers.router, payments.router,
    users.router, billing.router, devices.router, customer_management.router,
    reports.router, ops.router, service_packages.router,
):
    app.include_router(router)


@app.on_event("startup")
async def on_startup():
    await init_db()
    global status_monitor_task
    status_monitor_task = asyncio.create_task(monitor_loop())


@app.on_event("shutdown")
async def on_shutdown():
    global status_monitor_task
    if status_monitor_task:
        status_monitor_task.cancel()
        try:
            await status_monitor_task
        except asyncio.CancelledError:
            pass
        status_monitor_task = None


@app.get("/", response_class=HTMLResponse)
async def home(
    request: Request,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
):
    from app.models.models import Customer
    visible = Customer.is_archived == False
    async def count(*conditions):
        return await db.scalar(select(func.count(Customer.id)).where(visible, *conditions)) or 0

    total = await count()
    pending = await count(Customer.status.in_(("request", "pending_provisioning")))
    installing = await count(Customer.status == "installing")
    configuring = await count(Customer.status == "configuring")
    active = await count(Customer.status == "active")
    los = await count(Customer.olt_provisioning_status == "los")
    dying_gasp = await count(Customer.olt_provisioning_status == "dying_gasp")
    offline = await count(Customer.olt_provisioning_status == "offline")
    waiting = await count(Customer.olt_provisioning_status == "provisioned", Customer.mikrotik_provisioning_status == "waiting_session")
    online = await count(Customer.olt_provisioning_status == "provisioned")

    return templates.TemplateResponse(
        request=request,
        name="index.html",
        context={
            "title": "BestWeb Billing System",
            "message": "Sistem Manajemen ISP: Bulanan PPP & Hotspot Voucher.",
            "current_user": current_user,
            "stats": {
                "total": total, "pending": pending, "installing": installing,
                "configuring": configuring, "active": active,
                "los": los, "dying_gasp": dying_gasp, "offline": offline,
                "waiting": waiting, "online": online,
            },
        },
    )
async def home(
    request: Request,
    db: AsyncSession = Depends(get_db),
    current_user=Depends(get_current_user),
):
    from app.models.models import Customer

    visible = Customer.is_archived == False
    async def count(*conditions):
        return await db.scalar(select(func.count(Customer.id)).where(visible, *conditions)) or 0

    total = await count()
    pending = await count(Customer.status.in_(("request", "pending_provisioning")))
    installing = await count(Customer.status == "installing")
    configuring = await count(Customer.status == "configuring")
    active = await count(Customer.status == "active")
    ppp = await count(Customer.type == "bulanan_ppp")
    hotspot = await count(Customer.type == "hotspot_voucher")
@app.get("/api/dashboard/stats")
async def api_dashboard_stats(db: AsyncSession = Depends(get_db)):
    from app.models.models import Customer
    visible = Customer.is_archived == False
    async def count(*conditions):
        return await db.scalar(select(func.count(Customer.id)).where(visible, *conditions)) or 0
    
    total = await count()
    pending = await count(Customer.status.in_(("request", "pending_provisioning")))
    installing = await count(Customer.status == "installing")
    configuring = await count(Customer.status == "configuring")
    active = await count(Customer.status == "active")
    los = await count(Customer.olt_provisioning_status == "los")
    dying_gasp = await count(Customer.olt_provisioning_status == "dying_gasp")
    offline = await count(Customer.olt_provisioning_status == "offline")
    waiting = await count(Customer.olt_provisioning_status == "provisioned", Customer.mikrotik_provisioning_status == "waiting_session")
    online = await count(Customer.olt_provisioning_status == "provisioned")
    
    return {
        "total": total, "pending": pending, "installing": installing,
        "configuring": configuring, "active": active,
        "los": los, "dying_gasp": dying_gasp, "offline": offline,
        "waiting": waiting, "online": online
    }
if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
