use std::path::Path;

/// File language classification with binary detection and encoding-aware reading.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Language {
    C,
    Python,
    Java,
    Shell,
    Perl,
    JavaScript,
    Scala,
    Haskell,
    Pascal,
    Php,
    Patch,
    MsDos,
    PlainText,
    Binary,
    Unknown,
}

impl Language {
    pub fn is_source(&self) -> bool {
        matches!(
            self,
            Self::C
                | Self::Python
                | Self::Java
                | Self::Shell
                | Self::Perl
                | Self::JavaScript
                | Self::Scala
                | Self::Haskell
                | Self::Pascal
                | Self::Php
        )
    }

    pub fn is_text(&self) -> bool {
        !matches!(self, Self::Binary)
    }

    /// Classify a file by its extension.
    pub fn from_path(path: &Path) -> Self {
        let ext = path
            .extension()
            .and_then(|e| e.to_str())
            .unwrap_or("")
            .to_ascii_lowercase();

        match ext.as_str() {
            "c" | "cc" | "cpp" | "cxx" | "h" | "hh" | "hpp" | "hxx" => Self::C,
            "py" | "pyw" | "pyx" | "pxd" => Self::Python,
            "java" | "class" | "jar" | "jsp" => Self::Java,
            "sh" | "bash" | "zsh" | "csh" | "ksh" | "fish" => Self::Shell,
            "pl" | "pm" | "pod" | "t" => Self::Perl,
            "js" | "jsx" | "mjs" | "ts" | "tsx" => Self::JavaScript,
            "scala" | "sc" => Self::Scala,
            "hs" | "lhs" => Self::Haskell,
            "pas" | "pp" | "dpr" => Self::Pascal,
            "php" | "php3" | "php4" | "php5" | "phtml" => Self::Php,
            "patch" | "diff" => Self::Patch,
            "bat" | "cmd" | "ps1" => Self::MsDos,
            "txt" | "md" | "rst" | "adoc" | "cfg" | "conf" | "ini" | "yml" | "yaml"
            | "toml" | "json" | "xml" | "html" | "htm" | "css" | "csv" | "tsv" | "log"
            | "mk" | "cmake" | "makefile" | "dockerfile" | "proto" | "go" | "rs" | "rb"
            | "swift" | "kt" | "kts" | "r" | "m" | "mm" | "f" | "f90" | "f95" | "sql"
            | "lua" | "tcl" | "awk" | "sed" | "v" | "sv" | "vhd" | "vhdl" => Self::PlainText,
            "o" | "a" | "so" | "dylib" | "dll" | "exe" | "bin" | "elf" | "ko" | "obj"
            | "lib" | "pyc" | "pyo" | "wasm" => Self::Binary,
            _ => Self::Unknown,
        }
    }

    /// The pattern-database language key this maps to.
    pub fn as_pattern_key(&self) -> &'static str {
        match self {
            Self::C => "c",
            Self::Python => "python",
            Self::Java => "java",
            Self::Shell => "shell",
            Self::Perl => "perl",
            Self::JavaScript => "javascript",
            Self::Scala => "scala",
            Self::Haskell => "haskell",
            Self::Pascal => "pascal",
            Self::Php => "php",
            Self::Patch => "patch",
            Self::MsDos => "msdos",
            Self::PlainText => "all",
            Self::Binary => "binary",
            Self::Unknown => "all",
        }
    }
}
