"""
main.py
Main API file used for handling Prestonet API reqs
Author: Vojtech Pokorny, vojtech.pokorny@prestonet.cz
Date (last edit): 6.2.2025
Note: Using framework FastAPI
"""

# Importing FastAPI libraries
from fastapi import FastAPI, Depends, HTTPException, status, Request
from fastapi.security import APIKeyHeader, HTTPBearer, HTTPAuthorizationCredentials
from fastapi.responses import FileResponse

# Importing classic Python libraries
import os
from dotenv import load_dotenv
from fastapi import FastAPI, Request, Depends
import json
import logging
from datetime import datetime
from db import get_db_pool
import requests

# Importing scripts
from scripts import *

# FastAPI instance
app = FastAPI()

# Get API KEY value
load_dotenv()
API_KEY = os.getenv("API_KEY")

# HTTP Bearer, Google Token
http_bearer = HTTPBearer()
GOOGLE_TOKEN_INFO_URL = "https://oauth2.googleapis.com/tokeninfo"

# API Key Configuration
API_KEY_NAME = "x-api-key" # Header name
api_key_header = APIKeyHeader(name=API_KEY_NAME)

# Získáme pool při startu serveru
@app.on_event("startup")
async def startup():
    app.state.db_pool = await get_db_pool()

# Zavřeme pool při vypnutí
@app.on_event("shutdown")
async def shutdown():
    await app.state.db_pool.close()

# Dependency to authenticate Token
async def authenticate_google_token(credentials: HTTPAuthorizationCredentials = Depends(http_bearer)):
    token = credentials.credentials

    # Verify token with Google
    response = requests.get(GOOGLE_TOKEN_INFO_URL, params={'access_token': token})
    if response.status_code != 200:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid Google access token")

    token_info = response.json()
    email = token_info.get('email')

    if not email:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Email not found in token")

    # OPTIONAL: Check domain
    allowed_domain = os.getenv("ALLOWED_GOOGLE_DOMAIN", "prestonet.cz")
    if not email.endswith(f"@{allowed_domain}"):
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Unauthorized domain")

    return email  # Return the verified email

# Dependency to authenticate API key
async def authenticate(api_key: str = Depends(api_key_header)):
	if api_key != API_KEY:
		raise HTTPException(
			status_code=status.HTTP_403_FORBIDDEN,
			detail="Invalid API key",
		)

# Default route
@app.get("/", dependencies=[Depends(authenticate)])
async def read_root():
	return {
		"message": "Welcome to the Prestonet API server!",
		"auth": 1
	}

# Test route
@app.get("/test", dependencies=[Depends(authenticate)])
async def get_test():
	try:
		return get_test_json()
	except Exception as e:
		raise HTTPException(
			status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
			detail=f"An error occurred: {str(e)}",
		)

# QRcode route
@app.get("/qrcode", dependencies=[Depends(authenticate)])
async def get_qrcode(ssid, password, output_file):
	try:
		return generate_qrcode(ssid, password, output_file)
	except ValueError as ve:
		raise HTTPException(
			status_code=status.HTTP_400_BAD_REQUEST,
		    	detail=str(ve)
		)
	except Exception as err:
		raise HTTPException(
            		status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
		    	detail=f"An error occurred: {str(err)}"
		)

# Prestonet Webhooks Log
LOG_FILE = "logs/prestonet_webhooks.log"
logging.basicConfig(filename=LOG_FILE, level=logging.INFO, format="%(asctime)s - %(message)s")

@app.post("/log/prestonet-webhooks", dependencies=[Depends(authenticate)])
async def add_log(request: Request):
	try:
		# body = await request.json()
		# log_entry = json.dumps(body, separators=(',', ':'))
		# logging.info(log_entry)
		body = await request.json()
		logging.info(f"Received body: {body}")

        	# příklad extrakce z payloadu
		user = body.get("user")
		application = body.get("application")
		object = body.get("object")
		object_id = body.get("object_id")
		input = body.get("input")
		button = body.get("button")
		webhook_url = body.get("webhook_url")
		run_id = body.get("run_id")
		status = body.get("status")
		status = str(status) if status is not None else None

		await add_log_to_db(
			app.state.db_pool,
			user=user,
			application=application,
			object=object,
			object_id=object_id,
			input=input,
			button=button,
			webhook_url=webhook_url,
			run_id=run_id,
			status=status
		)
		return {"message": "Log saved", "status": "success"}
	except Exception as e:
		logging.error(f"Error saving log: {str(e)}")
		return {"message": "Failed to save log", "status": "error"}

@app.get("/log/prestonet-webhooks", dependencies=[Depends(authenticate)])
async def get_logs(button_name):
	try:
		return get_button_logs("/var/www/api/logs/prestonet_webhooks.log", button_name)
	except ValueError as ve:
		raise HTTPException(
			status_code=status.HTTP_400_BAD_REQUEST,
			detail=str(ve)
		)
	except Exception as err:
		raise HTTPException(
			status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
			detail=f"An error occurred: {str(err)}"
		)

# Prestonet Webhooks admin users
@app.get("/prestonet-webhooks/admin", dependencies=[Depends(authenticate)])
async def get_admin_prestonet_webhooks():
	try:
		return get_admin_list()
	except ValueError as ve:
		raise HTTPException(
			status_code=status.HTTP_400_BAD_REQUEST,
			detail=str(ve)
		)
	except Exception as err:
		raise HTTPException(
			status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
			detail=f"An error occurred: {str(err)}"
		)

@app.get("/prestonet-webhooks/groups", dependencies=[Depends(authenticate)])
async def get_groups_prestonet_webhooks(email):
	try:
		return get_user_group_list(email)
	except ValueError as ve:
		raise HTTPException(
			status_code=status.HTTP_400_BAD_REQUEST,
			detail=str(ve)
		)
	except Exception as err:
		raise HTTPException(
			status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
			detail=f"An error occurred: {str(err)}"
		)

# Set the directory where your images are stored.
# If the images folder is at an absolute path like '/images', use that instead.
IMAGES_DIR = os.path.join(os.path.dirname(__file__), "images")

@app.get("/download/{filename}")
async def download_file(filename: str):
    return
	# Construct the full file path
	#file_path = os.path.join(IMAGES_DIR, filename)

	# Check if the file exists; if not, raise a 404 error.
	#if not os.path.isfile(file_path):
		#raise HTTPException(status_code=404, detail="File not found")

	# Return the file as a downloadable response.
	# 'application/octet-stream' signals a binary file download.
	#return FileResponse(
		#path=file_path,
		#media_type='application/octet-stream',
		#filename=filename  # This will set the 'Content-Disposition' header to trigger a download.
	#)

@app.get("/gpt-tokens", dependencies=[Depends(authenticate)])
async def get_gpt_count(prompt, model="gpt-4o-mini"):
    try:
        return {"number_of_tokens" : count_tokens(prompt, model)}
    except ValueError as ve:
        raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=str(ve)
                )
    except Exception as err:
        raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"An error occured {str(err)}"
                )
