import { describe, expect, it } from "vitest";
import { composeAssistantAnswer } from "../src/services/answerComposer";
import type { UnifiedRetrievalResult } from "../src/types/assistant";

function buildRetrievalWithMojibake(): UnifiedRetrievalResult {
  return {
    fragment_id: "F1",
    requirement_ids: ["R1"],
    route: "hybrid_store_plus_live",
    status: "ok",
    result_type: "chain",
    items: [
      {
        counterparty_id: "CP-1",
        operations_count: 12,
        document_refs_count: 3
      }
    ],
    summary: {
      route_focus: "cross_entity_breakage",
      source_records: 262,
      filtered_records_after_narrowing: 24,
      checked_records: 24,
      semantic_narrowing_applied: true,
      ranking_basis: ["closure_risk", "repeatability", "financial_impact"]
    },
    evidence: [],
    why_included: [
      "РЎРµРјР°РЅС‚РёС‡РµСЃРєРѕРµ СЃСѓР¶РµРЅРёРµ РІС‹РїРѕР»РЅРµРЅРѕ РїРѕ РїСЂРѕС„РёР»СЋ cross_entity_breakage.",
      "РџРѕСЃР»Рµ narrowing РѕСЃС‚Р°Р»РѕСЃСЊ 24 РёР· 262 Р·Р°РїРёСЃРµР№."
    ],
    selection_reason: [
      "РћС‚Р±РѕСЂ РѕСЃРЅРѕРІР°РЅ РЅР° account_scope + domain_scope + document_types + relation_patterns + anomaly_patterns.",
      "Р Р°РЅР¶РёСЂРѕРІР°РЅРёРµ РїРѕ basis: closure_risk, repeatability, financial_impact."
    ],
    risk_factors: ["broken_chain", "period_close_risk"],
    business_interpretation: [],
    confidence: "medium",
    limitations: [],
    errors: []
  };
}

describe("assistant answer encoding sanitizer", () => {
  it("filters mojibake in explainable answer and falls back to readable reasoning", () => {
    const output = composeAssistantAnswer({
      userMessage: "Разложи цепочку и покажи хвосты по расчетам за 2020-06.",
      routeSummary: {
        mode: "deterministic_v2",
        message_in_scope: true,
        scope_confidence: "high",
        planner: {
          total_fragments: 1,
          in_scope_fragments: 1,
          out_of_scope_fragments: 0,
          discarded_fragments: 0,
          contains_multiple_tasks: false
        },
        decisions: [],
        fallback: {
          type: "none",
          message: null
        }
      },
      retrievalResults: [buildRetrievalWithMojibake()],
      requirements: [
        {
          requirement_id: "R1",
          source_fragment_id: "F1",
          requirement_text: "Проверка цепочки расчетов",
          subject_tokens: ["chain", "account_60"],
          status: "covered",
          route: "hybrid_store_plus_live"
        }
      ],
      coverageReport: {
        requirements_total: 1,
        requirements_covered: 1,
        requirements_uncovered: [],
        requirements_partially_covered: [],
        clarification_needed_for: [],
        out_of_scope_requirements: []
      },
      groundingCheck: {
        status: "grounded",
        route_subject_match: true,
        missing_requirements: [],
        reasons: [],
        why_included_summary: [],
        selection_reason_summary: []
      },
      enableAnswerPolicyV11: false
    });

    expect(output.reply_type).toBe("factual_with_explanation");
    expect(output.assistant_reply).toContain("Почему это попало в ответ:");
    expect(output.assistant_reply).not.toMatch(/(?:Р.|С.){5,}/u);
    expect(output.assistant_reply).toContain("Проверка выполнена по профилю cross_entity_breakage.");
    expect(output.assistant_reply).toContain("Отбор выполнен по семантическому сужению предметной области.");
  });
});

