# -*- coding: utf-8 -*-
"""
@File: main.py
@Date: 2020-09-14
@author: A2TEC
@section MODIFYINFO 수정정보
- 수정자/수정일   : 수정내역
- 2022-01-14/hsj100@a2tec.co.kr : refactoring
@brief: Main
"""

from dataclasses import asdict

import uvicorn
from fastapi import FastAPI, Depends
from fastapi.security import APIKeyHeader
from fastapi.staticfiles import StaticFiles
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.middleware.cors import CORSMiddleware

from main_rest.app.common import consts

from main_rest.app.database.conn import db
from main_rest.app.common.config import conf
from main_rest.app.middlewares.token_validator import access_control
from main_rest.app.middlewares.trusted_hosts import TrustedHostMiddleware
from main_rest.app.routes import dev, index, auth, users, services
from contextlib import asynccontextmanager

from custom_logger.main_log import main_logger as LOG


API_KEY_HEADER = APIKeyHeader(name='Authorization', auto_error=False)


@asynccontextmanager
async def lifespan(app: FastAPI):
    # When service starts.
    LOG.info(f"REST start (port : {conf().REST_SERVER_PORT})")
    
    import os
    import const
    if os.path.exists(const.TEMP_FOLDER):
        for _file in os.scandir(const.TEMP_FOLDER):
            os.remove(_file)
    
    LOG.info(f"temp folder clean")
    
    yield
    
    # When service is stopped.
    LOG.info("REST shutdown")


def create_app():
    """
    fast_api_app 생성

    :return: fast_api_app
    """
    configurations = conf()
    fast_api_app = FastAPI(
        title=configurations.SW_TITLE,
        version=configurations.SW_VERSION,
        description=configurations.SW_DESCRIPTION,
        terms_of_service=configurations.TERMS_OF_SERVICE,
        contact=configurations.CONTEACT,
        license_info={'name': 'Copyright by A2TEC', 'url': 'http://www.a2tec.co.kr'},
        lifespan=lifespan
    )

    # 데이터 베이스 이니셜라이즈
    conf_dict = asdict(configurations)
    db.init_app(fast_api_app, **conf_dict)

    # 레디스 이니셜라이즈

    # 미들웨어 정의
    fast_api_app.add_middleware(middleware_class=BaseHTTPMiddleware, dispatch=access_control)
    fast_api_app.add_middleware(
        CORSMiddleware,
        allow_origins=conf().ALLOW_SITE,
        allow_credentials=True,
        allow_methods=['*'],
        allow_headers=['*'],
    )
    fast_api_app.add_middleware(TrustedHostMiddleware, allowed_hosts=conf().TRUSTED_HOSTS, except_path=['/health'])

    # 라우터 정의
    fast_api_app.include_router(index.router, tags=['Defaults'])
    
    # if conf().DEBUG:
        # fast_api_app.include_router(auth.router, tags=['Authentication'], prefix='/api')

    fast_api_app.include_router(services.router, tags=['Services'], prefix='/api', dependencies=[Depends(API_KEY_HEADER)])

    # if conf().DEBUG:
    #     fast_api_app.include_router(users.router, tags=['Users'], prefix='/api', dependencies=[Depends(API_KEY_HEADER)])
    #     fast_api_app.include_router(dev.router, tags=['Developments'], prefix='/api', dependencies=[Depends(API_KEY_HEADER)])
    
    import os
    # fast_api_app.mount('/static', StaticFiles(directory=os.path.abspath('./rest/app/static')), name="static")
    
    return fast_api_app


app = create_app()

#TODO(jwkim): 422 error handler
# @app.exception_handler(RequestValidationError)
# async def validation_exception_handler(request, exc):
#     err = exc.errors()
#     return JSONResponse(
#         status_code=422,
#         content={
#             "result": False,
#             "error": f"VALIDATION ERROR : {err}",
#             "data": None},
#     )

if __name__ == '__main__':
    uvicorn.run('main:app', host='0.0.0.0', port=conf().REST_SERVER_PORT, reload=True)
