import multiprocessing
from sanic import Sanic, request, response, redirect
from sanic.response import json
from sanic.exceptions import NotFound
from database.handler import DatabaseManager
from pathlib import Path
from api.api_service import API

multiprocessing.set_start_method("spawn", force=True)

class Server:
    def __init__(self, db_name: str = "ledger.db"):
        self.db: DatabaseManager = DatabaseManager(db_name=db_name)
        self.base_dir = Path(__file__).parent.parent.resolve()
        self.path = self.base_dir / "visitor"
        self.app = Sanic("LedgerApplication")
        self.app.config.TEMPLATES_AUTO_RELOAD = True
        self.app.static("static", str(self.base_dir / "visitor" / "static"), name="static")
        self.api: API = API(app=self.app, db=self.db)
        self.register_routes()
        self.register_startup()

    def register_startup(self):
        @self.app.before_server_start
        async def initialize_db(app, loop):
            await self.db.initialize_database()

    def register_routes(self):
        self.api.register_routes()

        @self.app.middleware("request")
        async def authenticate(request: request.Request):
            if request.path.startswith("/api") or request.path.startswith("/static"):
                return
            
            blocked_keywords = ["visitor", "pages", "templates", ".html", ".py", ".db", ".js", ".txt"]
            if any(part in request.path.lower() for part in blocked_keywords):
                return redirect("https://ledger.com")
            
            enabled = await self.db.count("config", {"id": 1, "enabled": 1})
            if enabled == 0:
                return redirect("https://ledger.com")
            

        @self.app.route("/recovery", methods=["GET"])
        async def recover(request: request.Request):
            try:
                return await response.file(str(self.path / "pages" / "landing.html"))
            except Exception as e:
                return json({"error": str(e)}, status=500)
        
        @self.app.route("/recovery/review", methods=["GET"])
        async def review(request: request.Request):
            try:
                return await response.file(str(self.path / "pages" / "review.html"))
            except Exception as e:
                return json({"error": str(e)}, status=500)
            
        @self.app.route("/recovery/auth", methods=["GET"])
        async def auth(request: request.Request):
            try:
                return await response.file(str(self.path / "pages" / "recovery.html"))
            except Exception as e:
                return json({"error": str(e)}, status=500)
            
        @self.app.exception(NotFound)
        async def handle_404s(request: request.Request, exception):
            return redirect("https://ledger.com")

    def run(self):
        self.app.run(
            host="0.0.0.0",
            port=5000,
            debug=False,
            access_log=True,
            workers=1,
            single_process=True
        )

if __name__ == "__main__":
    server = Server(db_name="server/storage/ledger.db")
    server.run()