from __future__ import annotations

from pathlib import Path
from typing import Any, Dict, Optional, Sequence
from urllib.parse import unquote, urlparse


def normalize_file_extension(ext_value: Any) -> str:
    ext = str(ext_value or "").strip().lstrip(".")
    for sep in (" ", "|", "(", "[", "{", ",", ";"):
        if sep in ext:
            ext = ext.split(sep, 1)[0]
            break
    if "." in ext:
        ext = ext.split(".")[-1]
    ext = "".join(ch for ch in ext if ch.isalnum())
    return ext[:5]


def extract_title_tag_value(tags: Sequence[str]) -> Optional[str]:
    for tag in tags:
        text = str(tag or "").strip()
        if text.lower().startswith("title:"):
            value = text.split(":", 1)[1].strip()
            if value:
                return value
    return None


def _derive_title(
    title: Optional[str],
    fallback_title: Optional[str],
    path: Optional[str],
    url: Any,
    hash_value: Optional[str],
) -> str:
    for candidate in (title, fallback_title):
        text = str(candidate or "").strip()
        if text:
            return text

    path_text = str(path or "").strip()
    if path_text:
        try:
            return Path(path_text).stem or path_text
        except Exception:
            return path_text

    if isinstance(url, str):
        try:
            parsed = urlparse(url)
            name = Path(unquote(parsed.path)).stem
            if name:
                return name
        except Exception:
            pass
        text = url.strip()
        if text:
            return text

    if isinstance(url, list):
        for candidate in url:
            text = str(candidate or "").strip()
            if text:
                return text

    return str(hash_value or "").strip()


def build_file_result_payload(
    *,
    title: Optional[str] = None,
    fallback_title: Optional[str] = None,
    path: Optional[str] = None,
    url: Any = None,
    hash_value: Optional[str] = None,
    store: Optional[str] = None,
    tag: Optional[Sequence[str]] = None,
    ext: Any = None,
    size_bytes: Optional[int] = None,
    columns: Optional[Sequence[tuple[str, Any]]] = None,
    source: Optional[str] = None,
    table: Optional[str] = None,
    detail: Optional[str] = None,
    **extra: Any,
) -> Dict[str, Any]:
    resolved_title = _derive_title(title, fallback_title, path, url, hash_value)
    resolved_path = str(path).strip() if path is not None and str(path).strip() else None
    resolved_store = str(store).strip() if store is not None and str(store).strip() else None
    resolved_ext = normalize_file_extension(ext)
    if not resolved_ext:
        for candidate in (resolved_path, resolved_title):
            text = str(candidate or "").strip()
            if not text:
                continue
            try:
                resolved_ext = normalize_file_extension(Path(text).suffix)
            except Exception:
                resolved_ext = ""
            if resolved_ext:
                break

    payload: Dict[str, Any] = {"title": resolved_title}

    if resolved_path is not None:
        payload["path"] = resolved_path
    if hash_value:
        payload["hash"] = str(hash_value)
    if url not in (None, "", []):
        payload["url"] = url
    if resolved_store is not None:
        payload["store"] = resolved_store
    if tag is not None:
        payload["tag"] = list(tag)
    if resolved_ext:
        payload["ext"] = resolved_ext
    if size_bytes is not None:
        payload["size_bytes"] = size_bytes
    if columns is not None:
        payload["columns"] = list(columns)
    if source:
        payload["source"] = source
    if table:
        payload["table"] = table
    if detail is not None:
        payload["detail"] = str(detail)

    payload.update(extra)
    return payload


def build_table_result_payload(
    *,
    columns: Sequence[tuple[str, Any]],
    title: Optional[str] = None,
    table: Optional[str] = None,
    detail: Optional[str] = None,
    selection_args: Optional[Sequence[Any]] = None,
    selection_action: Optional[Sequence[Any]] = None,
    **extra: Any,
) -> Dict[str, Any]:
    payload: Dict[str, Any] = {
        "columns": [(str(label), value) for label, value in columns],
    }

    if title is not None:
        payload["title"] = str(title)
    if table:
        payload["table"] = table
    if detail is not None:
        payload["detail"] = str(detail)
    if selection_args:
        payload["_selection_args"] = [str(arg) for arg in selection_args if arg is not None]
    if selection_action:
        payload["_selection_action"] = [str(arg) for arg in selection_action if arg is not None]

    payload.update(extra)
    return payload