# Provides json2nix command for converting JSON to Nix attribute set syntax
# Usage: wl-paste | json2nix | wl-copy
#        json2nix < settings.json
{ config, lib, pkgs, ... }:

let
  cfg = config.json2nix;

  json2nixScript = pkgs.writeScriptBin "json2nix" ''
    #!${pkgs.python3}/bin/python3
    """Convert JSON to Nix attribute set syntax.
    
    Usage: wl-paste | json2nix | wl-copy
           json2nix < settings.json
    """
    import json
    import sys

    def to_nix(obj, indent=0):
        """Convert a Python object (from JSON) to Nix syntax."""
        spaces = "  " * indent
        
        if obj is None:
            return "null"
        elif isinstance(obj, bool):
            return "true" if obj else "false"
        elif isinstance(obj, int):
            return str(obj)
        elif isinstance(obj, float):
            # Ensure floats stay as floats (e.g., 1.0 not 1)
            s = str(obj)
            if '.' not in s and 'e' not in s.lower():
                s += ".0"
            return s
        elif isinstance(obj, str):
            # Escape special characters for Nix strings
            escaped = obj.replace("\\", "\\\\")
            escaped = escaped.replace('"', '\\"')
            escaped = escaped.replace("\n", "\\n")
            escaped = escaped.replace("\r", "\\r")
            escaped = escaped.replace("\t", "\\t")
            return f'"{escaped}"'
        elif isinstance(obj, list):
            if not obj:
                return "[ ]"
            items = []
            for item in obj:
                items.append(f"{spaces}  {to_nix(item, indent + 1)}")
            return "[\n" + "\n".join(items) + f"\n{spaces}]"
        elif isinstance(obj, dict):
            if not obj:
                return "{ }"
            items = []
            for key, value in obj.items():
                # Quote keys that aren't valid Nix identifiers
                if not key.isidentifier() or key in ['if', 'then', 'else', 'let', 'in', 'with', 'rec', 'inherit', 'or', 'and']:
                    nix_key = f'"{key}"'
                else:
                    nix_key = key
                nix_value = to_nix(value, indent + 1)
                items.append(f"{spaces}  {nix_key} = {nix_value};")
            return "{\n" + "\n".join(items) + f"\n{spaces}}}"

    try:
        data = json.load(sys.stdin)
        print(to_nix(data))
    except json.JSONDecodeError as e:
        print(f"Error: Invalid JSON - {e}", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)
  '';
in
{
  options.json2nix = {
    enable = lib.mkEnableOption "json2nix command for converting JSON to Nix syntax";
  };

  config = lib.mkIf cfg.enable {
    home.packages = [ json2nixScript ];
  };
}
