import time

from mirage.accessor.sharepoint import SharePointAccessor
from mirage.cache.context import invalidate_after_write
from mirage.core.msgraph.drive_ops import (SIMPLE_UPLOAD_MAX,
                                           upload_session_write)
from mirage.core.sharepoint.client import graph_put_bytes, item_url, split_path
from mirage.core.sharepoint.resolve import resolve
from mirage.observe.context import record
from mirage.types import PathSpec
from mirage.utils.errors import enoent


async def write_bytes(accessor: SharePointAccessor, path: PathSpec,
                      data: bytes) -> None:
    virtual = path.virtual if isinstance(path, PathSpec) else path
    prefix, stripped = split_path(path)
    resolved = await resolve(accessor, path)
    if resolved.drive_id is None or resolved.item_path is None:
        raise enoent(virtual)
    config = accessor.config
    drive_id = resolved.drive_id
    item_p = resolved.item_path
    start_ms = int(time.monotonic() * 1000)
    if len(data) <= SIMPLE_UPLOAD_MAX:
        url = item_url(config, drive_id, item_p, action="/content")
        await graph_put_bytes(config, url, data)
    else:
        session_url = item_url(config,
                               drive_id,
                               item_p,
                               action="/createUploadSession")
        await upload_session_write(config, session_url, data)
    record("write", stripped, "sharepoint", len(data), start_ms)
    await invalidate_after_write(path)
