# src/main.py
# Parses and calls commands

from ctf.commands import basic_group
from ctf.cli_forensics import forensics_group
import click
import sys
import re

# Globally track the detector instance if it is active
_active_detector = None

# {{{ FlagDetectorStream
class FlagDetectorStream:
    """Intercepts stdout to scan output for matching flag formats."""
    def __init__(self, original_stream, pattern_str):
        self.original_stream = original_stream
        self._flag_buffer = ""
        self.detecting = True
        
        # Clean pattern from standard anchors ^ and $ for substring matching
        pat = pattern_str
        if pat.startswith("^") and pat.endswith("$"):
            pat = pat[1:-1]
        try:
            self.pattern = re.compile(pat) if pat else None
        except re.error:
            self.pattern = None
            
    def write(self, data):
        self.original_stream.write(data)
        if self.detecting and self.pattern:
            self._flag_buffer += data
            matches = []
            for match in self.pattern.finditer(self._flag_buffer):
                matches.append(match.group())
            if matches:
                self.detecting = False
                self.original_stream.write("\n\033[1;32m[!] Potential flag(s) detected in command output:\033[0m\n")
                for match in matches:
                    self.original_stream.write(f"  \033[1;32m✓ {match}\033[0m\n")
                    try:
                        from ctf.utils import load_config, write_config
                        config_path = "/home/venus/code/ctf/config.toml"
                        config = load_config(config_path)
                        if "Competition" not in config:
                            config["Competition"] = {}
                        config["Competition"]["last_flag"] = match
                        write_config(config, config_path)
                    except Exception:
                        pass
                self._flag_buffer = ""
                self.detecting = True
                
    def flush(self):
        self.original_stream.flush()

    def __getattr__(self, name):
        return getattr(self.original_stream, name)
# }}}

# {{{ flag_cmd
@click.command(name="flag")
@click.option("-p", "--plain", is_flag=True, help="Print raw flag without flavor text.")
def flag_cmd(plain):
    """Retrieve the last detected flag from config."""
    global _active_detector
    if _active_detector is not None:
        _active_detector.detecting = False
    try:
        from ctf.utils import load_config
        config = load_config("/home/venus/code/ctf/config.toml")
        last_flag = config.get("Competition", {}).get("last_flag", "")
        if not last_flag:
            if not plain:
                click.echo("No flag has been detected yet.")
            return
        if plain:
            click.echo(last_flag, nl=False)
        else:
            click.echo(f"Last detected flag: {last_flag}")
    finally:
        if _active_detector is not None:
            _active_detector.detecting = True
# }}}

# {{{ main
def main():
    @click.group()
    def cli(): pass
    
    cli.add_command(forensics_group)
    cli.add_command(basic_group)
    cli.add_command(flag_cmd)
    
    from ctf.utils import load_config
    config = load_config("/home/venus/code/ctf/config.toml")
    flag_format = config.get("Competition", {}).get("flag_format", "")
    
    global _active_detector
    if flag_format:
        detector = FlagDetectorStream(sys.stdout, flag_format)
        sys.stdout = detector
        _active_detector = detector
        try:
            cli()
        finally:
            sys.stdout = detector.original_stream
            _active_detector = None
    else:
        cli()
# }}}

if __name__ == "__main__":
    main()
