from __future__ import annotations

from mcp.server.fastmcp import FastMCP

from .backend_client import BackendClient
from .config import DEFAULT_PROFILE
from .session_store import SessionStore
from .tools.app_tools import AppTools
from .tools.auth_tools import AuthTools
from .tools.file_tools import FileTools
from .tools.navigation_tools import NavigationTools
from .tools.package_tools import PackageTools
from .tools.portal_tools import PortalTools
from .tools.solution_tools import SolutionTools
from .tools.workspace_tools import WorkspaceTools


def build_builder_server() -> FastMCP:
    server = FastMCP(
        "Qingflow App Builder MCP",
        instructions=(
            "Use this server for high-level Qingflow builder workflows. "
            "Call solution_schema_example before generating non-trivial builder payloads. "
            "Prefer solution_build_app for package/entity/field/layout design, then solution_build_flow for workflow, "
            "then solution_build_views, solution_build_analytics_portal, and solution_build_navigation. "
            "Avoid handcrafting low-level workflow/view/report payloads."
        ),
    )
    sessions = SessionStore()
    backend = BackendClient()
    auth = AuthTools(sessions, backend)
    workspace = WorkspaceTools(sessions, backend)
    files = FileTools(sessions, backend)
    apps = AppTools(sessions, backend)
    packages = PackageTools(sessions, backend)
    portals = PortalTools(sessions, backend)
    navigation = NavigationTools(sessions, backend)
    solution = SolutionTools(sessions, backend)

    @server.tool()
    def auth_login(
        profile: str = DEFAULT_PROFILE,
        base_url: str | None = None,
        qf_version: str | None = None,
        email: str = "",
        password: str = "",
        persist: bool = True,
    ) -> dict:
        return auth.auth_login(
            profile=profile,
            base_url=base_url,
            qf_version=qf_version,
            email=email,
            password=password,
            persist=persist,
        )

    @server.tool()
    def auth_use_token(
        profile: str = DEFAULT_PROFILE,
        base_url: str | None = None,
        qf_version: str | None = None,
        token: str = "",
        ws_id: int | None = None,
        persist: bool = False,
    ) -> dict:
        return auth.auth_use_token(
            profile=profile,
            base_url=base_url,
            qf_version=qf_version,
            token=token,
            ws_id=ws_id,
            persist=persist,
        )

    @server.tool()
    def auth_whoami(profile: str = DEFAULT_PROFILE) -> dict:
        return auth.auth_whoami(profile=profile)

    @server.tool()
    def auth_logout(profile: str = DEFAULT_PROFILE, forget_persisted: bool = False) -> dict:
        return auth.auth_logout(profile=profile, forget_persisted=forget_persisted)

    @server.tool()
    def workspace_list(
        profile: str = DEFAULT_PROFILE,
        page_num: int = 1,
        page_size: int = 20,
        include_external: bool = False,
    ) -> dict:
        return workspace.workspace_list(
            profile=profile,
            page_num=page_num,
            page_size=page_size,
            include_external=include_external,
        )

    @server.tool()
    def workspace_select(profile: str = DEFAULT_PROFILE, ws_id: int = 0) -> dict:
        return workspace.workspace_select(profile=profile, ws_id=ws_id)

    @server.tool()
    def file_upload_local(
        profile: str = DEFAULT_PROFILE,
        upload_kind: str = "attachment",
        file_path: str = "",
        upload_mark: str | None = None,
        content_type: str | None = None,
        bucket_type: str | None = None,
        path_id: int | None = None,
        file_related_url: str | None = None,
    ) -> dict:
        return files.file_upload_local(
            profile=profile,
            upload_kind=upload_kind,
            file_path=file_path,
            upload_mark=upload_mark,
            content_type=content_type,
            bucket_type=bucket_type,
            path_id=path_id,
            file_related_url=file_related_url,
        )

    @server.tool()
    def app_list(profile: str = DEFAULT_PROFILE, ship_auth: bool = False) -> dict:
        return apps.app_list(profile=profile, ship_auth=ship_auth)

    @server.tool()
    def app_search(profile: str = DEFAULT_PROFILE, keyword: str = "", page_num: int = 1, page_size: int = 50) -> dict:
        return apps.app_search(profile=profile, keyword=keyword, page_num=page_num, page_size=page_size)

    @server.tool()
    def app_get_base(profile: str = DEFAULT_PROFILE, app_key: str = "", include_raw: bool = False) -> dict:
        return apps.app_get_base(profile=profile, app_key=app_key, include_raw=include_raw)

    @server.tool()
    def app_get_form_schema(
        profile: str = DEFAULT_PROFILE,
        app_key: str = "",
        form_type: int = 1,
        being_draft: bool | None = None,
        being_apply: bool | None = None,
        audit_node_id: int | None = None,
        include_raw: bool = False,
    ) -> dict:
        return apps.app_get_form_schema(
            profile=profile,
            app_key=app_key,
            form_type=form_type,
            being_draft=being_draft,
            being_apply=being_apply,
            audit_node_id=audit_node_id,
            include_raw=include_raw,
        )

    @server.tool()
    def app_create(profile: str = DEFAULT_PROFILE, payload: dict | None = None) -> dict:
        return apps.app_create(profile=profile, payload=payload or {})

    @server.tool()
    def app_publish(profile: str = DEFAULT_PROFILE, app_key: str = "", payload: dict | None = None) -> dict:
        return apps.app_publish(profile=profile, app_key=app_key, payload=payload or {})

    @server.tool()
    def package_list(profile: str = DEFAULT_PROFILE, trial_status: str = "all") -> dict:
        return packages.package_list(profile=profile, trial_status=trial_status)

    @server.tool()
    def package_get(profile: str = DEFAULT_PROFILE, tag_id: int = 0) -> dict:
        return packages.package_get(profile=profile, tag_id=tag_id)

    @server.tool()
    def portal_list(profile: str = DEFAULT_PROFILE) -> dict:
        return portals.portal_list(profile=profile)

    @server.tool()
    def portal_get(profile: str = DEFAULT_PROFILE, dash_key: str = "", being_draft: bool = False) -> dict:
        return portals.portal_get(profile=profile, dash_key=dash_key, being_draft=being_draft)

    @server.tool()
    def navigation_list_published(profile: str = DEFAULT_PROFILE, page_num: int = 1, page_size: int = 50) -> dict:
        return navigation.navigation_list_published(profile=profile, page_num=page_num, page_size=page_size)

    @server.tool()
    def navigation_list_draft_all(profile: str = DEFAULT_PROFILE, query_key: str | None = None) -> dict:
        return navigation.navigation_list_draft_all(profile=profile, query_key=query_key)

    @server.tool()
    def navigation_get_status(profile: str = DEFAULT_PROFILE) -> dict:
        return navigation.navigation_get_status(profile=profile)

    @server.tool()
    def solution_design_session(
        action: str = "get",
        session_id: str = "",
        stage: str | None = None,
        design_patch: dict | None = None,
        metadata: dict | None = None,
    ) -> dict:
        return solution.solution_design_session(
            action=action,
            session_id=session_id,
            stage=stage,
            design_patch=design_patch or {},
            metadata=metadata or {},
        )

    @server.tool()
    def solution_schema_example(stage: str = "app", intent: str = "minimal") -> dict:
        return solution.solution_schema_example(stage=stage, intent=intent)

    @server.tool()
    def solution_build_all(
        profile: str = DEFAULT_PROFILE,
        mode: str = "plan",
        build_id: str = "",
        solution_spec: dict | None = None,
        publish: bool = True,
        run_label: str | None = None,
        target: dict | None = None,
        repair_patch: dict | None = None,
        verify: bool = False,
    ) -> dict:
        return solution.solution_build_all(
            profile=profile,
            mode=mode,
            build_id=build_id,
            solution_spec=solution_spec or {},
            publish=publish,
            run_label=run_label,
            target=target or {},
            repair_patch=repair_patch or {},
            verify=verify,
        )

    @server.tool()
    def solution_build_app(
        profile: str = DEFAULT_PROFILE,
        mode: str = "plan",
        build_id: str = "",
        app_spec: dict | None = None,
        publish: bool = True,
        run_label: str | None = None,
        target: dict | None = None,
        repair_patch: dict | None = None,
    ) -> dict:
        return solution.solution_build_app(
            profile=profile,
            mode=mode,
            build_id=build_id,
            app_spec=app_spec or {},
            publish=publish,
            run_label=run_label,
            target=target or {},
            repair_patch=repair_patch or {},
        )

    @server.tool()
    def solution_build_flow(
        profile: str = DEFAULT_PROFILE,
        mode: str = "plan",
        build_id: str = "",
        flow_spec: dict | None = None,
        publish: bool = True,
        run_label: str | None = None,
        repair_patch: dict | None = None,
    ) -> dict:
        return solution.solution_build_flow(
            profile=profile,
            mode=mode,
            build_id=build_id,
            flow_spec=flow_spec or {},
            publish=publish,
            run_label=run_label,
            repair_patch=repair_patch or {},
        )

    @server.tool()
    def solution_build_views(
        profile: str = DEFAULT_PROFILE,
        mode: str = "plan",
        build_id: str = "",
        views_spec: dict | None = None,
        publish: bool = True,
        run_label: str | None = None,
        repair_patch: dict | None = None,
    ) -> dict:
        return solution.solution_build_views(
            profile=profile,
            mode=mode,
            build_id=build_id,
            views_spec=views_spec or {},
            publish=publish,
            run_label=run_label,
            repair_patch=repair_patch or {},
        )

    @server.tool()
    def solution_build_analytics_portal(
        profile: str = DEFAULT_PROFILE,
        mode: str = "plan",
        build_id: str = "",
        analytics_portal_spec: dict | None = None,
        publish: bool = True,
        run_label: str | None = None,
        repair_patch: dict | None = None,
    ) -> dict:
        return solution.solution_build_analytics_portal(
            profile=profile,
            mode=mode,
            build_id=build_id,
            analytics_portal_spec=analytics_portal_spec or {},
            publish=publish,
            run_label=run_label,
            repair_patch=repair_patch or {},
        )

    @server.tool()
    def solution_build_navigation(
        profile: str = DEFAULT_PROFILE,
        mode: str = "plan",
        build_id: str = "",
        navigation_spec: dict | None = None,
        publish: bool = True,
        run_label: str | None = None,
        repair_patch: dict | None = None,
    ) -> dict:
        return solution.solution_build_navigation(
            profile=profile,
            mode=mode,
            build_id=build_id,
            navigation_spec=navigation_spec or {},
            publish=publish,
            run_label=run_label,
            repair_patch=repair_patch or {},
        )

    @server.tool()
    def solution_build_status(build_id: str = "") -> dict:
        return solution.solution_build_status(build_id=build_id)
    return server


mcp = build_builder_server()


def main() -> None:
    mcp.run()


if __name__ == "__main__":
    main()
