import type { ItemResponse, ServiceError } from './types'
import { ServiceErrorCode } from './types'
import type { CreateNeedInput } from '../domain/need'
import type { AssetType } from '../domain/enums'
import type { ParseNeedResult, ParsedNeedCriteria, FollowUpQuestion } from '../domain/needBuilder'
import type { UnifiedMatchResult } from '../domain/unifiedResult'

// ── Decision Brief ────────────────────────────────────────────────────────────

export interface DecisionBrief {
  id: string
  shortlistId: string
  summary: string
  sections: { title: string; body: string }[]
  generatedAt: string
  isDraft: true
}

function buildMockDecisionBrief(shortlistId: string): DecisionBrief {
  return {
    id: crypto.randomUUID(),
    shortlistId,
    summary: 'Die Shortlist enthält qualitativ hochwertige Matches mit starker Standortübereinstimmung. Die verfügbaren Flächen decken den Bedarf gut ab. Zwei Objekte eignen sich als Erstbesichtigungen.',
    sections: [
      {
        title: 'Zusammenfassung der Objekte',
        body: 'Die Shortlist umfasst mehrere Objekte aus dem verifizierten Portfolio. Die Matchscores liegen zwischen 74 und 88, was auf eine gute bis sehr gute Übereinstimmung mit den Suchkriterien hinweist.',
      },
      {
        title: 'Standortbewertung',
        body: 'Die Mehrheit der Objekte befindet sich in bevorzugten Lagen. Die ÖV-Anbindung ist bei allen Objekten als gut bis sehr gut einzustufen.',
      },
      {
        title: 'Budgetanalyse',
        body: 'Die Mietpreise liegen im budgetkonformen Bereich. Keine der Optionen überschreitet das maximale Budget pro m².',
      },
      {
        title: 'Empfohlene nächste Schritte',
        body: '1. Besichtigung der Top-2-Objekte vereinbaren. 2. Detaillierte Flächenpläne anfordern. 3. Vertragskonditionen prüfen lassen.',
      },
    ],
    generatedAt: new Date().toISOString(),
    isDraft: true,
  }
}

// ── Compare Summary ───────────────────────────────────────────────────────────

export interface ComparisonSummary {
  strongestOption: { matchId: string; label: string; reason: string }
  bestValue: { matchId: string; label: string; reason: string } | null
  highestConfidence: { matchId: string; label: string; confidenceLevel: number }
  biggestTradeoffs: string[]
  missingDataWarnings: string[]
  recommendedNextStep: string
}

function buildComparisonSummary(items: UnifiedMatchResult[]): ComparisonSummary {
  if (items.length === 0) {
    return {
      strongestOption: { matchId: '', label: '–', reason: 'Keine Ergebnisse' },
      bestValue: null,
      highestConfidence: { matchId: '', label: '–', confidenceLevel: 0 },
      biggestTradeoffs: [],
      missingDataWarnings: [],
      recommendedNextStep: 'Suchergebnisse überprüfen',
    }
  }

  const getTitle = (item: UnifiedMatchResult) =>
    item.resultType !== 'FUTURE_AVAILABILITY'
      ? (item as any).property?.title ?? `Match ${item.matchScore}`
      : (item as any).signal?.companyName ?? 'Zukunftssignal'

  const strongest = items.reduce((a, b) => a.matchScore > b.matchScore ? a : b)

  const propertyItems = items.filter(i => i.resultType !== 'FUTURE_AVAILABILITY')
  const bestValue = propertyItems.length > 0
    ? propertyItems.reduce((a, b) =>
        ((a as any).property?.rentPricePerSqm ?? Infinity) <= ((b as any).property?.rentPricePerSqm ?? Infinity) ? a : b
      )
    : null

  const highestConf = items.reduce((a, b) =>
    a.match.confidenceLevel >= b.match.confidenceLevel ? a : b
  )

  const tradeoffs = items
    .flatMap(i => i.match.tradeoffs?.slice(0, 1).map(t => `${getTitle(i)}: ${t.concern}`) ?? [])
    .slice(0, 3)

  const missingWarnings = items
    .filter(i => (i.match.missingData?.filter(m => m.importance === 'CRITICAL').length ?? 0) > 0)
    .map(i => `${getTitle(i)}: fehlende Pflichtfelder`)

  const topNextAction = strongest.match.nextBestActions?.[0]?.label ?? 'Objekt besichtigen oder Details prüfen'

  return {
    strongestOption: {
      matchId: strongest.matchId,
      label: getTitle(strongest),
      reason: `Höchster Match Score (${strongest.matchScore}/100)`,
    },
    bestValue: bestValue
      ? {
          matchId: bestValue.matchId,
          label: getTitle(bestValue),
          reason: `Niedrigster Mietpreis (CHF ${(bestValue as any).property?.rentPricePerSqm ?? '–'}/m²)`,
        }
      : null,
    highestConfidence: {
      matchId: highestConf.matchId,
      label: getTitle(highestConf),
      confidenceLevel: highestConf.match.confidenceLevel,
    },
    biggestTradeoffs: tradeoffs,
    missingDataWarnings: missingWarnings,
    recommendedNextStep: topNextAction,
  }
}

