/**
 * Constraint Enforcer - Hard Gate vor jedem Draft
 *
 * Stellt sicher, dass die Drafting Engine NIEMALS die deterministische
 * Scope-Engine ueberschreibt. Prueft vor jedem Draft-Vorgang:
 *
 * 1. Ist der Dokumenttyp in requiredDocuments?
 * 2. Passt die Draft-Tiefe zum Level?
 * 3. Ist eine DSFA erforderlich (Hard Trigger)?
 * 4. Werden Risiko-Flags beruecksichtigt?
 */

import type { ScopeDecision, ScopeDocumentType, ComplianceDepthLevel } from '../compliance-scope-types'
import { DOCUMENT_SCOPE_MATRIX_CORE, getDepthLevelNumeric } from '../compliance-scope-types'
import type { ConstraintCheckResult, DraftContext } from './types'

export class ConstraintEnforcer {

  /**
   * Prueft ob ein Draft fuer den gegebenen Dokumenttyp erlaubt ist.
   * Dies ist ein HARD GATE - bei Violation wird der Draft blockiert.
   */
  check(
    documentType: ScopeDocumentType,
    decision: ScopeDecision | null,
    requestedDepthLevel?: ComplianceDepthLevel
  ): ConstraintCheckResult {
    const violations: string[] = []
    const adjustments: string[] = []
    const checkedRules: string[] = []

    // Wenn keine Decision vorhanden: Nur Basis-Drafts erlauben
    if (!decision) {
      checkedRules.push('RULE-NO-DECISION')
      if (documentType !== 'vvt' && documentType !== 'tom' && documentType !== 'dsi') {
        violations.push(
          'Scope-Evaluierung fehlt. Bitte zuerst das Compliance-Profiling durchfuehren.'
        )
      } else {
        adjustments.push(
          'Ohne Scope-Evaluierung wird Level L1 (Basis) angenommen.'
        )
      }
      return {
        allowed: violations.length === 0,
        violations,
        adjustments,
        checkedRules,
      }
    }

    const level = decision.determinedLevel
    const levelNumeric = getDepthLevelNumeric(level)

    // -----------------------------------------------------------------------
    // Rule 1: Dokumenttyp in requiredDocuments?
    // -----------------------------------------------------------------------
    checkedRules.push('RULE-DOC-REQUIRED')
    const isRequired = decision.requiredDocuments.some(
      d => d.documentType === documentType && d.requirement === 'mandatory'
    )
    const scopeReq = DOCUMENT_SCOPE_MATRIX_CORE[documentType]?.[level]

    if (!isRequired && scopeReq && !scopeReq.required) {
      // Nicht blockieren, aber warnen
      adjustments.push(
        `Dokument "${documentType}" ist auf Level ${level} nicht als Pflicht eingestuft. ` +
        `Entwurf ist moeglich, aber optional.`
      )
    }

    // -----------------------------------------------------------------------
    // Rule 2: Draft-Tiefe passt zum Level?
    // -----------------------------------------------------------------------
    checkedRules.push('RULE-DEPTH-MATCH')
    if (requestedDepthLevel) {
      const requestedNumeric = getDepthLevelNumeric(requestedDepthLevel)

      if (requestedNumeric > levelNumeric) {
        violations.push(
          `Angefragte Tiefe ${requestedDepthLevel} ueberschreitet das bestimmte Level ${level}. ` +
          `Die Scope-Engine hat Level ${level} festgelegt. ` +
          `Ein Draft mit Tiefe ${requestedDepthLevel} ist nicht erlaubt.`
        )
      } else if (requestedNumeric < levelNumeric) {
        adjustments.push(
          `Angefragte Tiefe ${requestedDepthLevel} liegt unter dem bestimmten Level ${level}. ` +
          `Draft wird auf Level ${level} angehoben.`
        )
      }
    }

    // -----------------------------------------------------------------------
    // Rule 3: DSFA-Enforcement
    // -----------------------------------------------------------------------
    checkedRules.push('RULE-DSFA-ENFORCEMENT')
    if (documentType === 'dsfa') {
      const dsfaRequired = decision.triggeredHardTriggers.some(
        t => t.requiresDSFA
      )

      if (!dsfaRequired && level !== 'L4') {
        adjustments.push(
          'DSFA ist laut Scope-Engine nicht verpflichtend. ' +
          'Entwurf wird als freiwillige Massnahme gekennzeichnet.'
        )
      }
    }

    // Umgekehrt: Wenn DSFA verpflichtend und Typ != dsfa, ggf. hinweisen
    if (documentType !== 'dsfa') {
      const dsfaRequired = decision.triggeredHardTriggers.some(
        t => t.requiresDSFA
      )
      const dsfaInRequired = decision.requiredDocuments.some(
        d => d.documentType === 'dsfa' && d.requirement === 'mandatory'
      )

      if (dsfaRequired && dsfaInRequired) {
        // Nur ein Hinweis, kein Block
        adjustments.push(
          'Hinweis: Eine DSFA ist laut Scope-Engine verpflichtend. ' +
          'Bitte sicherstellen, dass auch eine DSFA erstellt wird.'
        )
      }
    }

    // -----------------------------------------------------------------------
    // Rule 4: Risiko-Flags beruecksichtigt?
    // -----------------------------------------------------------------------
    checkedRules.push('RULE-RISK-FLAGS')
    const criticalRisks = decision.riskFlags.filter(
      f => f.severity === 'CRITICAL' || f.severity === 'HIGH'
    )

    if (criticalRisks.length > 0) {
      adjustments.push(
        `${criticalRisks.length} kritische/hohe Risiko-Flags erkannt. ` +
        `Draft muss diese adressieren: ${criticalRisks.map(r => r.message).join(', ')}`
      )
    }

    // -----------------------------------------------------------------------
    // Rule 5: Hard-Trigger Consistency
    // -----------------------------------------------------------------------
    checkedRules.push('RULE-HARD-TRIGGER-CONSISTENCY')
    for (const trigger of decision.triggeredHardTriggers) {
      const mandatoryDocs = trigger.mandatoryDocuments
      if (mandatoryDocs.includes(documentType)) {
        // Gut - wir erstellen ein mandatory document
      } else {
        // Pruefen ob die mandatory documents des Triggers vorhanden sind
        // (nur Hinweis, kein Block)
      }
    }

    return {
      allowed: violations.length === 0,
      violations,
      adjustments,
      checkedRules,
    }
  }

