package com.zioinfo.kintex.visitor.dto;

import java.util.List;

/**
 * M10 관람객·리드 응답 DTO 모음.
 * <p>★ PII 불변(N2/R10): 리스트/상세 응답에는 마스킹 필드({@code nameMasked}·{@code phoneMasked}·{@code emailMasked})만
 * 존재하며 원문 name/phone/email 필드는 존재하지 않는다. 마스킹은 매퍼 SQL 표현식이 수행한다.
 */
public final class VisitorDtos {

    private VisitorDtos() {
    }

    // ── SCR-30 등록 대시보드 요약 ──
    public record VisitorSummary(List<Kpi> kpis, List<TrendPoint> trend, List<TypeSlice> types, List<FormItem> forms) {
    }

    public record Kpi(String label, String value, String delta, String trend, Boolean ai, String sub) {
    }

    public record TrendPoint(String label, long preReg, long checkIn) {
    }

    public record TypeSlice(String name, int value, String color) {
    }

    public record FormItem(String id, String name, boolean active, long count) {
    }

    // ── SCR-30 등록자 목록(마스킹) ──
    public record VisitorListItem(String id, String nameMasked, String type, String company,
                                  String registeredAt, String checkin, boolean badgeIssued) {
    }

    // ── SCR-32 리드(마스킹 + AI 저장값) ──
    public record LeadItem(String id, String nameMasked, String role, String company, String product,
                           int interest, int score, String collectedAt, String phoneMasked, String emailMasked,
                           List<String> aiReasons, List<Activity> activity, String followupDraft, boolean aiGenerated) {
    }

    public record Activity(String text, String at) {
    }

    // ── 공개 사전등록 요청/결과 ──
    public record RegisterRequest(String name, String phone, String email, String visitorType,
                                  Boolean agreePrivacy, Boolean agreeMarketing) {
    }

    public record RegisterResult(String registrationId, String badgeCode) {
    }

    // ── SCR-31 현장 체크인 ──
    /** 체크인 요청 — QR 토큰 우선, 없으면 등록ID(수동 검색 후 체크인). */
    public record CheckinRequest(String token, String registrationId) {
    }

    /** 체크인 결과 — 원문 PII 미포함(마스킹 이름만). {@code alreadyCheckedIn} 이면 중복 스캔(재집계 없음). */
    public record CheckinResult(String registrationId, String nameMasked, String type, String company,
                                String badgeCode, boolean badgeIssued, String checkinState,
                                boolean alreadyCheckedIn, String checkinAt) {
    }

    /** 현장 수동 검색 결과(마스킹) — 데스크가 선택 후 체크인. */
    public record CheckinSearchItem(String registrationId, String nameMasked, String type, String company,
                                    String phoneMasked, String badgeCode, String checkinState) {
    }

    /** 실시간 입장 집계(SCR-31 우측 위젯). */
    public record CheckinStats(long preRegistered, long checkedIn, long inside, List<HourBucket> byHour) {
    }

    public record HourBucket(String hour, long count) {
    }

    /** 배지 재발급 결과 — 새 배지코드(QR 토큰은 서버 내부 갱신, 응답 미노출). */
    public record BadgeReissueResult(String registrationId, String badgeCode, boolean badgeIssued) {
    }

    // ── SCR-32 리드 수집 ──
    /** 리드 수집 요청 — 참가업체 부스에서 배지 스캔·상담. score 는 서버 규칙 엔진이 산출(클라이언트 값 무시). */
    public record LeadCollectRequest(String name, String phone, String email, String role, String company,
                                     String product, String boothId, String exhibitorId, String note,
                                     Integer interest, Integer dwellRatioPct, Integer revisitCount,
                                     Boolean decisionMaker, Integer docDownloads, Boolean agreePrivacy) {
    }

    public record LeadCollectResult(String leadId, int score, List<String> aiReasons, String scoreSource) {
    }

    /**
     * SCR-32 리드 AI 재계산 결과(F051). {@code scoreSource}="ai"(Claude/Ollama) | "rule"(폴백).
     * {@code aiGenerated}·{@code degraded}·{@code provider} 로 산출 출처를 정직하게 표기한다(환각 방지·라벨링 근거).
     *
     * @param leadId      리드 ID
     * @param score       0~100 스코어(AI 성공 시 AI 값, 실패 시 기존 규칙 스코어 유지)
     * @param aiReasons   근거 문구
     * @param scoreSource "ai" | "rule"
     * @param aiGenerated AI 산출 여부(폴백이면 false)
     * @param degraded    AI 경로 실패로 폴백했는지
     * @param provider    실제 응답 provider("claude"|"ollama"|"none")
     */
    public record LeadRescoreResult(String leadId, int score, List<String> aiReasons,
                                    String scoreSource, boolean aiGenerated, boolean degraded, String provider) {
    }
}
