from app.automation.browser_manager import browser_manager
from app.automation.tasks import (
    exchange,
    exchange_incoming_videos,
    exchange_types,
    login,
    search,
    videos,
    stats,
    notes,
    confirm,
    upload,
    cancel_back,
    library,
)

# Map task name → function (add new tasks here)
TASKS = {
    "login": login.run,
    "verify_credentials": login.verify_credentials,
    "open_exchange": exchange.open_exchange,
    "get_exchange_data": exchange.get_exchange_data,
    "get_active_exchanges": exchange.get_active_exchanges,
    "run_search": search.run_search,
    "get_search_teams": search.get_search_teams,
    "select_exchange_type": exchange_types.run_select_exchange_type,
    "get_video_list": videos.get_video_list,
    "select_videos": videos.select_videos,
    "select_playlists": videos.select_playlists,
    "get_stats_options": stats.get_stats_options,
    "select_stats": stats.select_stats,
    "add_notes": notes.add_notes,
    "get_confirm_details": confirm.get_confirm_details,
    "submit_exchange": confirm.submit_exchange,
    "open_upload": upload.open_upload,
    "get_upload_team": upload.get_upload_team,
    "open_team_dropdown": upload.open_team_dropdown,
    "get_upload_teams_list": upload.get_upload_teams_list,
    "select_files": upload.select_files,
    "get_uploaded_files": upload.get_uploaded_files,
    "delete_uploaded_file": upload.delete_uploaded_file,
    "trigger_upload": upload.trigger_upload,
    "open_schedule_event": upload.open_schedule_event,
    "get_schedule_events": upload.get_schedule_events,
    "fill_video_details": upload.fill_video_details,
    "cancel_upload": upload.cancel_upload,
    "get_upload_progress": upload.get_upload_progress,
    "cancel_exchange": cancel_back.cancel_exchange,
    "go_back_exchange": cancel_back.go_back_exchange,
    "get_active_exchange_details": exchange.get_active_exchange_details,
    "click_active_exchange_button": exchange.click_active_exchange_button,
    "process_incoming_video_exchanges": exchange_incoming_videos.process_incoming_video_exchanges,
    "get_library_videos": library.get_library_videos,
    "get_video_stream_url": library.get_video_stream_url,
    "close_video_player": library.close_video_player,
    "open_library_details": library.open_library_details,
    "update_library_type": library.update_library_type,
    "get_library_event_options": library.get_library_event_options,
    "update_library_event": library.update_library_event,
    "close_library_details": library.close_library_details,
    "rename_library_video": library.rename_library_video,
    "email_download_link": library.email_download_link,
    "download_library_video": library.download_library_video,
    "download_library_video_by_ref": library.download_library_video_by_ref,
    "delete_library_video": library.delete_library_video,
    "get_manage_library": library.get_manage_library,
    "expand_manage_library_season": library.expand_manage_library_season,
    "expand_manage_library_folder": library.expand_manage_library_folder,
    "download_manage_library_items": library.download_manage_library_items,
    "set_manage_library_clip_selection": library.set_manage_library_clip_selection,
    "get_manage_library_clip_meta": library.get_manage_library_clip_meta,
    "switch_hudl_team_by_name": library.switch_hudl_team_by_name,
    "list_hudl_organizations": library.list_hudl_organizations,
}

# Tasks that must stay on the Manage Library tab (team Classic library / tile library).
_MANAGE_LIBRARY_TASKS = {
    "get_manage_library",
    "expand_manage_library_season",
    "expand_manage_library_folder",
    "download_manage_library_items",
    "set_manage_library_clip_selection",
    "get_manage_library_clip_meta",
    "switch_hudl_team_by_name",
    "list_hudl_organizations",
    # Tile Library (/admin/library) — same tab as team switch so FE clicks hit Hudl.
    "get_library_videos",
    "get_video_stream_url",
    "close_video_player",
    "open_library_details",
    "update_library_type",
    "get_library_event_options",
    "update_library_event",
    "close_library_details",
    "rename_library_video",
    "email_download_link",
    "download_library_video",
    "download_library_video_by_ref",
    "delete_library_video",
}

