import { useState } from 'react' import { useQueryClient } from '@tanstack/react-query' import { Box, Chip, CircularProgress, Divider, Switch, Typography } from '@mui/material' import { Clock, ShieldCheck, Zap } from 'lucide-react' import type { Property } from '../../domain/property' import { MockupUnitProvider } from '../../provider/MockupUnitProvider' import { useUpdateProperty } from '../../hooks/useProperties' import { useToastStore } from '../../stores/toastStore' import { DS_BORDER, DS_PRE_MARKET, DS_SURFACE, DS_TEXT } from '../../lib/ds' import { SectionTitle } from './PropertyDetailHelpers' import { PreMarketDemandIntelligence } from './PreMarketDemandIntelligence' import { PreMarketUnitGrid, type UnitReleaseState } from './PreMarketUnitGrid' export const MOCK_TODAY = new Date('2026-05-20') export function PreMarketPanel({ p }: { p: Property }) { const [enabled, setEnabled] = useState(p.schattenmarktRelease?.enabled ?? false) const [leadTimeMonths, setLeadTimeMonths] = useState(p.schattenmarktRelease?.leadTimeMonths ?? 6) const [unitStates, setUnitStates] = useState>(() => { const init: Record = {} for (const u of p.units ?? []) { init[u.id] = { enabled: u.schattenmarktRelease?.enabled ?? false, availableFrom: u.schattenmarktRelease?.availableFrom ?? u.leaseEndDate ?? '', anonymous: u.schattenmarktRelease?.anonymous ?? false, } } return init }) const [unitSaving, setUnitSaving] = useState>({}) const queryClient = useQueryClient() const updateProperty = useUpdateProperty() const showToast = useToastStore(s => s.showToast) const saving = updateProperty.isPending if (p.resultType !== 'VERIFIED_PORTFOLIO') return null if (!p.leaseEndDate && !p.breakoutOptionDate) return null const candidates: Date[] = [] if (p.leaseEndDate) { const d = new Date(p.leaseEndDate); d.setMonth(d.getMonth() - leadTimeMonths); candidates.push(d) } if (p.breakoutOption && p.breakoutOptionDate) { const d = new Date(p.breakoutOptionDate); d.setMonth(d.getMonth() - leadTimeMonths); candidates.push(d) } const triggerDate = candidates.length ? candidates.reduce((a, b) => (a < b ? a : b)) : null const isActive = triggerDate ? MOCK_TODAY >= triggerDate : false const targetDate = (p.breakoutOption && p.breakoutOptionDate) ? new Date(p.breakoutOptionDate) : p.leaseEndDate ? new Date(p.leaseEndDate) : null const monthsUntil = targetDate ? Math.max(0, Math.round((targetDate.getTime() - MOCK_TODAY.getTime()) / (1000 * 60 * 60 * 24 * 30))) : null const demandProfiles = Math.min(14, (p.areaSqm >= 1000 ? 5 : p.areaSqm >= 500 ? 8 : 4) + (['Zürich', 'Basel', 'Bern', 'Zug'].some(c => (p.location?.city ?? '').includes(c)) ? 4 : 1)) const highQualityLeads = Math.max(1, Math.floor(demandProfiles * 0.38)) function save(nextEnabled: boolean, nextLeadTime: number) { updateProperty.mutate( { id: p.id, input: { schattenmarktRelease: { enabled: nextEnabled, leadTimeMonths: nextLeadTime } } }, { onSuccess: () => { showToast(nextEnabled ? 'Pre-Market Matching aktiviert.' : 'Pre-Market Matching deaktiviert.', 'success') }, onError: () => { showToast('Fehler beim Speichern.', 'error') }, }, ) } function handleToggle(_: React.ChangeEvent, checked: boolean) { setEnabled(checked) save(checked, leadTimeMonths) } function handleLeadTime(months: number) { setLeadTimeMonths(months) if (enabled) save(enabled, months) } async function saveUnit(unitId: string, nextEnabled: boolean, nextDate: string, nextAnonymous: boolean) { setUnitSaving(prev => ({ ...prev, [unitId]: true })) try { await MockupUnitProvider.update(unitId, { schattenmarktRelease: { enabled: nextEnabled, availableFrom: nextDate || undefined, anonymous: nextAnonymous }, }) await queryClient.invalidateQueries({ queryKey: ['property', p.id] }) await queryClient.invalidateQueries({ queryKey: ['properties'] }) } catch { showToast('Fehler beim Speichern der Einheit.', 'error') } finally { setUnitSaving(prev => ({ ...prev, [unitId]: false })) } } return ( <> {/* Toggle row */} Pre-Market Matching aktivieren Kontrollierte Freigabe für qualifizierte Suchanfragen — vor offizieller Insertion {saving && } {/* Active: lead time + status + unit grid + demand intelligence */} {enabled && ( {/* Lead time selector */} Lead Time {[3, 4, 5, 6, 8, 12].map(m => ( handleLeadTime(m)} sx={{ height: 20, fontSize: '0.68rem', cursor: 'pointer', bgcolor: leadTimeMonths === m ? DS_PRE_MARKET.accent : DS_SURFACE.slate.bg, color: leadTimeMonths === m ? DS_TEXT.inverted : '#374151', '&:hover': { bgcolor: leadTimeMonths === m ? DS_PRE_MARKET.accentHover : DS_BORDER.default }, }} /> ))} {/* Activation status */} {isActive ? : } {isActive ? `PRE-MARKET VERIFIED aktiv seit ${triggerDate?.toLocaleDateString('de-CH')} — Fläche im Matching-Feed sichtbar` : triggerDate ? `Freigabe startet ${triggerDate.toLocaleDateString('de-CH')} — noch ${monthsUntil} Monate bis Vertragsende` : 'Kein Vertragsende hinterlegt' } {(p.units?.length ?? 0) > 0 && ( )} )} {/* Inactive: explain value proposition */} {!enabled && ( Wenn aktiviert, erscheint diese Fläche {leadTimeMonths} Monate vor Vertragsende als verifiziertes PRE-MARKET VERIFIED Signal für qualifizierte Suchanfragen — kein öffentliches Inserat, kontrolliertes Early Matching. )} ) }