package com.zioinfo.kintex.auction.dto;

import java.util.List;

/**
 * M15 옥션 응답/요청 DTO 모음(프론트 auctionApi.ts 계약 정본과 정합).
 * <p>봉인 입찰 보안: 응찰자 뷰 {@link RankRow}는 마감 전 타사 금액을 {@code price=null,priceMasked=true}로
 * 마스킹하며 업체명을 노출하지 않는다. 전체 공개({@link AwardView})는 마감 후 발주자 전용.
 */
public final class AuctionDtos {

    private AuctionDtos() {
    }

    /** 목록·카드(SCR-26). status/type 는 화면 표시 문자열(진행중|마감|정산중 / 역경매|RFQ). */
    public record AuctionSummary(
            String id, String eventId, String title, String category,
            String type, String status, int round, int dday,
            int bidderCount, Long lowestPrice, String awardedCompany, Long finalPrice,
            List<String> materials, String accent) {
    }

    /** 종합평가 가중치. */
    public record Weights(int price, int reputation, int delivery) {
    }

    /** M2~M5 AI 자료 패키지 참조 URL(없으면 null → 플레이스홀더). */
    public record MaterialPackage(String layoutUrl, String designUrl, String boqUrl, String aiImageUrl) {
    }

    /**
     * F035 물량서(BOQ) 라인 — 공종·품명·단위·수량·산출근거. 금액(단가)은 미포함(응찰 업체가 견적서로 채움).
     */
    public record BoqLine(int seq, String trade, String item, String unit, long qty, String basis) {
    }

    /**
     * F035 물량서(BOQ) 자동산출 결과 — 옥션 자료 패키지 첨부용.
     * scope = booth(제목의 부스코드로 매칭한 단일 부스) | event(행사 전체 부스 집계).
     * lines 가 비어 있으면 설계 미확정 — note 로 사유 안내.
     */
    public record BoqResult(
            String auctionId, String eventId, String scope, String scopeLabel,
            int boothCount, long totalAreaM2, List<BoqLine> lines, String note, String generatedAt) {
    }

    /**
     * 실시간 순위 행(응찰자 뷰 · 봉인). priceMasked=true 이면 price 는 null(타사 비공개).
     * alias 는 위치 라벨(업체명 아님) — 업체 식별 불가.
     */
    public record RankRow(int rank, String alias, boolean isMe, boolean isLowest,
                          boolean priceMasked, Long price) {
    }

    /**
     * 실시간 순위 브로드캐스트 스냅샷(WebSocket {@code /topic/auctions/{id}/ranking}).
     * <p><b>봉인 안전(구조적 보장)</b>: 이 페이로드는 모든 구독자에게 동일하게 전송되므로
     * <b>뷰어별 개인화 정보(내 순위·내 금액·isMe)를 담지 않는다</b>. ranking 은 {@code isMe=false} 고정으로
     * 마스킹된 <b>공개 순위</b>(현행 폴링이 비응찰 발주자에게 노출하는 수준과 동일 — 최저가 금액만 공개,
     * 그 외 타사 금액·업체명 비공개)만 포함한다. 개인화 순위는 클라이언트가 인증된 상세 API로 재조회한다.
     * event = BID(응찰 접수/재응찰) | CLOSE(라운드 마감) | AWARD(낙찰).
     */
    public record RankingSnapshot(
            String auctionId, String eventId, String event, int round, boolean sealed,
            int bidderCount, Long lowestPrice, List<RankRow> ranking, String at) {
    }

    /** 상세(SCR-27). ranking 은 봉인 마스킹 적용본. canBid/canViewAward 로 UI 게이팅. */
    public record AuctionDetail(
            String id, String eventId, String title, String category, String type, String status,
            int round, int dday, String deadline, int bidderCount, Long lowestPrice,
            String awardCriteria, Weights weights, List<String> materials, MaterialPackage materialPackage,
            boolean sealed, Integer myRank, Long myPrice,
            List<RankRow> ranking, boolean canBid, boolean canViewAward,
            String awardedCompany, Long finalPrice) {
    }

    /** 옥션 개설 요청(SCR-26). */
    public record CreateAuctionRequest(
            String eventId, String title, String category, String type,
            String awardCriteria, Weights weights, Integer round, String deadline,
            String materialPackageId, List<String> materials, List<String> invitedCompanyIds) {
    }

    /** 견적서 라인아이템(SCR-28) — 공종·자재·수량·단가. 금액=수량×단가는 서버 계산. */
    public record QuoteLine(String trade, String material, Long qty, Long unitPrice) {
    }

    /**
     * 응찰(견적서 제출) 요청. lines(라인아이템)가 있으면 서버가 소계/부가세/총액을 재계산한다.
     * lines 미전송 시 total(경쟁 금액, 부가세 별도)만으로 폴백. 둘 다 없으면 검증 오류.
     */
    public record BidRequest(Long total, Integer leadDays, String validUntil, String terms,
                             List<QuoteLine> lines) {
    }

    /**
     * 응찰 결과(자사 확인용). total=경쟁 순위 금액(부가세 별도, 최저가 비교 기준),
     * grandTotal=부가세 포함 총액(소계+부가세).
     */
    public record BidResult(String id, int round, long subtotal, long vat, long total, long grandTotal,
                            int version, Integer myRank, Long lowestPrice) {
    }

    /** 낙찰 요청 — reason 필수. */
    public record AwardRequest(String bidId, String reason) {
    }

    /** 낙찰 결과. */
    public record AwardResult(String id, String bidId, String companyName, String awardedAt) {
    }

    /** 발주자 비교 컬럼(SCR-29 · 마감 후 봉인 해제). alias=업체명. */
    public record Quote(
            String bidId, String companyId, String alias, String subtitle, boolean recommended,
            long totalPrice, double priceDeltaPct, boolean isLowestPrice,
            int leadDays, boolean isShortestLead, double reputation, double score) {
    }

    /** AI 리스크 바(발주자 뷰). */
    public record RiskBar(String label, double pct, String tone) {
    }

    /** 낙찰 비교·선정 화면 페이로드(마감 후 발주자 전용). */
    public record AwardView(
            String auctionId, String auctionTitle, int bidderCount,
            String awardCriteria, Weights weights, List<Quote> quotes,
            List<RiskBar> riskBars, AwardResult awarded) {
    }

    // ── 업체 포털 대시보드(SCR-38) ──
    public record Kpi(String label, int value, String tone) {
    }

    public record AwardedBooth(String auctionId, String event, String name, String booth,
                               String client, Integer dday, String stage) {
    }

    public record MyBid(String auctionId, String auctionTitle, long myPrice, Integer myRank, int dday) {
    }

    public record FeedItem(String text, String meta, String tone) {
    }

    public record ContractorDashboard(
            String companyName, List<Kpi> kpis, List<AwardedBooth> awardedBooths,
            List<MyBid> myAuctionBids, List<FeedItem> feed) {
    }
}
