import json
import os
from typing import List, Any

import yaml
from playwright.sync_api import BrowserContext as BrowserExtensionSync, Worker
from .model import TResponse, TCommand, _JS_CODE, StateCommand, StateResponse, Response, AnalyzePageResponse


def execute_on_extension_sync(
        browser_context: BrowserExtensionSync, js_code: str, command: dict[str, Any]
) -> dict[str, Any]:
    """
    Evaluates the specified javascript code in the extension context, passing the `command` as a parameter of the evaluation, returning the response serialized as `dict`.
    """

    def _ensure_worker() -> Worker:
        if len(browser_context.service_workers) == 0:
            return browser_context.wait_for_event("serviceworker")
        else:
            return browser_context.service_workers[0]

    worker = _ensure_worker()
    response = worker.evaluate(js_code, json.dumps(command))
    json_data = json.loads(response)
    return json_data


def execute_command_sync(
        browser_context: BrowserExtensionSync, command: TCommand, responseType: type[TResponse]
) -> TResponse:
    json_data = execute_on_extension_sync(browser_context, js_code=_JS_CODE, command=command.model_dump())
    command_response = Response[responseType](**json_data)
    return command_response.data


def analyze_current_page_sync(browser_context: BrowserExtensionSync,
                              ) -> AnalyzePageResponse:
    current_dir = os.path.dirname(os.path.abspath(__file__))
    rules = yaml.safe_load(open(os.path.join(current_dir, 'rules.yaml')))
    response = execute_command_sync(browser_context, StateCommand(timeout=10, rules=rules),
                                    StateResponse)
    out_map = {}
    for _, obj in response.pageAnalysis.map.items():
        if 'bid' not in obj.html.attributes.keys():
            pass
            # print("Warning: Pu Mapping for an element failed since bid wasn't found on its attribues")
        else:
            out_map[obj.html.attributes['bid']] = obj
    response.pageAnalysis.map = out_map
    return response.pageAnalysis
