
from __future__ import annotations
from fastapi import APIRouter, FastAPI, Response, UploadFile, File, Form, Request
from http import HTTPStatus
from fastapi.middleware.cors import CORSMiddleware
from pathlib import Path
from .routes import set_routes
from percolate import __version__
from starlette.middleware.sessions import SessionMiddleware
from uuid import uuid1
from datetime import datetime
from starlette.middleware.base import BaseHTTPMiddleware
import os
import json
from percolate.utils import logger
from contextlib import asynccontextmanager
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
import percolate as p8
from percolate.models.p8.types import Schedule
# Global scheduler instance
scheduler = BackgroundScheduler()

def run_scheduled_job(schedule_record):
    """Placeholder job runner for scheduled tasks."""
    logger.info(f"Running scheduled task {schedule_record} ")

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan: start and shutdown scheduler."""
    
    repo = p8.repository(Schedule)
    table = Schedule.get_model_table_name()  
   
    try:
        data = repo.execute(f"SELECT * FROM {table} WHERE disabled_at IS NULL")
        for d in data:
            try:
                record = Schedule(**d)
                trigger = CronTrigger.from_crontab(record.schedule)
                scheduler.add_job(run_scheduled_job, trigger, args=[record], id=str(record.id))
            except Exception as e:
                logger.warning(f"Failed to schedule job for record {d.get('id')}: {e}")
    except Exception as ex:
        logger.warning(f"Failed to load scheduler data {ex}")
    scheduler.start()
    logger.info(f"Scheduler started with jobs: {[j.id for j in scheduler.get_jobs()]}")
    try:
        yield
    finally:
        scheduler.shutdown()


app = FastAPI(
    title="Percolate",
    openapi_url=f"/openapi.json",
    description=(
        """Percolate server can be used to do maintenance tasks on the database and also to test the integration of APIs in general"""
    ),
    version=__version__,
    contact={
        "name": "Percolation Labs",
        "url": "https://github.com/Percolation-Labs/percolate.git",
        "email": "percolationlabs@gmail.com",
    },
    license_info={
        "name": "MIT",
        "url": "https://opensource.org/licenses/MIT",
    },
    docs_url="/swagger",
    redoc_url=f"/docs",
    lifespan=lifespan,
)

k = str(uuid1())

logger.info('Percolate api app started')
 
app.add_middleware(SessionMiddleware, secret_key=k)
#app.add_middleware(PayloadLoggerMiddleware)


api_router = APIRouter()

origins = [
    "http://localhost:5008",
]

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


@app.get("/", include_in_schema=False)
@app.get("/healthcheck", include_in_schema=False)
async def healthcheck():
    return {"status": "ok"}

@app.get("/ping", include_in_schema=False)
async def ping():
    return Response(status_code=HTTPStatus.OK)


    
# Create the apple-app-site-association file content
# Replace YOUR_TEAM_ID with your actual Apple Developer Team ID
def get_aasa_content(team_id):
    return {
        "applinks": {
            "apps": [],
            "details": [
                {
                    "appID": f"{team_id}.EEPIS.EepisApp",
                    "paths": ["/auth/google/callback*"]
                }
            ]
        }
    }

@app.get("/.well-known/apple-app-site-association")
async def serve_apple_app_site_association():
    # Replace with your actual Team ID
    team_id = os.environ.get("APPLE_TEAM_ID", "SG2497YYXJ")
    
    content = get_aasa_content(team_id)
    
    # Return JSON with the correct content type
    return Response(
        content=json.dumps(content),
        media_type="application/json"
    )
    
app.include_router(api_router)
set_routes(app)

@app.get("/models")
def get_models():
    """
    
    List the models that have configured tokens in the Percolate database. Only models with tokens set will be shown
    """
    
    from percolate.models.p8 import LanguageModelApi
    import percolate as p8
    
    data  = p8.repository(LanguageModelApi).execute(f"""select name as id, token_env_key, created_at as created, updated_at as updated from p8."LanguageModelApi" where token is not null """)
    
    data =  [{
        'id': r['id'],
        'created': r['created'],
        'updated': r['updated'],
        'object': 'model',
        
    } for r in data]
    
    return {'object':'list', 'data': data}
    
def start():
    import uvicorn

    uvicorn.run(
        f"{Path(__file__).stem}:app",
        host="0.0.0.0",
        port=5008,
        log_level="debug",
        reload=True,
    )


if __name__ == "__main__":
    """
    You can start the dev with this in the root
    if running the docker image we keep the same port and stop the service in docker - this makes it easier to test in dev
    for example: 
    1. docker compose stop percolate-api
    2. uvicorn percolate.api.main:app --port 5008 --reload 
    Now we are running the dev server on the same location that the database etc expects
    Also add percolate-api mapped to localhost in your hosts files
    
    http://127.0.0.1:5008/docs or /swagger
    """
    
    start()