import { MockupPropertyProvider } from '../provider/MockupPropertyProvider'
import { FreshnessStatus } from '../domain/enums'
import type { DataQualitySummary } from '../domain/dashboard'
import type { DataQuality, Property } from '../domain/property'

export type RecommendedAction = {
  id: string
  label: string
  detail: string
  priority: 'HIGH' | 'MEDIUM' | 'LOW'
  field?: string
}

// ── Field → Action map ────────────────────────────────────────────────────────

const FIELD_ACTION_MAP: Record<string, Omit<RecommendedAction, 'id'>> = {
  'Mietpreis/m²':      { label: 'Mietpreis ergänzen',          detail: 'Fehlender Mietpreis schließt Objekt aus Budget-Matches aus', priority: 'HIGH',   field: 'Mietpreis/m²' },
  'Fläche m²':         { label: 'Fläche bestätigen',           detail: 'Fläche ist Hard-Kriterium für alle Matchings',               priority: 'HIGH',   field: 'Fläche m²' },
  'Verfügbarkeit':     { label: 'Verfügbarkeit bestätigen',    detail: 'Timing ist entscheidend für Nachfrager mit Deadlines',       priority: 'HIGH',   field: 'Verfügbarkeit' },
  'Adresse':           { label: 'Adresse vervollständigen',    detail: 'Für Standortbewertung und Kartenansicht notwendig',          priority: 'HIGH',   field: 'Adresse' },
  'Beschreibung':      { label: 'Beschreibung hinzufügen',     detail: 'Verbesserter Kontext erhöht Nachfrager-Vertrauen',           priority: 'MEDIUM', field: 'Beschreibung' },
  'Soft Factors':      { label: 'Passantenfrequenz & ESG',     detail: 'Soft Factors verbessern Match-Scoring erheblich',            priority: 'MEDIUM', field: 'Soft Factors' },
  'Ausbaustandard':    { label: 'Ausbaustandard angeben',      detail: 'SHELL/BASIC/FULL/PREMIUM beeinflusst Eignung stark',        priority: 'MEDIUM', field: 'Ausbaustandard' },
  'Bilder':            { label: 'Bilder hochladen',            detail: 'Objektfotos steigern Anfragerate deutlich',                  priority: 'MEDIUM', field: 'Bilder' },
  'Jahresmiete (CHF)': { label: 'Jahresmiete angeben',         detail: 'Ergänzt Mietpreis/m² für Budgetvergleiche',                 priority: 'LOW',    field: 'Jahresmiete (CHF)' },
  'Expansionspotenzial': { label: 'Erweiterungsfläche angeben', detail: 'Wichtig für wachsende Unternehmen',                       priority: 'LOW',    field: 'Expansionspotenzial' },
}

const FRESHNESS_ACTIONS: Record<string, RecommendedAction> = {
  [FreshnessStatus.OUTDATED]: {
    id: 'review_source',
    label: 'Quelle überprüfen',
    detail: 'Daten sind älter als 14 Tage — Verfügbarkeit könnte sich geändert haben',
    priority: 'HIGH',
  },
  [FreshnessStatus.STALE]: {
    id: 'update_data',
    label: 'Daten aktualisieren',
    detail: 'Daten sind 2–14 Tage alt — Aktualitätsscore reduziert',
    priority: 'MEDIUM',
  },
}

// ── Core Checks ───────────────────────────────────────────────────────────────

const CRITICAL_CHECKS: Array<{ field: string; present: (p: Property) => boolean }> = [
  { field: 'Mietpreis/m²',  present: p => p.rentPricePerSqm > 0 },
  { field: 'Fläche m²',     present: p => p.areaSqm > 0 },
  { field: 'Verfügbarkeit', present: p => !!p.availabilityDate },
  { field: 'Adresse',       present: p => !!p.address?.street && !!p.address?.city },
]

const OPTIONAL_CHECKS: Array<{ field: string; present: (p: Property) => boolean }> = [
  { field: 'Beschreibung',      present: p => !!p.description && p.description.length > 20 },
  { field: 'Soft Factors',      present: p => !!(p.softFactors?.prestigeScore || p.softFactors?.footfallScore || p.softFactors?.commuterAccessScore) },
  { field: 'Ausbaustandard',    present: p => !!p.hardFacts?.fitOut },
  { field: 'Bilder',            present: p => (p.images?.length ?? 0) > 0 },
  { field: 'Jahresmiete (CHF)', present: p => !!p.rentChfSqmYear },
  { field: 'Expansionspotenzial', present: p => !!(p.expansionPotentialSqm || p.hardFacts) },
]

