import type { Need } from '../../domain/need'
import type { Property } from '../../domain/property'
import type { Match, NextBestAction, ScoreBreakdown } from '../../domain/match'
import { MatchStrength, RiskLevel, ResultType, ConfidenceLevel } from '../../domain/enums'
import type { MatchEngineOutput } from '../../domain/scoring'
import { calculateScore } from './scoreCalculator'

// ── Strength + Risk Classification ───────────────────────────────────────────

export function matchStrengthFromScore(score: number): typeof MatchStrength[keyof typeof MatchStrength] {
  if (score >= 78) return MatchStrength.STRONG
  if (score >= 52) return MatchStrength.MODERATE
  return MatchStrength.WEAK
}

function riskLevelFromRisks(risks: Match['risks']): typeof RiskLevel[keyof typeof RiskLevel] {
  if (!risks || risks.length === 0) return RiskLevel.LOW
  const levels = risks.map(r => r.level)
  if (levels.includes(RiskLevel.CRITICAL)) return RiskLevel.CRITICAL
  if (levels.includes(RiskLevel.HIGH)) return RiskLevel.HIGH
  if (levels.includes(RiskLevel.MEDIUM)) return RiskLevel.MEDIUM
  return RiskLevel.LOW
}

function confidenceLabelFromScore(score: number): typeof ConfidenceLevel[keyof typeof ConfidenceLevel] {
  if (score >= 0.90) return ConfidenceLevel.VERY_HIGH
  if (score >= 0.75) return ConfidenceLevel.HIGH
  if (score >= 0.55) return ConfidenceLevel.MEDIUM
  if (score >= 0.35) return ConfidenceLevel.LOW
  return ConfidenceLevel.VERY_LOW
}

// ── Next Best Action Generator ────────────────────────────────────────────────

export function generateNextBestActions(
  output: MatchEngineOutput,
  property: Property,
  _need: Need,
): NextBestAction[] {
  const actions: NextBestAction[] = []

  if (output.excluded) {
    actions.push({
      label: 'Kriterien überprüfen',
      description: `Ausschlussgrund: ${output.excludedReason}`,
      priority: 'HIGH',
      actionType: 'REVIEW',
    })
    return actions
  }

  const score = output.finalScore

  if (score >= 78) {
    actions.push({
      label: 'Shortlist hinzufügen',
      description: 'Starkes Match — sofort zur Shortlist hinzufügen',
      priority: 'HIGH',
      actionType: 'SHORTLIST',
    })
    actions.push({
      label: 'Besichtigung anfragen',
      description: 'Dieses Objekt zeitnah besichtigen',
      priority: 'HIGH',
      actionType: 'CONTACT',
    })
  } else if (score >= 52) {
    actions.push({
      label: 'Details verifizieren',
      description: 'Mittleres Match — kritische Datenpunkte direkt bestätigen',
      priority: 'MEDIUM',
      actionType: 'VERIFY',
    })
    actions.push({
      label: 'Mit Alternativen vergleichen',
      description: 'Dieses Objekt mit anderen Matches vergleichen',
      priority: 'MEDIUM',
      actionType: 'COMPARE',
    })
  } else {
    actions.push({
      label: 'Manuell prüfen',
      description: 'Schwaches Match — Eignung manuell beurteilen',
      priority: 'LOW',
      actionType: 'REVIEW',
    })
  }

  if (property.resultType === ResultType.FUTURE_AVAILABILITY) {
    actions.push({
      label: 'Frühzeitig vormerken',
      description: 'Verfügbarkeit unbestätigt — Signal im Auge behalten',
      priority: 'MEDIUM',
      actionType: 'SCHEDULE',
    })
  }

  if (output.missingData.some(m => m.importance === 'CRITICAL' || m.importance === 'HIGH')) {
    actions.push({
      label: 'Fehlende Daten anfordern',
      description: 'Objektdaten für vollständige Bewertung vervollständigen',
      priority: 'HIGH',
      actionType: 'VERIFY',
    })
  }

  return actions.slice(0, 4)  // cap at 4 actions
}

// ── Build Full Match Entity ───────────────────────────────────────────────────

