import type { Need } from '../../domain/need'
import type { Property } from '../../domain/property'
import type { ScoreFactor, TradeOff, Risk, MissingDataItem } from '../../domain/match'
import { ResultType, AvailabilityStatus } from '../../domain/enums'
import { RiskLevel } from '../../domain/enums'

// ── Trade-Off Detection ───────────────────────────────────────────────────────

export function analyzeTradeOffs(
  hardFactors: ScoreFactor[],
  softFactors: ScoreFactor[],
  need: Need,
  property: Property,
): TradeOff[] {
  const tradeOffs: TradeOff[] = []
  const byKey = (factors: ScoreFactor[], key: string) => factors.find(f => f.criterion === key)

  const location = byKey(hardFactors, 'location')
  const budget   = byKey(hardFactors, 'budget')
  const area     = byKey(hardFactors, 'area')
  const timing   = byKey(hardFactors, 'timing')
  const prestige = byKey(softFactors, 'prestige')
  const flex     = byKey(softFactors, 'flexibility')
  const access   = byKey(softFactors, 'accessibility')

  // Prime location at budget premium
  if (location && budget && location.score >= 85 && budget.score < 60) {
    tradeOffs.push({
      criterion: 'location-vs-budget',
      concern: `Erstklassiger Standort (${property.location.city}) zu erhöhten Mietkosten`,
      severity: budget.score < 40 ? 'HIGH' : 'MEDIUM',
      mitigation: 'Nebenkosten analysieren; längere Laufzeit für Konditionenverhandlung nutzen',
      impactOnScore: -Math.round((100 - budget.score) * budget.weight * 10),
    })
  }

  // Large space but poor budget fit
  if (area && budget && area.score >= 80 && budget.score < 55) {
    tradeOffs.push({
      criterion: 'area-vs-budget',
      concern: 'Grosszügige Fläche übersteigt Budget — Teiluntermiete denkbar',
      severity: 'MEDIUM',
      mitigation: 'Möglichkeit für Untermiete oder Co-Working prüfen',
      impactOnScore: -5,
    })
  }

  // Good timing but low data quality
  if (timing && timing.score >= 80 && (property.dataQuality?.score ?? 1) < 0.55) {
    tradeOffs.push({
      criterion: 'timing-vs-dataQuality',
      concern: 'Verfügbarkeit stimmt, Datenbasis ist aber noch unvollständig',
      severity: 'MEDIUM',
      mitigation: 'Objektdaten vor Zusage direkt beim Vermieter verifizieren',
      impactOnScore: -8,
    })
  }

  // High prestige but low flexibility
  if (prestige && flex && prestige.score >= 75 && flex.score < 40) {
    tradeOffs.push({
      criterion: 'prestige-vs-flexibility',
      concern: 'Repräsentative Lage mit eingeschränkter Vertragsflexibilität',
      severity: 'LOW',
      mitigation: 'Breakclause-Option in Verhandlung einfordern',
      impactOnScore: -4,
    })
  }

  // Future signal with good location
  if (property.resultType === ResultType.FUTURE_AVAILABILITY && location && location.score >= 85) {
    tradeOffs.push({
      criterion: 'futureSignal-vs-location',
      concern: 'Sehr guter Standort, aber Verfügbarkeit noch unbestätigt',
      severity: 'HIGH',
      mitigation: 'Frühzeitig Kontakt mit Eigentümer aufnehmen; Letter of Intent erwägen',
      impactOnScore: -12,
    })
  }

  // Good accessibility but poor public transport
  if (access && access.score < 40 && need.softFactors?.maxPublicTransportMinutes !== undefined) {
    tradeOffs.push({
      criterion: 'accessibility-vs-commute',
      concern: 'Erreichbarkeit unter Ihren Anforderungen — Pendlererfahrung beeinträchtigt',
      severity: 'MEDIUM',
      mitigation: 'Shuttle-Service oder Mobility-Angebot als Kompensation anfragen',
      impactOnScore: -6,
    })
  }

  return tradeOffs
}

// ── Risk Analysis ─────────────────────────────────────────────────────────────

