from __future__ import annotations

from clients._path_setup import ensure_paths

ensure_paths()

import time
from threading import Lock
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

from clients.movej_client import MoveJClient, action_music,action_air,action_drive_comfort,action_drive_economy,action_hello


app = FastAPI(title="Humanoid Robot Control API (Blocking + Mutex + Ignore)")

class ActionResponse(BaseModel):
    code: int
    msg: str
    action: Optional[str] = None
    ignored: bool = False

class StatusResponse(BaseModel):
    running: bool
    current_action: Optional[str]
    last_action: Optional[str]
    last_finished_at: Optional[float]


# 🔒 全局唯一互斥锁：保证同一时间只能执行一个 action
action_lock = Lock()

# 状态变量（简单可用；多线程更严谨可再加锁，这里够用）
running = False
current_action = None
last_action = None
last_finished_at = None


def run_action_blocking_ignore_if_busy(action_func, action_name: str) -> ActionResponse:
    """
    通用执行模板：
    - 忙：直接忽略（立即返回，不执行）
    - 空闲：阻塞执行，执行完再返回
    """
    global running, current_action, last_action, last_finished_at

    # 忙就忽略（静默丢弃动作）
    if not action_lock.acquire(blocking=False):
        return ActionResponse(
            code=0,
            msg=f"{action_name} ignored: robot busy",
            action=action_name,
            ignored=True,
        )

    client = MoveJClient()
    # client = 0
    running = True
    current_action = action_name

    try:
        action_func(client)  # ✅ 阻塞到动作执行结束
        last_action = action_name
        last_finished_at = time.time()
        return ActionResponse(
            code=0,
            msg=f"{action_name} finished",
            action=action_name,
            ignored=False,
        )
    except Exception as e:
        return ActionResponse(
            code=1,
            msg=f"{action_name} failed: {e}",
            action=action_name,
            ignored=False,
        )
    finally:
        try:
            # print("closing action")
            client.close()
        finally:
            running = False
            current_action = None
            action_lock.release()


# @app.post("/action/one", response_model=ActionResponse)
# def call_action_one():
#     return run_action_blocking_ignore_if_busy(action_one, "action_one")

@app.post("/action/music", response_model=ActionResponse)
def call_action_music():
    return run_action_blocking_ignore_if_busy(action_music, "action_music")

@app.post("/action/air", response_model=ActionResponse)
def call_action_air():
    return run_action_blocking_ignore_if_busy(action_air, "action_air")

@app.post("/action/hello", response_model=ActionResponse)
def call_action_hello():
    return run_action_blocking_ignore_if_busy(action_hello, "action_hello")
# @app.post("/action/drive_comfort", response_model=ActionResponse)
# def call_action_drive_comfort():
#     return run_action_blocking_ignore_if_busy(action_drive_comfort, "action_drive_comfort")
#
# @app.post("/action/drive_economy", response_model=ActionResponse)
# def call_action_drive_economy():
#     return run_action_blocking_ignore_if_busy(action_drive_economy, "action_drive_economy")
#
# @app.post("/action/two", response_model=ActionResponse)
# def call_action_two():
#     return run_action_blocking_ignore_if_busy(action_two, "action_two")
# @app.post("/action/two", response_model=ActionResponse)
# def call_action_two():
#     return run_action_blocking_ignore_if_busy(action_two, "action_two")

@app.get("/status", response_model=StatusResponse)
def get_status():
    return StatusResponse(
        running=running,
        current_action=current_action,
        last_action=last_action,
        last_finished_at=last_finished_at,
    )


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "http_server:app",
        host="0.0.0.0",
        port=8000,
        reload=False
    )
