#!/usr/bin/env python3
"""Validate and score the Chapter 16 technology selection matrix."""

from __future__ import annotations

import csv
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
MATRIX = ROOT / "technology_selection_matrix.csv"
CANDIDATES = ["managed_warehouse", "open_lakehouse", "self_managed_stack"]
REQUIRED_COLUMNS = {"criterion", "weight", "evidence_required", *CANDIDATES}


def main() -> None:
    if not MATRIX.exists():
        raise SystemExit(f"Missing matrix: {MATRIX}")

    with MATRIX.open(newline="", encoding="utf-8") as handle:
        reader = csv.DictReader(handle)
        missing = REQUIRED_COLUMNS - set(reader.fieldnames or [])
        if missing:
            raise SystemExit(f"Matrix is missing required columns: {sorted(missing)}")
        rows = list(reader)

    if len(rows) < 5:
        raise SystemExit("Matrix should contain at least five decision criteria.")

    total_weight = 0.0
    scores = {candidate: 0.0 for candidate in CANDIDATES}

    for row in rows:
        criterion = row["criterion"].strip()
        if not criterion:
            raise SystemExit("Every row must have a criterion name.")
        try:
            weight = float(row["weight"])
        except ValueError as exc:
            raise SystemExit(f"Invalid weight for {criterion}: {row['weight']}") from exc
        if weight <= 0:
            raise SystemExit(f"Weight must be positive for {criterion}.")
        total_weight += weight

        if len(row["evidence_required"].strip()) < 20:
            raise SystemExit(f"Evidence requirement for {criterion} is too vague.")

        for candidate in CANDIDATES:
            try:
                score = float(row[candidate])
            except ValueError as exc:
                raise SystemExit(f"Invalid score for {candidate} / {criterion}: {row[candidate]}") from exc
            if not 1 <= score <= 10:
                raise SystemExit(f"Score for {candidate} / {criterion} must be between 1 and 10.")
            scores[candidate] += weight * score

    if abs(total_weight - 1.0) > 0.0001:
        raise SystemExit(f"Weights must sum to 1.0; found {total_weight:.4f}.")

    print("Weighted scores:")
    for candidate, score in sorted(scores.items(), key=lambda item: item[1], reverse=True):
        print(f"- {candidate}: {score:.2f}")

    winner = max(scores, key=scores.get)
    print(f"Recommended option under current weights: {winner}")
    print("Validation passed: matrix shape, weights, scores, and evidence requirements are usable.")


if __name__ == "__main__":
    main()