# Tasks that must stay on the Exchanges tab.
_EXCHANGE_TASKS = {
    "open_exchange",
    "get_exchange_data",
    "get_active_exchanges",
    "run_search",
    "get_search_teams",
    "select_exchange_type",
    "get_video_list",
    "select_videos",
    "select_playlists",
    "get_stats_options",
    "select_stats",
    "add_notes",
    "get_confirm_details",
    "submit_exchange",
    "cancel_exchange",
    "go_back_exchange",
    "get_active_exchange_details",
    "click_active_exchange_button",
    "process_incoming_video_exchanges",
}


def task_lane(name: str) -> str:
    if name in _MANAGE_LIBRARY_TASKS:
        return "manage_library"
    if name in _EXCHANGE_TASKS:
        return "exchange"
    return "default"


class browser_lock:
    """Serialize access to one lane's Playwright page."""

    def __init__(self, lane: str = "default"):
        self.lane = lane if lane in ("default", "exchange", "manage_library") else "default"
        self._page = None

    async def __aenter__(self):
        await browser_manager.lane_lock(self.lane).acquire()
        browser_manager.set_lane_busy(self.lane, True)
        self._page = await browser_manager.get_page(self.lane)
        return self._page

    async def __aexit__(self, exc_type, exc, tb):
        browser_manager.set_lane_busy(self.lane, False)
        browser_manager.record_activity()
        browser_manager.lane_lock(self.lane).release()
        return False