  /**
   * Convenience: Prueft aus einem DraftContext heraus.
   */
  checkFromContext(
    documentType: ScopeDocumentType,
    context: DraftContext
  ): ConstraintCheckResult {
    // Reconstruct a minimal ScopeDecision from context
    const pseudoDecision: ScopeDecision = {
      id: 'projected',
      determinedLevel: context.decisions.level,
      scores: context.decisions.scores,
      triggeredHardTriggers: context.decisions.hardTriggers.map(t => ({
        ruleId: t.id,
        category: '',
        description: t.label,
        legalReference: t.legalReference,
        minimumLevel: context.decisions.level,
        requiresDSFA: false,
        mandatoryDocuments: [],
        matchedValue: null,
        explanation: '',
      })),
      requiredDocuments: context.decisions.requiredDocuments.map(d => ({
        documentType: d.documentType,
        label: d.documentType,
        requirement: 'mandatory' as const,
        priority: 'medium' as const,
        estimatedEffort: 0,
        triggeredBy: [],
      })),
      riskFlags: context.constraints.riskFlags.map(f => ({
        severity: f.severity,
        category: '',
        message: f.title,
        recommendation: f.recommendation,
      })),
      gaps: [],
      nextActions: [],
      reasoning: [],
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
    }

    return this.check(documentType, pseudoDecision)
  }
}

/** Singleton-Instanz */
export const constraintEnforcer = new ConstraintEnforcer()