// ── Public API ────────────────────────────────────────────────────────────────

export function getMissingCriticalFields(property: Property): string[] {
  const fromData = property.dataQuality?.missingCriticalFields ?? []
  if (fromData.length > 0) return fromData
  return CRITICAL_CHECKS.filter(c => !c.present(property)).map(c => c.field)
}

export function getQualityWarnings(property: Property): string[] {
  return property.dataQuality?.warnings ?? []
}

export function getRecommendedActions(quality: DataQuality, freshness?: string): RecommendedAction[] {
  const actions: RecommendedAction[] = []

  for (const field of quality.missingCriticalFields) {
    const def = FIELD_ACTION_MAP[field]
    if (def) actions.push({ id: `fill_${field}`, ...def })
  }

  const fn = freshness ?? quality.freshness
  if (fn && fn !== FreshnessStatus.FRESH) {
    const freshnessAction = FRESHNESS_ACTIONS[fn]
    if (freshnessAction) actions.push(freshnessAction)
  }

  for (const field of quality.missingOptionalFields) {
    const def = FIELD_ACTION_MAP[field]
    if (def) actions.push({ id: `fill_opt_${field}`, ...def })
  }

  return actions
}

export function calculatePropertyQuality(property: Property): DataQuality {
  if (property.dataQuality?.qualityLevel) return property.dataQuality

  const missingCritical = CRITICAL_CHECKS.filter(c => !c.present(property)).map(c => c.field)
  const missingOptional = OPTIONAL_CHECKS.filter(c => !c.present(property)).map(c => c.field)

  const completeness = 1 - (missingCritical.length * 0.15 + missingOptional.length * 0.05)
  const confidence = property.confidenceScore ?? 0.5

  const freshnessVal = property.dataQuality?.freshness ?? FreshnessStatus.OUTDATED
  const freshnessFactor = freshnessVal === FreshnessStatus.FRESH ? 1 : freshnessVal === FreshnessStatus.STALE ? 0.7 : 0.4

  const score = Math.min(1, Math.max(0, completeness * 0.5 + confidence * 0.3 + freshnessFactor * 0.2))

  const warnings: string[] = []
  if (confidence < 0.5) warnings.push('Niedrige Daten-Vertrauensscore')
  if (freshnessVal === FreshnessStatus.OUTDATED) warnings.push('Daten sind veraltet (>14 Tage)')
  if (missingCritical.length > 0) warnings.push(`${missingCritical.length} Pflichtfeld(er) fehlen`)

  const qualityLevel = missingCritical.length > 0
    ? 'INCOMPLETE'
    : score >= 0.8 ? 'HIGH' : score >= 0.6 ? 'MEDIUM' : 'LOW'

  return {
    score,
    qualityLevel,
    missingCriticalFields: missingCritical,
    missingOptionalFields: missingOptional,
    lastVerifiedAt: property.dataQuality?.lastVerifiedAt,
    freshness: freshnessVal,
    warnings,
  }
}

// ── Portfolio summary (existing) ──────────────────────────────────────────────

export const dataQualityService = {
  async getPortfolioQualitySummary(): Promise<DataQualitySummary> {
    const properties = await MockupPropertyProvider.getAll()

    const avgScoreRaw =
      properties.length > 0
        ? properties.reduce((sum, p) => sum + (p.dataQuality?.score ?? 0), 0) / properties.length
        : 0

    const fieldCounts = properties
      .flatMap(p => p.dataQuality?.missingCriticalFields ?? [])
      .reduce<Record<string, number>>((acc, f) => {
        acc[f] = (acc[f] ?? 0) + 1
        return acc
      }, {})

    const topMissingFields = Object.entries(fieldCounts)
      .sort((a, b) => b[1] - a[1])
      .slice(0, 5)
      .map(([f]) => f)

    return {
      avgScore: Math.round(avgScoreRaw * 100),
      critical: properties.filter(p => (p.dataQuality?.score ?? 0) < 0.5).length,
      propertiesWithMissingCritical: properties.filter(
        p => (p.dataQuality?.missingCriticalFields?.length ?? 0) > 0,
      ).length,
      topMissingFields,
    }
  },

  getMissingCriticalFields,
  getQualityWarnings,
  getRecommendedActions,
  calculatePropertyQuality,
}