async def run_task(name: str, **kwargs) -> dict:
    """Run a Playwright task on its feature lane (Exchange / Manage Library / default).

    Lanes share one Hudl login but use separate tabs + locks, so Exchange and
    Manage Library can proceed in parallel without navigating each other away.
    """
    if name not in TASKS:
        raise ValueError(f"Unknown task: {name}. Available: {list(TASKS.keys())}")

    lane = task_lane(name)
    async with browser_manager.lane_lock(lane):
        browser_manager.set_lane_busy(lane, True)
        try:
            page = await browser_manager.get_page(lane)
            task_fn = TASKS[name]

            if name == "login":
                return await task_fn(
                    page,
                    force=kwargs.get("force", False),
                    credentials=kwargs.get("credentials"),
                )

            if name == "verify_credentials":
                creds = kwargs.get("credentials")
                if not creds:
                    raise ValueError("verify_credentials requires 'credentials'")
                return await login.verify_credentials(page, creds)

            if name == "run_search":
                query = kwargs.get("query", "")
                if not query:
                    raise ValueError("run_search requires 'query'")
                return await task_fn(page, query)

            if name == "select_exchange_type":
                return await task_fn(
                    page,
                    team_id=str(kwargs["team_id"]),
                    team_source=kwargs["team_source"],
                    exchange_type=kwargs["exchange_type"],
                    owner_team_id=kwargs.get("owner_team_id"),
                )

            if name == "select_videos":
                return await task_fn(page, video_indices=kwargs["video_indices"])

            if name == "select_playlists":
                return await task_fn(
                    page, playlist_indices=kwargs.get("playlist_indices")
                )

            if name == "select_stats":
                return await task_fn(
                    page,
                    include_stats=kwargs["include_stats"],
                    include_team_stats=kwargs.get("include_team_stats", True),
                    include_player_stats=kwargs.get("include_player_stats", True),
                )

            if name == "add_notes":
                return await task_fn(page, message=kwargs["message"])

            if name == "select_files":
                return await task_fn(
                    page,
                    team_index=kwargs.get("team_index"),
                    file_path=kwargs.get("file_path"),
                )

            if name == "delete_uploaded_file":
                return await task_fn(page, file_index=kwargs["file_index"])

            if name == "fill_video_details":
                return await task_fn(
                    page,
                    schedule_event_index=kwargs.get("schedule_event_index"),
                    video_type=kwargs.get("video_type", "Game"),
                    title=kwargs.get("title"),
                    check_event=kwargs.get("check_event", False),
                )

            if name == "cancel_exchange":
                return await task_fn(page, step_index=kwargs["step_index"])

            if name == "go_back_exchange":
                return await task_fn(page, back_index=kwargs["back_index"])

            if name == "get_active_exchange_details":
                return await task_fn(
                    page,
                    exchange_name=kwargs["exchange_name"],
                    exchange_index=kwargs.get("exchange_index"),
                    exchange_id=kwargs.get("exchange_id"),
                    href=kwargs.get("href"),
                    team_id=kwargs.get("team_id"),
                )

            if name == "click_active_exchange_button":
                return await task_fn(
                    page,
                    action_type=kwargs["action_type"],
                    exchange_name=kwargs["exchange_name"],
                    exchange_index=kwargs.get("exchange_index"),
                    exchange_id=kwargs.get("exchange_id"),
                    href=kwargs.get("href"),
                )

            if name == "get_video_stream_url":
                return await task_fn(page, watch_url=kwargs["watch_url"])

            if name in (
                "open_library_details",
                "get_library_event_options",
                "download_library_video",
                "delete_library_video",
            ):
                return await task_fn(page, video_index=kwargs["video_index"])

            if name == "download_library_video_by_ref":
                return await task_fn(
                    page,
                    video_index=kwargs.get("video_index"),
                    v=kwargs.get("v"),
                )

            if name == "update_library_type":
                return await task_fn(
                    page,
                    video_index=kwargs["video_index"],
                    video_type=kwargs["video_type"],
                )

            if name == "update_library_event":
                return await task_fn(
                    page,
                    video_index=kwargs["video_index"],
                    event_name=kwargs["event_name"],
                )

            if name == "rename_library_video":
                return await task_fn(
                    page,
                    video_index=kwargs["video_index"],
                    new_name=kwargs.get("new_name"),
                    cancel=kwargs.get("cancel", False),
                )

            if name == "email_download_link":
                return await task_fn(
                    page,
                    video_index=kwargs["video_index"],
                    option=kwargs.get("option", "video_and_stats"),
                    cancel=kwargs.get("cancel", False),
                )

            if name == "get_manage_library":
                return await task_fn(page, team_id=kwargs.get("team_id"))

            if name == "expand_manage_library_season":
                return await task_fn(
                    page,
                    team_id=kwargs.get("team_id"),
                    season_label=kwargs.get("season_label", ""),
                )

            if name == "expand_manage_library_folder":
                return await task_fn(
                    page,
                    team_id=kwargs.get("team_id"),
                    season_label=kwargs.get("season_label", ""),
                    folder_path=kwargs.get("folder_path") or [],
                )

            if name == "download_manage_library_items":
                return await task_fn(
                    page,
                    team_id=kwargs.get("team_id"),
                    season_label=kwargs.get("season_label", ""),
                    items=kwargs.get("items") or [],
                    download_format=kwargs.get("download_format", "multiple"),
                    include_breakdown=kwargs.get("include_breakdown", True),
                )

            if name == "set_manage_library_clip_selection":
                return await task_fn(
                    page,
                    team_id=kwargs.get("team_id"),
                    season_label=kwargs.get("season_label", ""),
                    path=kwargs.get("path") or [],
                    label=kwargs.get("label", ""),
                    selected=kwargs.get("selected", True),
                )

            if name == "get_manage_library_clip_meta":
                return await task_fn(
                    page,
                    team_id=kwargs.get("team_id"),
                    season_label=kwargs.get("season_label", ""),
                    folder_path=kwargs.get("folder_path") or [],
                    label=kwargs.get("label", ""),
                )

            if name == "switch_hudl_team_by_name":
                return await task_fn(
                    page,
                    team_name=kwargs.get("team_name", ""),
                    org_name=kwargs.get("org_name"),
                    team_id=kwargs.get("team_id"),
                )

            if name == "list_hudl_organizations":
                return await task_fn(page)

            if name == "open_exchange":
                return await task_fn(page, team_id=kwargs.get("team_id"))

            if name == "get_exchange_data":
                return await task_fn(page, team_id=kwargs.get("team_id"))

            if name == "get_library_videos":
                return await task_fn(page, team_id=kwargs.get("team_id"))

            if name == "get_active_exchanges":
                return await task_fn(
                    page,
                    team_id=kwargs.get("team_id"),
                    full_scroll=kwargs.get("full_scroll", False),
                )

            return await task_fn(page)
        finally:
            browser_manager.set_lane_busy(lane, False)
            browser_manager.record_activity()