export function analyzeRisks(property: Property, hardFactors: ScoreFactor[]): Risk[] {
  const risks: Risk[] = []
  const byKey = (key: string) => hardFactors.find(f => f.criterion === key)

  // Future availability risk — always flag
  if (property.resultType === ResultType.FUTURE_AVAILABILITY) {
    risks.push({
      category: 'Verfügbarkeit',
      description: 'Zukünftiges Signal — Verfügbarkeit ist nicht bestätigt und kann sich verschieben oder entfallen',
      level: RiskLevel.HIGH,
      mitigation: 'Absichtserklärung einholen; alternative Objekte parallel prüfen',
    })
  }

  // Data quality risk
  const dq = property.dataQuality?.score ?? 0.5
  if (dq < 0.55) {
    risks.push({
      category: 'Datenqualität',
      description: `Datenqualität ${Math.round(dq * 100)}% — Angaben unvollständig oder nicht verifiziert`,
      level: dq < 0.40 ? RiskLevel.HIGH : RiskLevel.MEDIUM,
      mitigation: 'Objektdaten direkt beim Anbieter anfordern und validieren',
    })
  }

  // Budget risk
  const budgetFactor = byKey('budget')
  if (budgetFactor && budgetFactor.score < 50) {
    risks.push({
      category: 'Budget',
      description: 'Mietpreis liegt über dem gesetzten Budget — finanzielle Belastung prüfen',
      level: budgetFactor.score < 30 ? RiskLevel.HIGH : RiskLevel.MEDIUM,
      mitigation: 'Vollkostenrechnung inkl. Nebenkosten erstellen; Verhandlungsspielraum ausloten',
    })
  }

  // Occupied / delayed availability
  if (property.availabilityStatus === AvailabilityStatus.OCCUPIED) {
    risks.push({
      category: 'Verfügbarkeit',
      description: 'Objekt aktuell belegt — Übergabetermin unsicher',
      level: RiskLevel.MEDIUM,
      mitigation: 'Verbindlichen Übergabetermin schriftlich vereinbaren',
    })
  }

  // Low confidence score
  if (property.confidenceScore < 0.50) {
    risks.push({
      category: 'Datenverlässlichkeit',
      description: `Konfidenz ${Math.round(property.confidenceScore * 100)}% — Quelldaten unsicher`,
      level: RiskLevel.MEDIUM,
      mitigation: 'Unabhängige Verifikation der Objektangaben empfohlen',
    })
  }

  // Missing critical property data
  const criticalMissing = property.dataQuality?.missingCriticalFields ?? []
  if (criticalMissing.length > 0) {
    risks.push({
      category: 'Fehlende Kerndaten',
      description: `Fehlende Pflichtfelder: ${criticalMissing.slice(0, 3).join(', ')}${criticalMissing.length > 3 ? ` +${criticalMissing.length - 3}` : ''}`,
      level: RiskLevel.MEDIUM,
      mitigation: 'Objektdaten vor Verhandlung vervollständigen lassen',
    })
  }

  return risks
}

// ── Missing Data Detection ────────────────────────────────────────────────────

export function identifyMissingData(property: Property, need: Need): MissingDataItem[] {
  const missing: MissingDataItem[] = []

  if (!property.rentPricePerSqm || property.rentPricePerSqm <= 0) {
    missing.push({
      field: 'rentPricePerSqm',
      importance: 'CRITICAL',
      description: 'Mietpreis fehlt — Budget-Scoring nicht möglich',
      impact: 'Budget-Score wird neutral (50) gesetzt — Gesamtscore unzuverlässig',
    })
  }

  if (!property.availabilityDate || property.availabilityDate === '') {
    missing.push({
      field: 'availabilityDate',
      importance: 'HIGH',
      description: 'Kein Verfügbarkeitsdatum angegeben',
      impact: 'Timing-Score reduziert auf 38/100 — Einzugsfenster nicht prüfbar',
    })
  }

  if (!property.softFactors) {
    missing.push({
      field: 'softFactors',
      importance: 'HIGH',
      description: 'Soft Factors vollständig fehlend (Prestige, Erreichbarkeit, etc.)',
      impact: 'Alle Soft-Factor-Scores auf neutral (50) gesetzt — Matching-Qualität eingeschränkt',
    })
  } else {
    const sf = property.softFactors
    const missingFields: Array<[string, string]> = []
    if (sf.commuterAccessScore === undefined && sf.accessibility === undefined) missingFields.push(['accessibility', 'Erreichbarkeit'])
    if (sf.prestigeScore === undefined && sf.prestige === undefined) missingFields.push(['prestige', 'Prestige-Score'])
    if (sf.esgScore === undefined) missingFields.push(['esgScore', 'ESG-Bewertung'])
    if (missingFields.length > 0) {
      missing.push({
        field: missingFields.map(([k]) => k).join(', '),
        importance: 'MEDIUM',
        description: `Fehlende Soft Factors: ${missingFields.map(([, l]) => l).join(', ')}`,
        impact: 'Betroffene Scores neutral — Matching-Präzision verringert',
      })
    }
  }

  if (!property.hardFacts) {
    missing.push({
      field: 'hardFacts',
      importance: 'MEDIUM',
      description: 'Technische Objektdaten fehlen (Parkierung, ÖV-Score, etc.)',
      impact: 'Infrastruktureignung nicht prüfbar',
    })
  }

  if (need.budgetRange?.maxPerSqm === undefined || need.budgetRange.maxPerSqm <= 0) {
    missing.push({
      field: 'need.budgetRange',
      importance: 'HIGH',
      description: 'Kein Budget im Bedarf angegeben',
      impact: 'Budget-Scoring neutralisiert — Filter unwirksam',
    })
  }

  return missing
}
