package com.zioinfo.kintex.settlement.dto;

import java.util.List;

/**
 * M9 정산·결제 DTO 묶음 — 대시보드·청구서 목록/상세·수납 기록.
 * 금액은 모두 서버 계산 권위(원 단위, long). 민감정보·PII 미포함.
 */
public final class SettlementDtos {

    private SettlementDtos() {
    }

    // ── 대시보드(SCR /settlement) ────────────────────────────────────────────
    /** 정산 현황 요약 KPI + 상태 분포. paymentNote = PG 위임 고지 문구. */
    public record SettlementDashboard(
            String eventId,
            long billed,        // 총 청구액(Σ total)
            long collected,     // 총 수납액(Σ paid_amount)
            long outstanding,   // 미수(billed - collected)
            long invoiceCount,
            long overdueCount,
            double collectionRate, // 수납률(%) = collected/billed×100
            List<StatusBucket> statusDistribution,
            String paymentNote
    ) {
    }

    /** 상태별 건수·금액 분포(청구/수납). */
    public record StatusBucket(
            String status,     // pending|invoiced|paid|overdue
            long count,
            long totalAmount,
            long paidAmount
    ) {
    }

    // ── 청구서 목록 ───────────────────────────────────────────────────────────
    public record InvoiceSummary(
            String id,
            String eventId,
            String invoiceNo,
            String exhibitorName,
            long subtotal,
            long vat,
            long total,
            long paidAmount,
            long outstanding,
            String status,
            String dueDate,     // ISO 날짜(YYYY-MM-DD) 또는 null
            String issuedAt,    // ISO 8601 또는 null
            String category     // rental(임대·유틸) | auction_fee(옥션 수수료) — 유형 구분(F084)
    ) {
    }

    // ── 청구서 상세(라인아이템 + 수납 이력) ────────────────────────────────────
    public record InvoiceDetail(
            String id,
            String eventId,
            String invoiceNo,
            String exhibitorName,
            long subtotal,
            long vat,
            long total,
            long paidAmount,
            long outstanding,
            String status,
            String dueDate,
            String issuedAt,
            String paidAt,
            String note,
            String category,    // rental | auction_fee (F084)
            List<LineItem> lineItems,
            List<PaymentRecord> payments,
            boolean canManage   // 매니저 이상(수납/발행 버튼 노출용) — 서버 판정
    ) {
    }

    /** 청구 라인아이템(산출 스냅샷). category = RENTAL|UTILITY|OTHER. */
    public record LineItem(
            String category,
            String description,
            long quantity,
            long unitPrice,
            long amount
    ) {
    }

    /** 수납 기록. */
    public record PaymentRecord(
            String id,
            long amount,
            String method,
            String memo,
            String recordedAt
    ) {
    }

    // ── 요청 ──────────────────────────────────────────────────────────────────
    /** 수납 기록 요청 — 금액은 서버가 재검증(>0, 총액 초과 방지). */
    public record RecordPaymentRequest(
            Long amount,
            String method,   // manual|transfer|card (선택, 기본 manual)
            String memo
    ) {
    }

    /** 청구서 생성 결과 — 신규 생성 건수 + 요약. */
    public record GenerateResult(
            String eventId,
            int created,
            int skipped,
            List<InvoiceSummary> invoices
    ) {
    }

    /** F084 옥션 수수료 청구 생성 결과(낙찰 연동). created=false 이면 skipReason 사유(멱등/0원). */
    public record AuctionFeeResult(
            boolean created,
            String invoiceId,
            String invoiceNo,
            long fee,
            long vat,
            long total,
            double ratePercent,
            String skipReason
    ) {
    }

    // ── F085 환불·취소 규정 ────────────────────────────────────────────────────
    /**
     * 환불 산정 미리보기(취소 확정 전) 또는 확정 결과의 근거. 금액은 서버 계산 권위(원 단위).
     * <p>기준액(baseAmount) = 실 납입액(paid_amount). refundAmount = base × rate/100, forfeit = base − refund.
     * daysBeforeEvent = 취소 시점 D-일(음수=행사 후, null=개막일 미확정). rulesetVersion = refund-v1.0.
     */
    public record RefundQuote(
            String invoiceId,
            String invoiceNo,
            String status,          // 현재 청구 상태(cancelled 여부 판단용)
            long total,             // 청구 총액(참고)
            long baseAmount,        // 환불 산정 기준(실 납입액)
            double refundRatePercent,
            long refundAmount,
            long forfeitAmount,     // 공제·위약액 = base − refund
            Integer daysBeforeEvent,
            String bracketLabel,    // 적용 구간 라벨(예: "D-30 ~ D-59")
            String eventStartDate,  // 행사 개막일(YYYY-MM-DD) 또는 null
            boolean dateResolved,   // 개막일로 자동 산정 가능 여부(false=수기 검토)
            String rulesetVersion,
            String pgNote           // PG 미집행 고지(G2 게이트)
    ) {
    }

    /** 청구 취소 요청 — reason(선택), cancelDate(선택 ISO YYYY-MM-DD, 기본=오늘). */
    public record CancelInvoiceRequest(
            String reason,
            String cancelDate
    ) {
    }

    /** 청구 취소 결과 — 갱신된 청구 상세 + 환불 근거. */
    public record CancelResult(
            InvoiceDetail invoice,
            RefundQuote refund
    ) {
    }

    // ── F083 세금계산서 ────────────────────────────────────────────────────────
    /**
     * 세금계산서 데이터 문서(국세청 미전송 — 문서 데이터까지, G2 게이트).
     * 공급자(supplier*)는 킨텍스 상수, 공급받는자(buyer)는 참가업체 표시명. 금액은 청구서 스냅샷.
     */
    public record TaxInvoiceDto(
            String id,
            String invoiceId,
            String eventId,
            String taxInvoiceNo,
            String supplierName,
            String supplierBizNo,
            String supplierCeo,
            String supplierAddr,
            String buyerName,
            long supplyAmount,
            long vat,
            long total,
            String itemSummary,
            String status,          // issued(문서 발행) | void
            String issuedAt,
            String issueNote        // 국세청 전송 없음 고지(G2)
    ) {
    }

    // ── 정산 리포트 ────────────────────────────────────────────────────────────
    /** 정산 리포트 — 카테고리별 합계·수납율·미수 + 상세 행(CSV용). 취소 청구는 합계에서 제외. */
    public record SettlementReport(
            String eventId,
            String eventName,
            String generatedAt,
            long totalBilled,
            long totalCollected,
            long totalOutstanding,
            double collectionRate,
            long invoiceCount,
            List<ReportGroup> byCategory,
            List<ReportGroup> byStatus,
            List<ReportRow> rows
    ) {
    }

    /** 리포트 그룹 합계(카테고리/상태별). */
    public record ReportGroup(
            String key,             // category 또는 status 값
            long invoiceCount,
            long billed,
            long collected,
            long outstanding,
            double collectionRate
    ) {
    }

    /** 리포트 상세 행(CSV 다운로드 원천). */
    public record ReportRow(
            String invoiceNo,
            String exhibitorName,
            String category,
            String status,
            long subtotal,
            long vat,
            long total,
            long paidAmount,
            long outstanding,
            String dueDate
    ) {
    }
}
