from my_modules.functions import custom_limit_key, get_my_ip_address, get_local_ip_addresses, replace_last_ip_segment, generate_all_ips
from my_modules.app.constens import SECRET_KEY, THE_IP_BOT_MANAGER
from my_modules.AsyncCache import AsyncCache
from my_modules.app.logger import logger

from my_helpers.db.convex.ConvexRuntime import ConvexRuntime
from my_helpers.db.convex.ConvexWorkerPool import ConvexWorkerPool
from my_modules.db.ConvexDB import ConvexDB

from quart_session import Session
from flask_limiter import Limiter

import redis.asyncio as aioredis
from quart import Quart
import os

app = Quart(__name__, template_folder="../../templates/side", static_folder="../../templates/static")
app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 1024

app.secret_key = SECRET_KEY

# Cache, Sessions and Limiter over Valkey
if os.getenv("VALKEY_HOST", None) is not None:
  cache = AsyncCache(
    backend='redis',
    default_ttl=300,
    username=os.getenv('VALKEY_CACHE_USER', ''),
    password=os.getenv('VALKEY_CACHE_PASSWORD', ''),
    host=os.getenv('VALKEY_HOST'),
    port=os.getenv('VALKEY_PORT', 6379),
    db=os.getenv('VALKEY_DB', 0)
  )
else:
  cache = AsyncCache(
    backend='memory',
  )

if os.getenv("VALKEY_HOST", None) is not None:
  app.config.from_mapping(
    SESSION_TYPE="redis",
    SESSION_PERMANENT=True,
    SESSION_USE_SIGNER=True,
    SESSION_REDIS = aioredis.Redis(
      username=os.getenv('VALKEY_SESSION_USER', None),
      password=os.getenv('VALKEY_SESSION_PASSWORD', None),
      host=os.getenv("VALKEY_HOST"),
      port=os.getenv("VALKEY_PORT", 6379),
      db=os.getenv("VALKEY_DB", 0),
      decode_responses=True
    )
  )
else:
  app.config.from_mapping(
    SESSION_TYPE='memcached',
  )

Session(app)

LIMITER = Limiter(
  custom_limit_key,
  app=app,
  storage_uri=(
    f"redis://{os.getenv('VALKEY_LIMITER_USER', '')}:{os.getenv('VALKEY_LIMITER_PASSWORD', '')}"
    f"@{os.getenv("VALKEY_HOST")}:{os.getenv('VALKEY_PORT', 6379)}/{os.getenv('VALKEY_DB', 0)}"
  ) if os.getenv("VALKEY_HOST") else None,
  default_limits=[],
  strategy='moving-window'
)

convex_runtime = ConvexWorkerPool(os.getenv("CONVEX_URL"))
app.convex_runtime = convex_runtime

@app.before_serving
async def init_convex():
  await convex_runtime.start()
  app.convex = ConvexDB(runtime=convex_runtime)

  THE_IP_BOT_MANAGER.add_always_allowed_ip('127.0.0.1')
  THE_IP_BOT_MANAGER.add_always_allowed_ip(await get_my_ip_address())

  local_docker_host_ip = get_local_ip_addresses()
  if local_docker_host_ip:
    base_ip = replace_last_ip_segment(local_docker_host_ip, 1)
    all_local_ips = generate_all_ips(base_ip)
    THE_IP_BOT_MANAGER.update_always_allowed_ip(all_local_ips)

@app.after_serving
async def close_convex():
  if app.convex:
    await convex_runtime.stop()
  await logger.shutdown()
