from __future__ import annotations

import re
from pathlib import Path
from typing import List, Tuple

from .models import AttackSurfaceEntry, FindingDetail, Severity


class JSAnalyzer:
    """
    Heuristic analyzer for JavaScript files.
    """

    def __init__(self, strict: bool = True):
        self.strict = strict
        # Simple regex-based sinks
        self.sinks = {
            "innerHTML": "DOM XSS risk",
            "outerHTML": "DOM XSS risk",
            "document.write": "DOM XSS risk",
            "eval": "Code execution risk",
            "setTimeout": "Code execution risk if string used",
            "setInterval": "Code execution risk if string used",
        }

    def analyze(self, path: Path, content: str) -> Tuple[List[FindingDetail], List[AttackSurfaceEntry]]:
        findings: List[FindingDetail] = []
        surface: List[AttackSurfaceEntry] = []

        lines = content.splitlines()
        for idx, line in enumerate(lines, start=1):
            stripped = line.strip()
            if not stripped or stripped.startswith("//"):
                continue

            # Check for sinks
            for sink, desc in self.sinks.items():
                # Basic check: sink name followed by assignment or call
                # e.g. element.innerHTML = ... or eval(...)
                if sink in ["innerHTML", "outerHTML"]:
                    if re.search(rf"\.{sink}\s*=", line):
                        findings.append(
                            FindingDetail(
                                category="js-xss",
                                message=f"Potential DOM XSS via {sink}",
                                severity=Severity.MEDIUM,
                                file=str(path),
                                line=idx,
                                evidence=stripped,
                                remediation="Use textContent or safe DOM manipulation methods.",
                            )
                        )
                elif sink == "document.write":
                    if "document.write" in line:
                         findings.append(
                            FindingDetail(
                                category="js-xss",
                                message="Use of document.write",
                                severity=Severity.MEDIUM,
                                file=str(path),
                                line=idx,
                                evidence=stripped,
                                remediation="Avoid document.write; use DOM manipulation.",
                            )
                        )
                else:
                    # Function calls like eval(...)
                    if re.search(rf"\b{sink}\s*\(", line):
                        findings.append(
                            FindingDetail(
                                category="js-dangerous-func",
                                message=f"Use of dangerous function {sink}",
                                severity=Severity.HIGH if self.strict else Severity.MEDIUM,
                                file=str(path),
                                line=idx,
                                evidence=stripped,
                                remediation=f"Avoid using {sink} with dynamic strings.",
                            )
                        )

            # Hardcoded secrets (simple heuristic)
            if re.search(r"(api_key|token|secret)\s*[:=]\s*['\"][A-Za-z0-9_\-]{20,}['\"]", line, re.IGNORECASE):
                 findings.append(
                    FindingDetail(
                        category="hardcoded-secret",
                        message="Potential hardcoded secret detected",
                        severity=Severity.HIGH,
                        file=str(path),
                        line=idx,
                        evidence=stripped,
                        remediation="Do not hardcode secrets. Use environment variables or server-side configuration.",
                    )
                )

        return findings, surface