// ── Legacy types (kept for backward compatibility) ────────────────────────────

export interface CriteriaExtractionResult {
  extractedCriteria: Partial<CreateNeedInput>
  confidence: number
  missingFields: string[]
  assumptions: string[]
  followUpQuestions: string[]
}

export interface AIServiceProvider {
  extractCriteria(naturalLanguageInput: string): Promise<CriteriaExtractionResult>
  generateFollowUp(partialNeed: Partial<CreateNeedInput>): Promise<string[]>
}

// ── Mock parse logic ──────────────────────────────────────────────────────────

function mockParseNeed(input: string): ParseNeedResult {
  const lower = input.toLowerCase()

  // Asset type
  const assetType: AssetType | undefined =
    lower.includes('büro') || lower.includes('office') ? 'OFFICE'
    : lower.includes('logistik') || lower.includes('lager') ? 'LOGISTICS'
    : lower.includes('retail') || lower.includes('laden') || lower.includes('shop') ? 'RETAIL'
    : lower.includes('produktion') || lower.includes('gewerbe') || lower.includes('industrie') ? 'PRODUCTION'
    : lower.includes('gastro') || lower.includes('restaurant') ? 'GASTRO'
    : undefined

  // Area
  const areaRangeMatch = input.match(/(\d+)\s*[–\-–]\s*(\d+)\s*m[²2]/i)
  const areaSingleMatch = input.match(/(\d{3,5})\s*m[²2]/i)
  let areaRange: { min: number; max: number } | undefined
  let areaConfidence = 0.25
  if (areaRangeMatch) {
    areaRange = { min: parseInt(areaRangeMatch[1]), max: parseInt(areaRangeMatch[2]) }
    areaConfidence = 0.95
  } else if (areaSingleMatch) {
    const base = parseInt(areaSingleMatch[1])
    areaRange = { min: Math.round(base * 0.8), max: Math.round(base * 1.2) }
    areaConfidence = 0.70
  }

  // Locations
  const CITIES: [string, string][] = [
    ['zürich', 'Zürich'], ['basel', 'Basel'], ['bern', 'Bern'], ['genf', 'Genf'],
    ['lausanne', 'Lausanne'], ['winterthur', 'Winterthur'], ['zug', 'Zug'],
    ['luzern', 'Luzern'], ['st. gallen', 'St. Gallen'], ['lugano', 'Lugano'],
    ['biel', 'Biel'], ['schaffhausen', 'Schaffhausen'],
  ]
  const preferredLocations = CITIES.filter(([k]) => lower.includes(k)).map(([, v]) => v)
  const locationConfidence = preferredLocations.length > 0 ? 0.88 : 0.15

  // Budget
  const budgetPerSqmMatch = input.match(/(\d+)\s*(?:CHF)?\s*\/\s*m[²2]/i)
  const budgetMaxMatch = input.match(/(?:max\.?|bis|höchstens)\s*(?:CHF\s*)?(\d+)/i)
  let budgetRange: { maxPerSqm: number; currency: string } | undefined
  let budgetConfidence = 0.20
  if (budgetPerSqmMatch) {
    budgetRange = { maxPerSqm: parseInt(budgetPerSqmMatch[1]), currency: 'CHF' }
    budgetConfidence = 0.92
  } else if (budgetMaxMatch) {
    budgetRange = { maxPerSqm: parseInt(budgetMaxMatch[1]), currency: 'CHF' }
    budgetConfidence = 0.60
  }

  // Timing
  const yearMatch = input.match(/(?:ab\s+)?(?:Q[1-4]\s*\/?\s*)?(\d{4})/)
  const soonMatch = lower.includes('sofort') || lower.includes('asap')
  let timing: ParsedNeedCriteria['timing'] | undefined
  let timingConfidence = 0.20
  if (soonMatch) {
    timing = { earliestMoveIn: '2025-07-01', latestMoveIn: '2025-10-01', flexibleTiming: false }
    timingConfidence = 0.85
  } else if (yearMatch) {
    timing = { earliestMoveIn: `${yearMatch[1]}-01-01`, latestMoveIn: `${yearMatch[1]}-12-31`, flexibleTiming: lower.includes('flexibel') }
    timingConfidence = 0.75
  }

  // Must-haves
  const mustHaveCriteria: string[] = []
  if (lower.includes('öv') || lower.includes('bahnhof') || lower.includes('tram')) mustHaveCriteria.push('Gute ÖV-Anbindung')
  if (lower.includes('parking') || lower.includes('parkplatz') || lower.includes('tiefgarage')) mustHaveCriteria.push('Parkplätze vorhanden')
  if (lower.includes('klimaanlage') || lower.includes('klima')) mustHaveCriteria.push('Klimaanlage')
  if (lower.includes('server') || lower.includes('rechenzentr')) mustHaveCriteria.push('Serverraum / IT-Infrastruktur')
  if (lower.includes('barrierefrei')) mustHaveCriteria.push('Barrierefreiheit')
  if (lower.includes('küche') || lower.includes('kantine')) mustHaveCriteria.push('Kantine / Küche')

  // Soft
  const prestigeImportance: 'LOW' | 'MEDIUM' | 'HIGH' | undefined =
    lower.includes('prestige') || lower.includes('representativ') || lower.includes('repräsentativ') ? 'HIGH'
    : lower.includes('standard') ? 'LOW'
    : undefined
  const parkingNeed = lower.includes('parking') || lower.includes('parkplatz')
  const visibilityNeed: 'HIGH' | undefined = lower.includes('sichtbar') || lower.includes('passanten') ? 'HIGH' : undefined
  const footfallNeed: 'HIGH' | undefined = lower.includes('frequenz') || lower.includes('laufkundschaft') ? 'HIGH' : undefined

  // Missing fields
  const missingFields: string[] = []
  if (!assetType) missingFields.push('Nutzungstyp')
  if (!areaRange) missingFields.push('Flächenbedarf')
  if (preferredLocations.length === 0) missingFields.push('Standort')
  if (!budgetRange) missingFields.push('Budget')
  if (!timing) missingFields.push('Verfügbarkeitstermin')

  // Assumptions
  const assumptions: string[] = []
  if (areaRange && areaSingleMatch && !areaRangeMatch) {
    assumptions.push(`Flächenrange aus Einzelangabe (${areaSingleMatch[1]} m²) geschätzt — bitte prüfen`)
  }
  if (budgetRange && !budgetPerSqmMatch && budgetMaxMatch) {
    assumptions.push('Budget als Pauschalangabe interpretiert — Angabe pro m² unklar')
  }
  if (!assetType) {
    assumptions.push('Nutzungstyp konnte nicht eindeutig erkannt werden')
  }

  // Confidence by field
  const confidenceByField: Record<string, number> = {
    assetType: assetType ? 0.92 : 0.20,
    areaRange: areaConfidence,
    preferredLocations: locationConfidence,
    budgetRange: budgetConfidence,
    timing: timingConfidence,
    mustHaveCriteria: mustHaveCriteria.length > 0 ? 0.85 : 0.10,
    prestigeImportance: prestigeImportance ? 0.80 : 0.20,
    parkingNeed: parkingNeed ? 0.90 : 0.30,
  }

  // Follow-up questions
  const followUpQuestionCandidates: FollowUpQuestion[] = []

  if (!assetType) {
    followUpQuestionCandidates.push({
      id: 'fq-asset-type',
      questionText: 'Welchen Nutzungstyp suchen Sie?',
      targetField: 'assetType',
      reason: 'Der Nutzungstyp konnte nicht eindeutig erkannt werden.',
      suggestedAnswerOptions: ['Büro', 'Logistik / Lager', 'Retail', 'Produktion', 'Gastro / F&B'],
      importance: 'required',
    })
  }
  if (preferredLocations.length === 0) {
    followUpQuestionCandidates.push({
      id: 'fq-location',
      questionText: 'In welcher Region oder Stadt suchen Sie?',
      targetField: 'preferredLocations',
      reason: 'Kein konkreter Standort angegeben.',
      suggestedAnswerOptions: ['Zürich', 'Basel', 'Bern', 'Zug', 'Luzern', 'Genf'],
      importance: 'required',
    })
  }
  if (!timing) {
    followUpQuestionCandidates.push({
      id: 'fq-timing',
      questionText: 'Ab wann benötigen Sie die Fläche?',
      targetField: 'timing',
      reason: 'Kein Verfügbarkeitsdatum erkannt.',
      suggestedAnswerOptions: ['Sofort', 'In 3 Monaten', 'In 6 Monaten', 'In 12 Monaten', 'Flexibel'],
      importance: 'recommended',
    })
  }
  if (!budgetRange) {
    followUpQuestionCandidates.push({
      id: 'fq-budget',
      questionText: 'Was ist Ihr Maximalbudget pro m² und Jahr?',
      targetField: 'budgetRange',
      reason: 'Kein Budget erkannt.',
      suggestedAnswerOptions: ['< CHF 20/m²', 'CHF 20–40/m²', 'CHF 40–80/m²', '> CHF 80/m²', 'Flexible'],
      importance: 'recommended',
    })
  }
  followUpQuestionCandidates.push({
    id: 'fq-parking',
    questionText: 'Benötigen Sie Parkplätze vor Ort?',
    targetField: 'parkingNeed',
    reason: 'Angabe zu Parkplatzbedarf verbessert die Matchqualität.',
    suggestedAnswerOptions: ['Ja, zwingend', 'Ja, wenn möglich', 'Nein'],
    importance: 'optional',
  })

  // Suggested weights
  const suggestedWeights: Record<string, number> = {
    area: 0.20,
    location: preferredLocations.length > 0 ? 0.28 : 0.22,
    budget: budgetRange ? 0.22 : 0.18,
    timing: timing ? 0.15 : 0.12,
    prestige: prestigeImportance === 'HIGH' ? 0.10 : 0.05,
    accessibility: mustHaveCriteria.includes('Gute ÖV-Anbindung') ? 0.08 : 0.04,
    expansionPotential: 0.03,
    flexibility: lower.includes('flexibel') ? 0.07 : 0.03,
  }

  const rawSummary = `Bedarf analysiert: ${assetType ?? 'Typ unbekannt'} · ${preferredLocations.join(', ') || 'Standort unklar'} · ${areaRange ? `${areaRange.min}–${areaRange.max} m²` : 'Fläche unklar'} · ${budgetRange ? `max. CHF ${budgetRange.maxPerSqm}/m²` : 'Budget unklar'}`

  return {
    extractedCriteria: {
      assetType,
      areaRange,
      preferredLocations,
      budgetRange,
      timing,
      mustHaveCriteria,
      infrastructureRequirements: [],
      accessibilityRequirements: [],
      prestigeImportance,
      flexibilityNeed: lower.includes('flexibel') ? 'HIGH' : 'MEDIUM',
      expansionPotential: lower.includes('wachstum') || lower.includes('expansion'),
      parkingNeed,
      visibilityNeed,
      footfallNeed,
    },
    confidenceByField,
    missingFields,
    assumptions,
    suggestedWeights,
    followUpQuestionCandidates,
    rawSummary,
    promptVersion: 'mock-v1.0',
    schemaVersion: '1.0.0',
  }
}

