"use client";

/**
 * ScoringTransparency — 6.5 «Прозрачность скоринга». §13.6 scoring.product_scores:
 * one row per §14.2 product score — factor (RU label) · вес (value ∈ 0..1) ·
 * направление. Score semantics (HARD): value ∈ [0,1], выше = лучше для девелопера
 * (risk scores pre-inverted at the source), anchored on 0.5 = balance. So the
 * direction reads off the 0.5 midpoint: ≥0.55 «сильный» / 0.45–0.55 «нейтральный»
 * / <0.45 «слабый». Rows with value=null (thin data) render «нет данных».
 *
 * GRACEFUL: returns null when scoring carries no product scores.
 */

import styles from "@/app/site-finder/analysis/[cad]/ptica/ptica.module.css";
import type {
  ProductScore,
  ProductScoreCard,
  ReportScoring,
} from "@/types/forecast";
import { fmtNum } from "./scenario-helpers";

interface Props {
  scoring: ReportScoring;
}

const SCORE_GOOD_THRESHOLD = 0.55;
const SCORE_WEAK_THRESHOLD = 0.45;

const PRODUCT_SCORE_RU: Record<string, string> = {
  market_fit: "Соответствие рынку",
  demand: "Спрос",
  // #1963: «Риск …» сбивал (скор инвертирован, выше=лучше) → «Запас по предложению».
  supply_risk: "Запас по предложению",
  future_competition: "Будущая конкуренция",
  price_feasibility: "Доступность цены",
  infra_fit: "Инфраструктура",
  mortgage_sensitivity: "Чувствительность к ставке",
  differentiation: "Дифференциация",
  commercial: "Коммерция",
  confidence: "Надёжность данных",
};

// #1963 — порог баланса итогового скора (0.5 = баланс).
const OVERALL_BALANCE = 0.5;

/**
 * #1963 — §-ссылки («§10.4», «§9.6») из основного reason в tooltip-детали.
 * Возвращает {clean, refs}. Зеркало analysis/forecast-helpers.stripSectionRefs.
 */
function stripSectionRefs(reason: string): {
  clean: string;
  refs: string | null;
} {
  const SECTION_RE = /§\s*\d+(?:\.\d+)*(?:[a-zа-я](?=$|[\s.,;)]))?/gi;
  const refs = reason.match(SECTION_RE) ?? [];
  const clean = reason
    .replace(SECTION_RE, "")
    .replace(/\(\s*[,;]?\s*\)/g, "")
    .replace(/,\s*\)/g, ")")
    .replace(/\(\s+/g, "(")
    .replace(/\s+\)/g, ")")
    .replace(/\s{2,}/g, " ")
    .replace(/\s+([.,;)])/g, "$1")
    .trim();
  return { clean, refs: refs.length > 0 ? refs.join(", ") : null };
}

interface Direction {
  text: string;
  toneClass: string;
}

function scoreDirection(value: number | null): Direction {
  if (value == null) return { text: "—", toneClass: "" };
  if (value >= SCORE_GOOD_THRESHOLD)
    return { text: "сигнал ↑", toneClass: styles.numPos };
  if (value >= SCORE_WEAK_THRESHOLD)
    return { text: "нейтрально →", toneClass: "" };
  return { text: "сигнал ↓", toneClass: styles.numNeg };
}

function scoreRows(card: ProductScoreCard | null): ProductScore[] {
  if (card == null) return [];
  return Object.values(card.scores).filter(
    (s): s is ProductScore => s != null && typeof s.key === "string",
  );
}

export function ScoringTransparency({ scoring }: Props) {
  const scores = scoreRows(scoring.product_scores);
  if (scores.length === 0) return null;

  return (
    <>
      <div className={styles.sectionLabel}>
        6.5 · <b>прозрачность скоринга</b>
      </div>
      <div className={styles.panel}>
        {/* #1963 — общий вердикт по итоговому скору относительно баланса 0.5. */}
        {scoring.overall != null && (
          <p className={styles.confRationale}>
            {scoring.overall < OVERALL_BALANCE
              ? `Итог ${fmtNum(scoring.overall, 2)} ниже баланса 0.5 — рынок для этого продукта скорее неблагоприятный.`
              : `Итог ${fmtNum(scoring.overall, 2)} на уровне баланса 0.5 или выше — рынок для этого продукта скорее благоприятный.`}
          </p>
        )}
        <table className={styles.dtable}>
          <thead>
            <tr>
              <th>Фактор прогноза</th>
              {/* #1963 — «Вес» вводил в заблуждение: это значение скора, не вес. */}
              <th className={styles.thNum}>Оценка</th>
              <th>Направление</th>
            </tr>
          </thead>
          <tbody>
            {scores.map((s) => {
              const dir = scoreDirection(s.value);
              // #1963 — показываем причину прямо в строке (раньше только tooltip);
              // §-ссылки уводим в title-«детали».
              const { clean, refs } = s.reason
                ? stripSectionRefs(s.reason)
                : { clean: "", refs: null };
              return (
                <tr key={s.key}>
                  <td title={refs ? `Источник: ${refs}` : undefined}>
                    {PRODUCT_SCORE_RU[s.key] ?? s.key}
                    {clean && <p className={styles.scoreReason}>{clean}</p>}
                  </td>
                  <td className={styles.tdNum}>
                    {s.value != null ? fmtNum(s.value, 2) : "нет данных"}
                  </td>
                  <td className={dir.toneClass}>{dir.text}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
        <p className={styles.panelHint}>
          Оценка — значение скора ∈ 0…1 (выше — лучше для девелопера; риск-скоры
          уже инвертированы, поэтому «выше = лучше» и для них). Направление —
          относительно баланса 0.5.
        </p>
      </div>
    </>
  );
}
