"""sentence-menu: A command-line fuzzy menu keyed based on full sentences."""

import argparse
import json
import os
import subprocess
import sys
from pathlib import Path


def get_store_path():
    xdg = os.environ.get("XDG_DATA_HOME", os.path.expanduser("~/.local/share"))
    path = Path(xdg) / "sentence-menu" / "commands.json"
    path.parent.mkdir(parents=True, exist_ok=True)
    return path


def load_entries():
    path = get_store_path()
    if not path.exists():
        return []
    with open(path) as f:
        return json.load(f)


def save_entries(entries):
    path = get_store_path()
    with open(path, "w") as f:
        json.dump(entries, f, indent=2)


def fzf_select(entries):
    if not entries:
        print("No entries yet. Use 'sentence-menu add' to add one.", file=sys.stderr)
        sys.exit(1)

    lines = [e["sentence"] for e in entries]
    input_text = "\n".join(lines)

    try:
        result = subprocess.run(
            ["fzf", "--height=40%", "--reverse", "--prompt=  "],
            input=input_text,
            stdout=subprocess.PIPE,
            text=True,
        )
    except FileNotFoundError:
        print("fzf is required but not installed.", file=sys.stderr)
        print("Install it: https://github.com/junegunn/fzf", file=sys.stderr)
        sys.exit(1)

    if result.returncode != 0:
        sys.exit(1)

    selected = result.stdout.strip()
    for e in entries:
        if e["sentence"] == selected:
            return e
    return None


def cmd_add():
    sentence = input("Sentence: ").strip()
    if not sentence:
        print("Aborted.", file=sys.stderr)
        sys.exit(1)

    command = input("Command: ").strip()
    if not command:
        print("Aborted.", file=sys.stderr)
        sys.exit(1)

    entries = load_entries()
    entries.append({"sentence": sentence, "command": command})
    save_entries(entries)
    print(f"Added: {sentence}")


def cmd_edit():
    import tempfile

    entries = load_entries()
    entry = fzf_select(entries)
    if not entry:
        return

    editor = os.environ.get("VISUAL") or os.environ.get("EDITOR", "vi")

    with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:
        f.write(f"Sentence: {entry['sentence']}\n")
        f.write(f"Command: {entry['command']}\n")
        tmppath = f.name

    try:
        subprocess.run([editor, tmppath])

        with open(tmppath) as f:
            lines = f.readlines()

        for line in lines:
            if line.startswith("Sentence:"):
                new_sentence = line[len("Sentence:"):].strip()
                if new_sentence:
                    entry["sentence"] = new_sentence
            elif line.startswith("Command:"):
                new_command = line[len("Command:"):].strip()
                if new_command:
                    entry["command"] = new_command

        save_entries(entries)
        print("Updated.")
    finally:
        os.unlink(tmppath)


def cmd_run():
    entries = load_entries()
    entry = fzf_select(entries)
    if entry:
        import time
        print(f"$ {entry['command']}", file=sys.stderr)
        time.sleep(0.1)
        os.execvp("sh", ["sh", "-c", entry["command"]])


def cmd_echo():
    entries = load_entries()
    entry = fzf_select(entries)
    if entry:
        print(entry["command"])


def cmd_remove():
    entries = load_entries()
    entry = fzf_select(entries)
    if entry:
        entries.remove(entry)
        save_entries(entries)
        print(f"Removed: {entry['sentence']}")


def main():
    parser = argparse.ArgumentParser(
        prog="sentence-menu",
        description="A command-line fuzzy menu keyed based on full sentences.",
    )
    subparsers = parser.add_subparsers(dest="command")

    subparsers.add_parser("add", help="Interactively add a command")
    subparsers.add_parser("edit", help="Interactively edit an entry")
    subparsers.add_parser("echo", help="Print a command to stdout")
    subparsers.add_parser("remove", help="Remove an entry")

    args = parser.parse_args()

    if args.command == "add":
        cmd_add()
    elif args.command == "edit":
        cmd_edit()
    elif args.command == "echo":
        cmd_echo()
    elif args.command == "remove":
        cmd_remove()
    else:
        cmd_run()


if __name__ == "__main__":
    main()