"""Offline, synthetic threshold exercise. Requires Python 3; no external packages."""
from dataclasses import dataclass


@dataclass(frozen=True)
class Counts:
    tp: int
    fp: int
    tn: int
    fn: int

    @property
    def alerts(self):
        return self.tp + self.fp

    @property
    def precision(self):
        return self.tp / self.alerts if self.alerts else None

    @property
    def recall(self):
        positives = self.tp + self.fn
        return self.tp / positives if positives else None


def evaluate(rows, threshold):
    """Rows are (score, actual label). Scores equal to the threshold are positive."""
    tp = fp = tn = fn = 0
    for score, label in rows:
        predicted = score >= threshold
        if predicted and label == 1:
            tp += 1
        elif predicted and label == 0:
            fp += 1
        elif not predicted and label == 0:
            tn += 1
        elif not predicted and label == 1:
            fn += 1
        else:
            raise ValueError('Labels must be 0 or 1')
    return Counts(tp, fp, tn, fn)


def choose_threshold(rows, thresholds, capacity):
    """Maximize validation recall under capacity; break ties at the higher threshold."""
    candidates = [(threshold, evaluate(rows, threshold)) for threshold in thresholds]
    feasible = [(t, c) for t, c in candidates if c.alerts <= capacity and c.recall is not None]
    if not feasible:
        raise ValueError('No feasible threshold with measurable recall')
    return max(feasible, key=lambda item: (item[1].recall, item[0]))


def display(value):
    return 'undefined' if value is None else f'{value:.3f}'


def main():
    # Synthetic examples; validation and test are intentionally separate.
    validation = [(0.95, 1), (0.85, 0), (0.75, 1), (0.65, 0),
                  (0.55, 1), (0.45, 0), (0.35, 1), (0.25, 0)]
    test = [(0.90, 1), (0.80, 0), (0.70, 1), (0.60, 1), (0.40, 0), (0.20, 0)]
    thresholds = [0.35, 0.50, 0.65, 0.80, 1.00]
    threshold, selected = choose_threshold(validation, thresholds, capacity=4)
    result = evaluate(test, threshold)
    print(f'Chosen validation threshold: {threshold:.2f}; alerts: {selected.alerts}; '
          f'recall: {display(selected.recall)}')
    print(f'Test TP={result.tp} FP={result.fp} TN={result.tn} FN={result.fn}')
    print(f'Test precision={display(result.precision)} recall={display(result.recall)}')


if __name__ == '__main__':
    main()
