from fastapi import FastAPI, Cookie, Response, Request
from fastapi.middleware.cors import CORSMiddleware

import os
import uvicorn

from backio import *
from backio import login as pure_login

Modules = get_modules_from_yaml()

os.environ[ENV_SECRET] = str(os.urandom(24))

APP_HOST = host_for_api
APP_PORT = port_for_api

app = FastAPI()
app.add_middleware(
  CORSMiddleware,
  allow_origins=http_allowed_origins(),
  allow_credentials=True,
  allow_methods=['*'],
  allow_headers=['*'],)

#########################################################

@app.get('/hello')
@app.post('/hello')
def say_hello():
  return hello()

@app.get('/hello/zone')
@app.post('/hello/zone')
def say_hello_zone(id: int):
  return hello_zone(zoneid=id)

@app.get('/module')
@app.post('/module')
def say_module(function: str):
  return what_module(Modules, function)

@app.get('/access')
@app.post('/access')
def say_access(function: str):
  return {
    'access': get_afunc(function, pop=hstr),
    'notice': get_erole(function),
    'data': get_edata(function),
    'argument': get_afarg(function)}

@app.get('/timeout')
@app.post('/timeout')
def say_timeout():
  return {'session_timeout': token_expire_minutes}

@app.get('/client')
@app.post('/client')
def client(request: Request, access_token: str=Cookie(None)):
  return {'host': request.client.host, 'port': request.client.port}

@app.get('/login', response_model=Token)
@app.post('/login', response_model=Token)
def login(username: str, password: str, response: Response):
  return do_login(username, password, response)

@app.get('/logout')
@app.post('/logout')
def logout(response: Response):
  return do_logout(response)

@app.get('/me', response_model=User)
@app.post('/me', response_model=User)
def me(access_token: str=Cookie(None)):
  return get_current_user(access_token)

#########################################################

@app.get('/init/admin')
@app.post('/init/admin')
def init_admin(adminpass: str=DEFPASSWORD):
  return init_admin_database(adminpass)

@app.get('/init/zone')
@app.post('/init/zone')
def init_zone(zoneid: int, access_token: str=Cookie(None)):
  return init_zone_database(zoneid, access_token)

@app.get('/init/accounting')
@app.post('/init/accounting')
def init_accounting(zoneid: int, access_token: str=Cookie(None)):
  return init_accounting_database(zoneid, access_token)

@app.get('/data/dump/tables')
@app.post('/data/dump/tables')
def data_dump_tables(zone: str, access_token: str=Cookie(None)):
  return dump_database_tables(zone, access_token)

@app.get('/data/dump')
@app.post('/data/dump')
def data_dump(zone: str, table: str, idr: str='', access_token: str=Cookie(None)):
  return dump_zone_database(zone, table, access_token, idr=[] if not idr else idr.split(','))

@app.get('/data/load')
@app.post('/data/load')
def data_load(csv: str, zone: str, table: str, access_token: str=Cookie(None)):
  return load_zone_database(csv, zone, table, access_token)

#########################################################

@app.get('/call')
@app.post('/call')
def call(function: str, jsondata: str='{}', module: str='', access_token: str=Cookie(None)):
  if not module: module = function_module2(module_access, function)
  run = popattr(Modules.get(module), function)
  if not run: return error_unexpect(ERR_FUNCTION)
  try:
    return run(jsondata, access_token)
  except Exception as e:
    return error_unexpect(e)

def app_init():
  import argparse
  parser = argparse.ArgumentParser(description=f"LITERP COMPACT API SERVER {app_consts.get('VERSION')}")
  parser.add_argument('-p', '--port', type=int, default=APP_PORT, help=f'apply server http port, default "{APP_PORT}"')
  parser.add_argument('-d', '--db', type=str, default='sqlite', help=f'apply database engine, default "sqlite"')
  parser.add_argument('-c', '--cert', type=str, default='literp.pem', help=f'SSL certificate file path')
  parser.add_argument('-k', '--key', type=str, default='literp-key.pem', help=f'SSL key file path')
  args = parser.parse_args()
  if (db:=dict_extract(app_consts, f'database_engines.{args.db}')):
    set_engine(getattr(this, db.get('engine')))
    set_connect(getattr(this, db.get('connect')))
  return app, APP_HOST, args.port, args.cert, args.key

#########################################################