// ── Legacy mock provider (kept for backward compat) ───────────────────────────

const MockupAIServiceProvider: AIServiceProvider = {
  async extractCriteria(_input: string): Promise<CriteriaExtractionResult> {
    return {
      extractedCriteria: {
        companyName: 'Unbekannt (bitte bestätigen)',
        requiredArea: { min: 400, max: 900 },
        budgetRange: { maxPerSqm: 40, currency: 'CHF' },
      },
      confidence: 0.72,
      missingFields: ['assetType', 'timing', 'preferredLocations'],
      assumptions: ['Fläche aus Zahlenangabe geschätzt', 'Budget aus Kostennennung abgeleitet'],
      followUpQuestions: [
        'Welchen Nutzungstyp suchen Sie (Büro, Retail, Logistik)?',
        'In welchen Städten oder Regionen suchen Sie?',
        'Wann möchten Sie spätestens einziehen?',
      ],
    }
  },
  async generateFollowUp(partialNeed: Partial<CreateNeedInput>): Promise<string[]> {
    const questions: string[] = []
    if (!partialNeed.assetType) questions.push('Welchen Nutzungstyp suchen Sie?')
    if (!partialNeed.preferredLocations?.length) questions.push('In welchen Regionen suchen Sie?')
    if (!partialNeed.timing) questions.push('Was ist Ihr gewünschter Einzugstermin?')
    if (!partialNeed.budgetRange) questions.push('Was ist Ihr maximales monatliches Budget?')
    return questions
  },
}

