-- lx format
local format = require("core.format")
local quotes = require("core.quotes")

format.register({
	name = "PowerShell Script",
	shortname = "PS",
	extensions = { "ps1", "psm1", "psd1", "ps1xml", "pssc", "psrc", "cdxml" },
	comment = "#",

	patterns = {
		-- Comments
		{ pattern = "#.-\n", type = "comment" },
		{ pattern = { "<#", "#>" }, type = "comment" },

		-- Here-strings (must come before normal strings)
		{ pattern = { '@"', '"@' }, type = "string" }, -- @" ... "@  (expandable)
		{ pattern = { "@'", "'@" }, type = "string" }, -- @' ... '@  (literal)

		-- Strings
		-- PowerShell expandable strings: escape uses backtick, not backslash
		{ pattern = { '"', '"', "`" }, type = "string" },
		-- PowerShell literal strings: no backslash escapes
		{ pattern = { "'", "'" }, type = "string" },

		-- Numbers
		{ pattern = "0x[%da-fA-F]+", type = "hex" },
		{ pattern = "-?%d+[%d%.eE]*", type = "number" },
		{ pattern = "-?%.?%d+", type = "number" },

		-- Operators and punctuation
		{ pattern = "[%+%-=/%*%^%%<>!~|%?:%.%,%;%[%]%(%)%{%}]", type = "operator" },

		-- Variables
		-- ${...}
		{ pattern = "%${[^}]-}", type = "variable" },
		-- $env:PATH, $script:var, $global:var, $private:var, $local:var, $function:name
		{ pattern = "%$[%a_][%w_]*:%w[%w_]*", type = "variable" },
		-- General variables and common automatics
		{ pattern = "%$[%a_][%w_]*", type = "variable" },
		{ pattern = "%$_", type = "variable" },
		{ pattern = "%$%?", type = "variable" },
		{ pattern = "%$%$", type = "variable" },

		-- Attributes (often signal API surface)
		{ pattern = "%[[%a_][%w_%.%-]*%]", type = "meta" },

		-- Cmdlets: Verb-Noun (e.g. Get-Item)
		{ pattern = "[%u][%w_]*%-[%u][%w_]*", type = "function" },

		-- Parameter names: -Path, -Recurse, -ErrorAction
		{ pattern = "%f[%S]%-[%a][%w%-_]*", type = "function" },

		-- Declarations (captures used sparingly for the declared name)
		{ pattern = "%s*function%s+()[%a_][%w%-_]*", type = { "keyword", "function" }, line_start = true }, -- keyword + function name
		{ pattern = "%s*class%s+()[%a_][%w_]*", type = { "keyword", "keyword2" }, line_start = true }, -- keyword + class name
		{ pattern = "%s*enum%s+()[%a_][%w_]*", type = { "keyword", "keyword2" }, line_start = true }, -- keyword + enum name
		{ pattern = "%s*configuration%s+()[%a_][%w_]*", type = { "keyword", "keyword2" }, line_start = true }, -- keyword + configuration name

		-- Using directives
		{ pattern = "%s*(using%s+module%s+)([-%w_%.:\\/]+)", type = { "keyword", "string" }, line_start = true },
		{ pattern = "%s*(using%s+namespace%s+)([-%w_%.]+)",   type = { "keyword", "string" }, line_start = true },

		-- Call-like names (fallback)
		{ pattern = "[%a_][%w_]*%f[(]", type = "function" },

		-- Symbols and identifiers
		{ pattern = "[%a_][%w_]*", type = "symbol" },
	},

	outline_patterns = {
		-- Regions
		{ pattern = "%s*#region%s+.+", line_start = true },
		{ pattern = "%s*#endregion%s*", line_start = true },

		-- Requires and using (module surface)
		{ pattern = "%s*#requires%s+.+", line_start = true },
		{ pattern = "%s*using%s+module%s+.+", line_start = true },
		{ pattern = "%s*using%s+namespace%s+.+", line_start = true },

		-- Module exports (common in .psm1)
		{ pattern = "%s*Export%-ModuleMember%s+.+", line_start = true },

		-- Declarations
		{ pattern = "%s*function%s+[%a_][%w%-_]*", line_start = true },
		{ pattern = "%s*filter%s+[%a_][%w%-_]*", line_start = true },
		{ pattern = "%s*workflow%s+[%a_][%w%-_]*", line_start = true },
		{ pattern = "%s*configuration%s+[%a_][%w%-_]*", line_start = true },
		{ pattern = "%s*class%s+[%a_][%w_]*", line_start = true },
		{ pattern = "%s*enum%s+[%a_][%w_]*", line_start = true },

		-- Param blocks and common advanced function marker
		{ pattern = "%s*param%s*%b()", line_start = true },
		{ pattern = "%s*%[CmdletBinding%b()%]%s*$", line_start = true },

		-- Comment-based help (surface documentation)
		{ pattern = "%s*%.SYNOPSIS%s*$", line_start = true },
		{ pattern = "%s*%.DESCRIPTION%s*$", line_start = true },
		{ pattern = "%s*%.PARAMETER%s+.+", line_start = true },
		{ pattern = "%s*%.EXAMPLE%s*$", line_start = true },
		{ pattern = "%s*%.NOTES%s*$", line_start = true },
		{ pattern = "%s*%.LINK%s+.+", line_start = true },
	},

	block_comment = {
		block_open = "<#",
		block_close = "#>",
		block_line_prefix = " ",
		close_line_prefix = " ",
		open_on_own_line = false,
		close_on_own_line = true,
		strip_line_prefix = "^%s*",
		allow_nested = false,
	},

	guard_comment = {
		guard_open = { "if ($false) {", "if (0) {" },
		guard_close = "}",
		guard_body_prefix = "auto",
		guard_align_to_indent = true,
		allow_nested = true,
	},

	quotes = {
		primary = "double",
		secondary = "single",
		profiles = {
			double = quotes.profile.c_style_double(),
			single = quotes.profile.c_style_single(),
		},
	},

	symbols = {
		-- Control Flow
		["if"] = "keyword", -- Conditional branch
		["else"] = "keyword", -- If-else branch
		["elseif"] = "keyword", -- Combined else-if
		["switch"] = "keyword", -- Multi-way branch
		["default"] = "keyword", -- Switch default label
		["while"] = "keyword", -- Standard while loop
		["for"] = "keyword", -- For loop
		["foreach"] = "keyword", -- Collection iteration
		["do"] = "keyword", -- Start of do-while or do-until
		["until"] = "keyword", -- Loop condition for do...until
		["break"] = "keyword", -- Exit loop or switch
		["continue"] = "keyword", -- Skip to next loop iteration
		["in"] = "keyword", -- Used in foreach ($x in $y)
		["return"] = "keyword", -- Exit function and return value
		["exit"] = "keyword", -- Terminate script or runspace
		["throw"] = "keyword", -- Explicitly throw exception
		["trap"] = "keyword", -- Trap an exception
		["try"] = "keyword", -- Start error-handling block
		["catch"] = "keyword", -- Handle exception
		["finally"] = "keyword", -- Always executed block

		-- Variable Declarations
		["param"] = "keyword", -- Parameter block
		["dynamicparam"] = "keyword", -- Dynamic parameter block

		-- Pipeline Blocks
		["begin"] = "keyword", -- Pipeline begin block
		["process"] = "keyword", -- Pipeline process block
		["end"] = "keyword", -- Pipeline end block

		-- Declarations and Script Structure
		["function"] = "keyword", -- Declare a function
		["filter"] = "keyword", -- Declare a filter (pipeline-friendly function)
		["workflow"] = "keyword", -- Declare a workflow (Windows PowerShell)
		["configuration"] = "keyword", -- Declare a DSC configuration
		["class"] = "keyword", -- Define a class
		["enum"] = "keyword", -- Define an enumeration
		["data"] = "keyword", -- Data section

		-- Modules
		["using"] = "keyword", -- Using statement and module or namespace import

		-- Common Attributes (meta-ish keywords)
		["CmdletBinding"] = "keyword", -- Marks an advanced function
		["Parameter"] = "keyword", -- Declares a parameter attribute
		["ValidateSet"] = "keyword", -- Validate input against a fixed set
		["ValidateRange"] = "keyword", -- Validate numeric range
		["ValidatePattern"] = "keyword", -- Validate with regex pattern
		["ValidateScript"] = "keyword", -- Validate with a script block
		["Alias"] = "keyword", -- Adds alternative names
		["OutputType"] = "keyword", -- Declares output type
		["SupportsShouldProcess"] = "keyword", -- Enables -WhatIf or -Confirm

		-- Literals
		["$true"] = "literal", -- Boolean true literal
		["$false"] = "literal", -- Boolean false literal
		["$null"] = "literal", -- Null literal

		-- Comment tags
		["TODO"] = "comment", -- Task marker
		["FIXME"] = "comment", -- Bug marker
		["XXX"] = "comment", -- Attention marker
		["TBD"] = "comment", -- To be decided
		["HACK"] = "comment", -- Hacky workaround
		["NOTE"] = "comment", -- Note marker
	},
})