export function buildFullMatch(need: Need, property: Property): Match {
  const output = calculateScore(need, property)
  const now = new Date().toISOString()

  const scoreBreakdown: ScoreBreakdown = {
    hardMatchScore:      output.hardMatchScore,
    softFactorScore:     output.softFactorScore,
    confidenceModifier:  output.confidenceModifier,
    dataQualityModifier: output.dataQualityModifier,
    totalScore:          output.finalScore,
  }

  const matchScore    = output.finalScore
  const matchStrength = matchStrengthFromScore(matchScore)
  const riskLevel     = riskLevelFromRisks(output.risks)
  const confidenceLevel = property.confidenceScore

  const summary = buildExplainabilitySummary(output, property, matchScore, matchStrength)

  const uncertaintyIndicators: string[] = []
  if (property.resultType === ResultType.FUTURE_AVAILABILITY) uncertaintyIndicators.push('Zukünftiges Signal — nicht bestätigt')
  if (property.confidenceScore < 0.60) uncertaintyIndicators.push(`Niedrige Konfidenz (${Math.round(property.confidenceScore * 100)}%)`)
  if ((property.dataQuality?.score ?? 1) < 0.55) uncertaintyIndicators.push('Unvollständige Datenbasis')
  if (output.missingData.some(m => m.importance === 'CRITICAL')) uncertaintyIndicators.push('Kritische Daten fehlen')

  return {
    id:          `match-${need.id}-${property.id}`,
    needId:      need.id,
    propertyId:  property.id,
    resultId:    property.id,
    resultType:  property.resultType,

    matchScore,
    matchStrength,
    scoreBreakdown,
    confidenceLevel,
    confidenceLevelLabel: confidenceLabelFromScore(confidenceLevel),
    dataConfidenceScore: property.dataQuality?.score,

    positiveFactors:   output.positiveFactors,
    negativeFactors:   output.negativeFactors,
    tradeoffs:         output.tradeOffs,
    tradeOffs:         output.tradeOffs,
    risks:             output.risks,
    missingData:       output.missingData,
    nextBestActions:   output.nextBestActions,
    explainabilitySummary: summary,

    riskLevel,
    uncertaintyIndicators,

    status:    undefined,
    createdAt: now,
    updatedAt: now,
  }
}

function buildExplainabilitySummary(
  output: MatchEngineOutput,
  property: Property,
  score: number,
  strength: string,
): string {
  if (output.excluded) {
    return `Ausgeschlossen: ${output.excludedReason}`
  }
  const top = output.positiveFactors[0]
  const bottom = output.negativeFactors[0]
  const futureNote = property.resultType === ResultType.FUTURE_AVAILABILITY
    ? ' (Verfügbarkeit unbestätigt)'
    : ''
  const positive = top ? ` Stärke: ${top.explanation}.` : ''
  const negative = bottom ? ` Schwäche: ${bottom.explanation}.` : ''
  return `${strength}-Match mit ${score} Punkten${futureNote}.${positive}${negative}`
}

// ── Ranking ───────────────────────────────────────────────────────────────────

export function rankMatches(matches: Match[]): Match[] {
  return [...matches].sort((a, b) => {
    // Primary: matchScore descending
    if (b.matchScore !== a.matchScore) return b.matchScore - a.matchScore
    // Secondary: VERIFIED / MAISON_WORK > FUTURE
    const typeOrder: Record<string, number> = { VERIFIED_PORTFOLIO: 0, MAISON_WORK: 0, FUTURE_AVAILABILITY: 2 }
    const aOrder = typeOrder[a.resultType ?? 'VERIFIED_PORTFOLIO'] ?? 0
    const bOrder = typeOrder[b.resultType ?? 'VERIFIED_PORTFOLIO'] ?? 0
    if (aOrder !== bOrder) return aOrder - bOrder
    // Tertiary: higher confidence first
    return (b.confidenceLevel ?? 0) - (a.confidenceLevel ?? 0)
  })
}

// ── Batch computation ─────────────────────────────────────────────────────────

export function computeRankedMatches(need: Need, properties: Property[]): Match[] {
  const matches = properties
    .map(p => buildFullMatch(need, p))
    .filter(m => !m.matchScore || m.matchScore > 0)  // exclude hard-filtered
  return rankMatches(matches)
}
