from __future__ import annotations

from backend.constants import CloudConnections
from backend.utils.utils import get_doc_name

CONNECTION_FOLDER_SOURCE = "connection_folder"
SHAREPOINT_PATH_TYPE_FOLDER = "folder"
SHAREPOINT_PATH_TYPE_FILE = "file"


def is_connection_folder_doc(doc: dict) -> bool:
    if not isinstance(doc, dict):
        return False
    return doc.get("source") == CONNECTION_FOLDER_SOURCE


def is_local_doc(doc: dict) -> bool:
    return isinstance(doc, str) or (isinstance(doc, dict) and not is_connection_folder_doc(doc))


def is_delete_pending(doc) -> bool:
    return isinstance(doc, dict) and bool(doc.get("deletePending"))


def doc_name_equals(doc, filename: str) -> bool:
    name = get_doc_name(doc)
    return bool(name) and name.lower() == filename.lower()


def is_sharepoint_doc(doc: dict) -> bool:
    return isinstance(doc, dict) and doc.get("connectionType") == CloudConnections.SHAREPOINT_ONLINE.value


def is_sharepoint_file_doc(doc: dict) -> bool:
    return is_sharepoint_doc(doc) and doc.get("pathType") == SHAREPOINT_PATH_TYPE_FILE


def sharepoint_doc_source_folder_id(doc: dict) -> str | None:
    if is_sharepoint_file_doc(doc):
        return doc.get("sourceFolderId")
    return doc.get("folderId")


def sharepoint_doc_source_path(doc: dict) -> str | None:
    if is_sharepoint_file_doc(doc):
        return doc.get("sourceFolderPath") or _sharepoint_source_folder_path(doc.get("path") or doc.get("name") or "/")
    return doc.get("path") or doc.get("name")


def sharepoint_doc_replacement_key(doc: dict) -> str:
    if not is_sharepoint_doc(doc):
        return ""
    if is_sharepoint_file_doc(doc):
        return f"file:{sharepoint_doc_source_folder_id(doc) or ''}:{doc.get('path') or doc.get('name') or ''}"
    return str(doc.get("folderId") or doc.get("name") or "")


def with_sharepoint_source_folder_id(doc: dict, folder_id: str) -> dict:
    if is_sharepoint_file_doc(doc):
        return {**doc, "sourceFolderId": folder_id, "folderId": None}
    return {**doc, "folderId": folder_id}


def _normalize_sharepoint_path(raw_path: str, path_type: str) -> str:
    path = raw_path.strip() or "/"
    if not path.startswith("/"):
        path = f"/{path}"
    if path_type == SHAREPOINT_PATH_TYPE_FOLDER and path != "/" and not path.endswith("/"):
        path = f"{path}/"
    if path_type == SHAREPOINT_PATH_TYPE_FILE and path != "/":
        path = path.rstrip("/")
    return path


def _sharepoint_source_folder_path(path: str) -> str:
    normalized = _normalize_sharepoint_path(path, SHAREPOINT_PATH_TYPE_FILE)
    if normalized == "/":
        return "/"
    parent = normalized.rsplit("/", 1)[0] or "/"
    return _normalize_sharepoint_path(parent, SHAREPOINT_PATH_TYPE_FOLDER)


def _sharepoint_relative_file_path(path: str) -> str:
    normalized = _normalize_sharepoint_path(path, SHAREPOINT_PATH_TYPE_FILE)
    if normalized == "/":
        return "/"
    name = normalized.rsplit("/", 1)[-1]
    return f"/{name}" if name else "/"


def normalize_sharepoint_items(raw_items: list) -> list[dict]:
    selected_items = []
    seen = set()
    for item in raw_items:
        if not isinstance(item, dict):
            continue

        raw_path = item.get("path")
        if not isinstance(raw_path, str):
            continue

        item_type = str(item.get("type") or "").lower()
        is_directory = bool(item.get("directory", item_type != SHAREPOINT_PATH_TYPE_FILE))
        path_type = SHAREPOINT_PATH_TYPE_FOLDER if is_directory else SHAREPOINT_PATH_TYPE_FILE
        path = _normalize_sharepoint_path(raw_path, path_type)
        key = (path_type, path)
        if key in seen:
            continue
        seen.add(key)
        selected_items.append(
            {
                "path": path,
                "pathType": path_type,
                "sourcePath": _sharepoint_source_folder_path(path) if path_type == SHAREPOINT_PATH_TYPE_FILE else path,
                "relativePath": (
                    _sharepoint_relative_file_path(path) if path_type == SHAREPOINT_PATH_TYPE_FILE else None
                ),
            }
        )

    return selected_items


def make_sharepoint_doc_entry(
    folder_id: str | None,
    connection: str,
    site: str,
    drive: str,
    site_id: str,
    drive_id: str,
    path: str,
    size: int,
    path_type: str = SHAREPOINT_PATH_TYPE_FOLDER,
    source_folder_id: str | None = None,
    source_folder_path: str | None = None,
    relative_path: str | None = None,
) -> dict:
    doc = {
        "connectionType": CloudConnections.SHAREPOINT_ONLINE.value,
        "connection": connection,
        "name": path,
        "site": site,
        "drive": drive,
        "path": path,
        "pathType": path_type,
        "siteId": site_id,
        "driveId": drive_id,
        "folderId": folder_id,
        "size": size,
        "active": False,
        "source": CONNECTION_FOLDER_SOURCE,
        "kbId": None,
        "imgsFolderId": None,
        "recipeId": None,
    }
    if path_type == SHAREPOINT_PATH_TYPE_FILE:
        doc["sourceFolderId"] = source_folder_id
        doc["sourceFolderPath"] = source_folder_path
        doc["relativePath"] = relative_path
    return doc
