from __future__ import annotations from flask_openapi3 import APIBlueprint, Tag from pydantic import BaseModel, Field from swingmusic.services.setup_state import ( bootstrap_setup, configure_primary_directory, get_setup_status, trigger_initial_index, ) bp_tag = Tag(name="Setup", description="First-run setup and onboarding state") api = APIBlueprint("setup", __name__, url_prefix="/setup", abp_tags=[bp_tag]) class SetupBootstrapBody(BaseModel): username: str = Field(description="Owner username for first boot") password: str = Field(description="Owner password for first boot") root_dirs: list[str] = Field( default_factory=list, description="Initial primary music directories", ) class SetupDirectoryBody(BaseModel): root_dirs: list[str] = Field( default_factory=list, description="Primary music directories to use for indexing", ) class SetupIndexStartBody(BaseModel): force: bool = Field( default=False, description="Force queueing a new initial index run", ) @api.get("/status") def setup_status(): return get_setup_status() @api.post("/bootstrap") def setup_bootstrap(body: SetupBootstrapBody): try: owner = bootstrap_setup( username=body.username, password=body.password, root_dirs=body.root_dirs, ) return { "success": True, "owner": { "id": owner.id, "username": owner.username, }, "setup": get_setup_status(), } except ValueError as error: return {"success": False, "error": str(error)}, 400 @api.post("/directory") def setup_directory(body: SetupDirectoryBody): status = get_setup_status() if status["setup_completed"]: return { "success": False, "error": "Setup is already completed.", "setup": status, }, 400 if not status["owner_created"]: return { "success": False, "error": "Create the owner account before configuring directories.", "setup": status, }, 400 try: queued = configure_primary_directory(root_dirs=body.root_dirs) except ValueError as error: return {"success": False, "error": str(error)}, 400 return { "success": True, "queued": queued, "setup": get_setup_status(), } @api.get("/index-progress") def setup_index_progress(): status = get_setup_status() return { "index_state": status["index_state"], "index_progress": status["index_progress"], "index_message": status["index_message"], "initial_index_completed": status["initial_index_completed"], } @api.post("/index/start") def setup_index_start(body: SetupIndexStartBody): status = get_setup_status() if not status["owner_created"] or not status["directory_configured"]: return { "queued": False, "error": "Owner account and primary music directory are required before indexing.", "setup": status, }, 400 queued = trigger_initial_index(force=body.force) status = get_setup_status() return { "queued": queued, "setup": status, }