"""Sharepoint service used for creating new list items."""

import asyncio

from azure.identity.aio import CertificateCredential
from msgraph import GraphServiceClient
from msgraph.generated.models.field_value_set import FieldValueSet
from msgraph.generated.models.list_item import ListItem
from msgraph.generated.models.list_item_collection_response import ListItemCollectionResponse
from msgraph.generated.models.site import Site
from msgraph.generated.sites.item.lists.item.items.items_request_builder import ItemsRequestBuilder

from gso.settings import load_oss_params


class SharePointClient:
    """A client for interaction with SharePoint lists."""

    def __init__(self) -> None:
        """Initialise a new SharePoint client."""
        sp_params = load_oss_params().SHAREPOINT
        _credentials = CertificateCredential(
            tenant_id=sp_params.tenant_id,
            client_id=sp_params.client_id,
            certificate_path=sp_params.certificate_path,
            password=sp_params.certificate_password,
        )
        self.client = GraphServiceClient(_credentials, sp_params.scopes)
        self.site_id = sp_params.site_id
        self.list_ids = sp_params.list_ids

    def get_site(self) -> Site | None:
        """Get the SharePoint site that this orchestrator connects to."""

        async def _get_site() -> Site | None:
            return await self.client.sites.by_site_id(self.site_id).get()

        return asyncio.run(_get_site())

    def get_list_items(self, list_name: str) -> ListItemCollectionResponse | None:
        """Get list items from a given list in SharePoint.

        Args:
            list_name: The name of the list.
        """

        async def _get_list_items() -> ListItemCollectionResponse | None:
            query_params = ItemsRequestBuilder.ItemsRequestBuilderGetQueryParameters(expand=["fields"])
            request_configuration = ItemsRequestBuilder.ItemsRequestBuilderGetRequestConfiguration(
                query_parameters=query_params
            )
            return (
                await self.client.sites.by_site_id(self.site_id)
                .lists.by_list_id(self.list_ids[list_name])
                .items.get(request_configuration=request_configuration)
            )

        return asyncio.run(_get_list_items())

    def add_list_item(self, list_name: str, fields: dict[str, str]) -> str:
        """Add a new entry to a SharePoint list.

        Args:
            list_name: The name of the list.
            fields: Any pre-filled fields in the list item. Can be left empty.

        Returns:
            The URL of the list in which a new item has been created.
        """

        async def _new_list_item() -> str:
            request_body = ListItem(fields=FieldValueSet(additional_data=fields))
            new_item = (
                await self.client.sites.by_site_id(self.site_id)
                .lists.by_list_id(self.list_ids[list_name])
                .items.post(request_body)
            )

            #  Strip the last part of the URL, since we want the link to the list, not the list item.
            return new_item.web_url.rsplit("/", 1)[0]

        return asyncio.run(_new_list_item())