from contextlib import suppress

from bbot.core.helpers.logger import log_to_stderr
from bbot.modules.output.base import BaseOutputModule


class Human(BaseOutputModule):
    watched_events = ["*"]
    meta = {"description": "Output to text"}
    options = {"output_file": "", "console": True}
    options_desc = {"output_file": "Output to file", "console": "Output to console"}
    vuln_severity_map = {"LOW": "HUGEWARNING", "MEDIUM": "HUGEWARNING", "HIGH": "CRITICAL", "CRITICAL": "CRITICAL"}

    def setup(self):
        self._prep_output_dir("output.txt")
        return True

    def handle_event(self, event):
        event_type = f"[{event.type}]"
        event_tags = ""
        if getattr(event, "tags", []):
            event_tags = f'\t({", ".join(sorted(getattr(event, "tags", [])))})'
        event_str = f"{event_type:<20}\t{event.data_human}\t{event.module}{event_tags}"
        # log vulnerabilities in vivid colors
        if event.type == "VULNERABILITY":
            severity = event.data.get("severity", "INFO")
            if severity in self.vuln_severity_map:
                loglevel = self.vuln_severity_map[severity]
                log_to_stderr(event_str, level=loglevel, logname=False)
        elif event.type == "FINDING":
            log_to_stderr(event_str, level="HUGEINFO", logname=False)

        if self.file is not None:
            self.file.write(event_str + "\n")
            self.file.flush()
        if self.config.get("console", True):
            self.stdout(event_str)

    def cleanup(self):
        if getattr(self, "_file", None) is not None:
            with suppress(Exception):
                self.file.close()

    def report(self):
        if self._file is not None:
            self.info(f"Saved TXT output to {self.output_file}")
