import type {
  UnifiedMatchResult,
  VerifiedPortfolioResult,
  ExternalMarketResult,
  FutureAvailabilityResult,
} from '../../domain/unifiedResult'
import type { ScoreFactor } from '../../domain/match'
import type {
  MatchCardViewModel,
  MatchCardAction,
  MatchCardReason,
} from '../../components/match-card/MatchCardViewModel'
import { getCityIntelligence } from '../../lib/locationIntelligence'
import { formatUnitTitle, formatMultiUnitFloors } from '../../domain/unit'

const HARD_CRITERIA = new Set(['area', 'location', 'budget', 'timing'])

function buildReasons(positiveFactors: ScoreFactor[]): MatchCardReason[] {
  return positiveFactors.slice(0, 3).map(f => ({
    type: (HARD_CRITERIA.has(f.criterion) ? 'HARD_FACT' : 'SOFT_FACTOR') as MatchCardReason['type'],
    label: capitalize(f.criterion),
    explanation: f.explanation,
    score: f.score,
  }))
}

function capitalize(s: string): string {
  return s.charAt(0).toUpperCase() + s.slice(1)
}

export function buildMatchCardViewModel(
  result: UnifiedMatchResult,
  actions: MatchCardAction[],
): MatchCardViewModel {
  const { match, matchScore, resultType } = result

  const isFuture = resultType === 'FUTURE_AVAILABILITY'
  const property = !isFuture
    ? (result as VerifiedPortfolioResult | ExternalMarketResult).property
    : (result as FutureAvailabilityResult).property
  const signal = isFuture
    ? (result as FutureAvailabilityResult).signal
    : undefined
  const unit = isFuture
    ? (result as FutureAvailabilityResult).unit
    : (result as VerifiedPortfolioResult | ExternalMarketResult).unit

  const city = property?.location?.city
  const district = property?.location?.district
  const locationLabel = city
    ? `${city}${district ? `, ${district}` : ''}`
    : signal?.locationHint ?? '–'

  // Unit-first title: specific unit → floor range of all units → signal → property
  let cardTitle: string
  let propertySubtitle: string | undefined

  if (unit && property?.address) {
    cardTitle = formatUnitTitle(unit, property.address)
    propertySubtitle = property.title
  } else if (signal?.title) {
    cardTitle = signal.title
  } else if (property?.units && property.units.length > 0 && property.address) {
    const floorRange = formatMultiUnitFloors(property.units)
    cardTitle = `${floorRange} · ${property.address.street} ${property.address.houseNumber}`
    propertySubtitle = property.title
  } else {
    cardTitle = property?.title ?? signal?.companyName ?? signal?.locationHint ?? '–'
  }

  const availabilityLabel =
    property?.availabilityDate ??
    (signal?.timeHorizonMonths ? `~${signal.timeHorizonMonths} Monate` : undefined)

  const sourceLabel =
    property?.sourceLabel ??
    property?.sourceMeta?.sourceLabel ??
    property?.sourceMeta?.sourceType

  const externalUrl = property?.sourceUrl ?? property?.sourceMeta?.sourceUrl

  const reasons = buildReasons(match.positiveFactors)

  const cityIntel = city ? getCityIntelligence(city) : null
  const taxCalculatorUrl = cityIntel?.taxCalculatorUrl

  const dataQualityScore =
    property?.dataQuality?.score ?? signal?.confidenceScore ?? 0.5

  return {
    id: result.matchId,
    title: cardTitle,
    propertySubtitle,
    resultType,
    assetType: property?.assetType,
    matchScore,
    confidenceScore: match.confidenceLevel,
    dataQualityScore,
    locationLabel,
    availabilityLabel,
    sourceLabel,
    externalUrl,
    reasons,
    tradeoffs: match.tradeoffs ?? [],
    risks: match.risks ?? [],
    missingData: match.missingData ?? [],
    actions,
    disclaimer: isFuture
      ? (signal?.disclaimer ?? 'Probabilistisches Signal – kein bestätigtes Objekt')
      : undefined,
    explainabilitySummary: match.explainabilitySummary,
    taxCalculatorUrl,
    isReviewRequired: match.status === 'PENDING_REVIEW',
    isStaleData: false,
    // Schattenmarkt signal fields
    signalSourceType: signal?.source?.type,
    signalSourceUrl: signal?.source?.url,
    signalSourceCredibility: signal?.source?.credibility,
    signalProbability: signal?.probability,
    signalMarketIndicator: signal?.marketIndicator,
    signalType: signal?.signalType,
    signalIsVerified: signal?.isVerified,
    aiSignalSummary: signal?.aiSummary,
    signalQuality: (() => {
      if (!signal) return undefined
      if (signal.isVerified || signal.probability >= 0.70) return 'HIGH'
      if (signal.probability >= 0.50) return 'MEDIUM'
      return 'LOW'
    })(),
    signalIsControlled: signal?.signalType === 'LEASE_EXPIRY' && signal?.isVerified === true,
    signalMarketIndicators: signal?.marketIndicators,
    signalStrategicInterpretation: signal?.strategicInterpretation,
    signalConfirmedFacts: signal?.confirmedFacts,
    signalUnconfirmedFacts: signal?.unconfirmedFacts,
    signalAreaSqmEstimate: signal?.areaSqmEstimate,
    propertyId: property?.id ?? signal?.propertyId,
    unitId: match.unitId ?? unit?.id ?? signal?.unitId,
    preMarketUnit: unit,
    preMarketAllUnits: property?.units,
    scoreBreakdown: {
      hardMatchScore: match.scoreBreakdown.hardMatchScore,
      softFactorScore: match.scoreBreakdown.softFactorScore,
      totalScore: match.scoreBreakdown.totalScore,
    },
    allFactors: match.allFactors,
  }
}