const provider = MockupAIServiceProvider

const notConfiguredError = (): ServiceError => ({
  code: ServiceErrorCode.AI_GENERATION_FAILED,
  message: 'OpenRouter nicht konfiguriert',
})

export const openRouterAIService: AIServiceProvider = {
  async extractCriteria(_input: string): Promise<CriteriaExtractionResult> {
    throw notConfiguredError()
  },
  async generateFollowUp(_partialNeed: Partial<CreateNeedInput>): Promise<string[]> {
    throw notConfiguredError()
  },
}

export const aiService = {
  // Legacy methods
  async extractCriteria(input: string): Promise<ItemResponse<CriteriaExtractionResult>> {
    const data = await provider.extractCriteria(input)
    return { data }
  },
  async generateFollowUp(partialNeed: Partial<CreateNeedInput>): Promise<ItemResponse<string[]>> {
    const data = await provider.generateFollowUp(partialNeed)
    return { data }
  },

  // F014: Compare summary
  async summarizeComparison(items: UnifiedMatchResult[]): Promise<ItemResponse<ComparisonSummary>> {
    await new Promise(r => setTimeout(r, 600))
    return { data: buildComparisonSummary(items) }
  },

  // F008 methods
  async parseNeed(input: string): Promise<ItemResponse<ParseNeedResult>> {
    await new Promise(r => setTimeout(r, 1400))
    const data = mockParseNeed(input)
    return { data }
  },
  async generateFollowUpQuestions(criteria: ParsedNeedCriteria): Promise<ItemResponse<FollowUpQuestion[]>> {
    await new Promise(r => setTimeout(r, 600))
    const result = mockParseNeed(JSON.stringify(criteria))
    return { data: result.followUpQuestionCandidates }
  },

  async generateDecisionBrief(shortlistId: string): Promise<ItemResponse<DecisionBrief>> {
    await new Promise(r => setTimeout(r, 1800))
    return { data: buildMockDecisionBrief(shortlistId) }
  },
}
