{% include "templates/base/passwordless.py.j2" %}

from fastapi import APIRouter, Depends, HTTPException, Request, status

_runtime: Optional[PasswordlessRuntime] = None


def get_runtime() -> PasswordlessRuntime:
	global _runtime
	if _runtime is None:
		_runtime = PasswordlessRuntime(load_passwordless_settings())
	return _runtime


def create_router() -> APIRouter:
	"""Expose endpoints for issuing and verifying passwordless tokens."""

	router = APIRouter(prefix="/passwordless", tags=["passwordless"])

	@router.get("/metadata", response_model=Dict[str, Any])
	def get_metadata() -> Dict[str, Any]:
		return describe_passwordless()

	@router.get("/features", response_model=Dict[str, Any])
	def get_features() -> Dict[str, Any]:
		return {"features": list_passwordless_features()}

	@router.post("/tokens", status_code=status.HTTP_201_CREATED)
	async def issue_token(  # type: ignore[no-untyped-def]
		request: Request,
		runtime: PasswordlessRuntime = Depends(get_runtime),
	) -> Dict[str, Any]:
		payload = await request.json()
		identifier = payload.get("identifier")
		delivery_method = payload.get("delivery_method", "email")
		metadata = payload.get("metadata") or {}
		if not isinstance(identifier, str) or not identifier:
			raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="identifier is required")
		if not isinstance(metadata, dict):
			metadata = {}
		try:
			token = runtime.issue_code(
				identifier,
				delivery_method=delivery_method,
				metadata=metadata,
			)
		except ValueError as exc:
			raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc

		return {
			"token_id": token.token_id,
			"code": token.code,
			"delivery_method": token.delivery_method,
			"expires_at": token.expires_at,
		}

	@router.post("/magic-link", status_code=status.HTTP_201_CREATED)
	async def issue_magic_link(  # type: ignore[no-untyped-def]
		request: Request,
		runtime: PasswordlessRuntime = Depends(get_runtime),
	) -> Dict[str, Any]:
		payload = await request.json()
		identifier = payload.get("identifier")
		delivery_method = payload.get("delivery_method", "email")
		metadata = payload.get("metadata") or {}
		if not isinstance(identifier, str) or not identifier:
			raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="identifier is required")
		if not isinstance(metadata, dict):
			metadata = {}
		try:
			issued = runtime.issue_magic_link(
				identifier,
				delivery_method=delivery_method,
				metadata=metadata,
			)
		except ValueError as exc:
			raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc

		return {
			"token_id": issued.token.token_id,
			"url": issued.url,
			"expires_at": issued.token.expires_at,
		}

	@router.post("/verify", status_code=status.HTTP_200_OK)
	async def verify_code(  # type: ignore[no-untyped-def]
		request: Request,
		runtime: PasswordlessRuntime = Depends(get_runtime),
	) -> Dict[str, Any]:
		payload = await request.json()
		identifier = payload.get("identifier")
		code = payload.get("code")
		delivery_method = payload.get("delivery_method")
		if not isinstance(identifier, str) or not isinstance(code, str):
			raise HTTPException(
				status.HTTP_400_BAD_REQUEST,
				detail="identifier and code required",
			)
		try:
			token = runtime.verify_code(
				identifier,
				code,
				delivery_method=delivery_method,
			)
		except ValueError as exc:
			raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc

		return {
			"token_id": token.token_id,
			"identifier": token.identifier,
			"metadata": token.metadata,
		}

	return router


__all__.extend(["get_runtime", "create_router"])
