from __future__ import annotations

import os
from pathlib import Path
from typing import Optional

from .._http import HttpClient
from ..models.workspace import WorkspaceFile, FileContent

TEXT_VIEWABLE_EXTENSIONS = frozenset({
    ".txt", ".pdb", ".cif", ".csv", ".tsv", ".log", ".py", ".json",
    ".yaml", ".yml", ".toml", ".cfg", ".ini", ".xml", ".html", ".htm",
    ".css", ".js", ".ts", ".md", ".rst", ".sh", ".bash", ".zsh",
    ".bat", ".r", ".rmd", ".sdf", ".mol", ".mol2", ".smiles", ".smi",
    ".fasta", ".fa", ".fastq", ".gff", ".gtf", ".bed", ".sam",
    ".vcf", ".pqr", ".ent", ".seq", ".aln", ".out", ".err",
    ".tex", ".bib", ".env", ".dockerfile", ".makefile",
})


def is_text_viewable(file_path: str) -> bool:
    ext = os.path.splitext(file_path)[1].lower()
    name = os.path.basename(file_path).lower()
    # Files without extension (Makefile, Dockerfile, etc.)
    if not ext and name in ("makefile", "dockerfile", "readme", "license", "changelog"):
        return True
    return ext in TEXT_VIEWABLE_EXTENSIONS


class Workspace:
    """Scoped workspace helper for a specific project + chat.

    Usage:
        ws = client.rosalind.workspace(project="Default", chat_name="run-1")
        ws.list_folders()
        ws.list_files(folder="scripts")
        ws.get_file_content(file_path="scripts/main.py")
    """

    def __init__(self, http: HttpClient, project: str, chat_name: str):
        self._http = http
        self._project = project
        self._chat_name = chat_name
        self._base = f"/rosalind/chat/{project}/{chat_name}"

    def list_folders(self) -> list[str]:
        data = self._http.get(f"{self._base}/archive/files")
        raw_files = data.get("files", [])
        folders: set[str] = set()
        for f in raw_files:
            loc = f.get("location", f.get("file_location", ""))
            parts = loc.split("/")
            if len(parts) > 1:
                folders.add(parts[0])
        return sorted(folders)

    def list_files(self, folder: Optional[str] = None) -> list[WorkspaceFile]:
        data = self._http.get(f"{self._base}/archive/files")
        raw_files = data.get("files", [])
        result = []
        for f in raw_files:
            wf = WorkspaceFile.from_dict(f)
            if folder is None or wf.location.startswith(folder + "/") or wf.folder == folder:
                result.append(wf)
        return result

    def get_file_content(
        self,
        file_path: str,
        include_images: bool = True,
    ) -> FileContent:
        data = self._http.get(
            f"{self._base}/file/content",
            params={"file_location": file_path, "include_images": include_images},
        )
        return FileContent.from_dict(data)

    def download_file_content(self, file_path: str, save_as: str) -> Path:
        response = self._http.get_raw(
            f"{self._base}/archive/file",
            params={"file_location": file_path},
        )
        dest = Path(save_as)
        dest.parent.mkdir(parents=True, exist_ok=True)
        dest.write_bytes(response.content)
        return dest
