# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt

"""LCOV reporting for coverage.py."""

from __future__ import annotations

import base64
import hashlib
import sys
from collections.abc import Iterable
from typing import IO, TYPE_CHECKING

from coverage.plugin import FileReporter
from coverage.report_core import get_analysis_to_report
from coverage.results import Analysis, AnalysisNarrower, Numbers
from coverage.types import TMorf

if TYPE_CHECKING:
    from coverage import Coverage


def line_hash(line: str) -> str:
    """Produce a hash of a source line for use in the LCOV file."""
    # The LCOV file format optionally allows each line to be MD5ed as a
    # fingerprint of the file.  This is not a security use.  Some security
    # scanners raise alarms about the use of MD5 here, but it is a false
    # positive.  This is not a security concern.
    # The unusual encoding of the MD5 hash, as a base64 sequence with the
    # trailing = signs stripped, is specified by the LCOV file format.
    hashed = hashlib.md5(line.encode("utf-8"), usedforsecurity=False).digest()
    return base64.b64encode(hashed).decode("ascii").rstrip("=")


def lcov_lines(
    analysis: Analysis,
    lines: list[int],
    source_lines: list[str],
    outfile: IO[str],
) -> None:
    """Emit line coverage records for an analyzed file."""
    hash_suffix = ""
    for line in lines:
        if source_lines:
            hash_suffix = "," + line_hash(source_lines[line - 1])
        # Q: can we get info about the number of times a statement is
        # executed?  If so, that should be recorded here.
        hit = int(line not in analysis.missing)
        outfile.write(f"DA:{line},{hit}{hash_suffix}\n")

    if analysis.numbers.n_statements > 0:
        outfile.write(f"LF:{analysis.numbers.n_statements}\n")
        outfile.write(f"LH:{analysis.numbers.n_executed}\n")


def lcov_functions(
    fr: FileReporter,
    file_analysis: Analysis,
    outfile: IO[str],
) -> None:
    """Emit function coverage records for an analyzed file."""
    # lcov 2.2 introduces a new format for function coverage records.
    # We continue to generate the old format because we don't know what
    # version of the lcov tools will be used to read this report.

    # "and region.lines" below avoids a crash due to a bug in PyPy 3.8
    # where, for whatever reason, when collecting data in --branch mode,
    # top-level functions have an empty lines array.  Instead we just don't
    # emit function records for those.

    # suppressions because of https://github.com/pylint-dev/pylint/issues/9923
    functions = [
        (
            min(region.start, min(region.lines)),  # pylint: disable=nested-min-max
            max(region.start, max(region.lines)),  # pylint: disable=nested-min-max
            region,
        )
        for region in fr.code_regions()
        if region.kind == "function" and region.lines
    ]
    if not functions:
        return

    narrower = AnalysisNarrower(file_analysis)
    narrower.add_regions(r.lines for _, _, r in functions)

    functions.sort()
    functions_hit = 0
    for first_line, last_line, region in functions:
        # A function counts as having been executed if any of it has been
        # executed.
        analysis = narrower.narrow(region.lines)
        hit = int(analysis.numbers.n_executed > 0)
        functions_hit += hit

        outfile.write(f"FN:{first_line},{last_line},{region.name}\n")
        outfile.write(f"FNDA:{hit},{region.name}\n")

    outfile.write(f"FNF:{len(functions)}\n")
    outfile.write(f"FNH:{functions_hit}\n")


def lcov_arcs(
    fr: FileReporter,
    analysis: Analysis,
    lines: list[int],
    outfile: IO[str],
) -> None:
    """Emit branch coverage records for an analyzed file."""
    branch_stats = analysis.branch_stats()
    executed_arcs = analysis.executed_branch_arcs()
    missing_arcs = analysis.missing_branch_arcs()

    for line in lines:
        if line not in branch_stats:
            continue

        # This is only one of several possible ways to map our sets of executed
        # and not-executed arcs to BRDA codes.  It seems to produce reasonable
        # results when fed through genhtml.
        _, taken = branch_stats[line]

        if taken == 0:
            # When _none_ of the out arcs from 'line' were executed,
            # it can mean the line always raised an exception.
            assert len(executed_arcs[line]) == 0
            destinations = [(dst, "-") for dst in missing_arcs[line]]
        else:
            # Q: can we get counts of the number of times each arc was executed?
            # branch_stats has "total" and "taken" counts for each branch,
            # but it doesn't have "taken" broken down by destination.
            destinations = [(dst, "1") for dst in executed_arcs[line]]
            destinations.extend((dst, "0") for dst in missing_arcs[line])

        # Sort exit arcs after normal arcs.  Exit arcs typically come from
        # an if statement, at the end of a function, with no else clause.
        # This structure reads like you're jumping to the end of the function
        # when the conditional expression is false, so it should be presented
        # as the second alternative for the branch, after the alternative that
        # enters the if clause.
        destinations.sort(key=lambda d: (d[0] < 0, d))

        for dst, hit in destinations:
            branch = fr.arc_description(line, dst)
            outfile.write(f"BRDA:{line},0,{branch},{hit}\n")

    # Summary of the branch coverage.
    brf = sum(t for t, k in branch_stats.values())
    brh = brf - sum(t - k for t, k in branch_stats.values())
    if brf > 0:
        outfile.write(f"BRF:{brf}\n")
        outfile.write(f"BRH:{brh}\n")


class LcovReporter:
    """A reporter for writing LCOV coverage reports."""

    report_type = "LCOV report"

    def __init__(self, coverage: Coverage) -> None:
        self.coverage = coverage
        self.config = coverage.config
        self.total = Numbers(self.coverage.config.precision)

    def report(self, morfs: Iterable[TMorf] | None, outfile: IO[str]) -> float:
        """Renders the full lcov report.

        `morfs` is a list of modules or filenames

        outfile is the file object to write the file into.
        """

        self.coverage.get_data()
        outfile = outfile or sys.stdout

        # ensure file records are sorted by the _relative_ filename, not the full path
        to_report = [
            (fr.relative_filename(), fr, analysis)
            for fr, analysis in get_analysis_to_report(self.coverage, morfs)
        ]
        to_report.sort()

        for fname, fr, analysis in to_report:
            self.total += analysis.numbers
            self.lcov_file(fname, fr, analysis, outfile)

        return self.total.n_statements and self.total.pc_covered

    def lcov_file(
        self,
        rel_fname: str,
        fr: FileReporter,
        analysis: Analysis,
        outfile: IO[str],
    ) -> None:
        """Produces the lcov data for a single file.

        This currently supports both line and branch coverage,
        however function coverage is not supported.
        """

        if analysis.numbers.n_statements == 0:
            if self.config.skip_empty:
                return

        outfile.write(f"SF:{rel_fname}\n")

        lines = sorted(analysis.statements)
        if self.config.lcov_line_checksums:
            source_lines = fr.source().splitlines()
        else:
            source_lines = []

        lcov_lines(analysis, lines, source_lines, outfile)
        lcov_functions(fr, analysis, outfile)
        if analysis.has_arcs:
            lcov_arcs(fr, analysis, lines, outfile)

        outfile.write("end_of_record\n")
