// ─────────────────────────────────────────────────────────────────────────────
// Blocked file-extension lists & helpers
//
// Defines a comprehensive set of code / executable extensions that are NOT
// allowed to be uploaded through the CRM's file-attachment feature.
// Provides utilities to check individual filenames or filter whole arrays.
// ─────────────────────────────────────────────────────────────────────────────

/**
 * Set of file extensions considered dangerous or executable.
 *
 * Covers scripting languages, compiled binaries, OS-specific executables,
 * smart-contract sources, database scripts, and more.
 */
export const BLOCKED_CODE_EXTENSIONS = new Set([
  // Python & data-science notebooks
  "py", "pyc", "pyo", "pyw", "pyx", "ipynb",
  // JavaScript / TypeScript ecosystem
  "js", "mjs", "cjs", "jsx", "ts", "tsx",
  // PHP
  "php", "phtml", "php3", "php4", "php5",
  // Ruby
  "rb", "erb",
  // Perl
  "pl", "pm",
  // Lua
  "lua",
  // Shell (Unix / Linux / macOS)
  "sh", "bash", "zsh", "ksh", "fish",
  // PowerShell (Windows)
  "ps1", "psm1", "psd1",
  // Batch / Command (Windows)
  "bat", "cmd",
  // VBScript
  "vbs",
  // AppleScript
  "applescript",
  // AutoHotkey
  "ahk",
  // AutoIt
  "au3",
  // Tcl
  "tcl",
  // C / C++
  "c", "h", "cpp", "cc", "cxx", "hpp", "hh", "hxx",
  // C# / Visual Basic (.NET)
  "cs", "vb",
  // Java
  "java", "class", "jar",
  // Go
  "go",
  // Rust
  "rs",
  // Swift
  "swift",
  // Kotlin
  "kt", "kts",
  // Scala
  "scala",
  // Groovy / Gradle
  "groovy", "gradle",
  // D
  "d",
  // Nim
  "nim",
  // Crystal
  "cr",
  // Zig
  "zig",
  // V
  "v",
  // VHDL
  "vhd", "vhdl",
  // Assembly
  "asm", "s",
  // Fortran
  "f", "f90", "f95", "for",
  // Pascal
  "pas", "pp",
  // Ada
  "ada", "adb", "ads",
  // COBOL
  "cob", "cbl",
  // Haskell
  "hs", "lhs",
  // OCaml
  "ml", "mli",
  // F#
  "fs", "fsx", "fsi",
  // Clojure
  "clj", "cljs", "cljc", "edn",
  // Lisp / Scheme
  "lisp", "lsp",
  "scm", "ss",
  "rkt",
  // Elixir
  "ex", "exs",
  // Erlang
  "erl", "hrl",
  // Julia
  "jl",
  // Elm
  "elm",
  // PureScript
  "purs",
  // Reason / ReScript
  "re", "rei",
  // Solidity (Ethereum smart contracts)
  "sol",
  // Move (Sui / Aptos smart contracts)
  "move",
  // Prolog
  "pro",
  // Objective-C
  "m",
  // Web markup
  "html", "htm",
  // Stylesheets
  "css", "scss", "sass", "less",
  // Front-end frameworks
  "vue", "svelte",
  "json5",
  // Compiled / binary
  "o", "so", "dll", "exe", "dylib",
  // WebAssembly
  "wasm", "wat", "bin",
  "out",
  // Package formats
  "deb", "rpm",
  // Mobile apps
  "app", "apk", "ipa",
  // SQL / database scripts
  "sql", "psql",
  // Arduino
  "ino", "pde",
  // SAS / Stata
  "sas", "do",
])

// ── Extension extraction ─────────────────────────────────────────────────────

/**
 * Extract every extension from a dot-separated filename.
 *
 * `"archive.tar.gz"` → `["tar", "gz"]`
 * `"notes.txt"`      → `["txt"]`
 * `"Makefile"`       → `[]`
 *
 * @param name - Filename (may include path segments before the final dot).
 * @returns    Lowercased extension list, without the dots.
 */
export function getAllExtensions(name: string): string[] {
  const parts = name.split(".")
  if (parts.length <= 1) return []
  return parts.slice(1).map((ext) => ext.toLowerCase())
}

// ── Block checks ─────────────────────────────────────────────────────────────

/**
 * Determine whether a filename has a blocked (dangerous) extension.
 *
 * Checks every segment after the first dot; if **any** matches a blocked
 * extension, the file is considered blocked.
 *
 * @param name - Filename to inspect.
 * @returns    `true` if at least one extension is in the blocked set.
 */
export function hasBlockedCodeExtension(name: string): boolean {
  const exts = getAllExtensions(name)
  return exts.some((ext) => BLOCKED_CODE_EXTENSIONS.has(ext))
}

/**
 * Partition an array of `{ name }` objects into allowed and rejected subsets
 * based on `hasBlockedCodeExtension`.
 *
 * @param files - Array of objects that have a `name` string property.
 * @returns     `{ allowed, rejected }` — both are sub-arrays of the input.
 */
export function filterBlockedFiles<T extends { name: string }>(
  files: T[],
): { allowed: T[]; rejected: T[] } {
  const allowed: T[] = []
  const rejected: T[] = []
  for (const f of files) {
    if (hasBlockedCodeExtension(f.name)) {
      rejected.push(f)
    } else {
      allowed.push(f)
    }
  }
  return { allowed, rejected }
}
