package com.zioinfo.kintex.settlement;

import com.zioinfo.kintex.auth.EventAccessGuard;
import com.zioinfo.kintex.auth.KintexPrincipal;
import com.zioinfo.kintex.common.ApiResponse;
import com.zioinfo.kintex.common.PageResponse;
import com.zioinfo.kintex.common.audit.Audited;
import com.zioinfo.kintex.settlement.dto.SettlementDtos.*;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

/**
 * M9 정산·결제 API — 행사 청구/수납 현황 대시보드·청구서 목록/상세·생성·발행·수납 기록.
 * <p>인증 필수. 조회는 행사 접근 권한(멤버·홀매니저), 생성·발행·수납은 매니저 이상(서비스 재검증).
 * 결제는 PG 위임 고지 패턴 — 실제 PG 연동 없이 상태 전이·수동 수납만.
 */
@RestController
@RequestMapping("/api/settlement")
public class SettlementController {

    private final SettlementService service;
    private final EventAccessGuard guard;

    public SettlementController(SettlementService service, EventAccessGuard guard) {
        this.service = service;
        this.guard = guard;
    }

    /** GET /api/settlement/dashboard?eventId= — 청구/수납/미수 KPI + 상태 분포. */
    @GetMapping("/dashboard")
    public ApiResponse<SettlementDashboard> dashboard(@AuthenticationPrincipal KintexPrincipal principal,
                                                      @RequestParam String eventId) {
        guard.requireEventAccess(principal, eventId);
        return ApiResponse.ok(service.getDashboard(eventId));
    }

    /** GET /api/settlement/invoices?eventId=&status=&page=&size= — 청구서 목록(상태 필터·페이지네이션). */
    @GetMapping("/invoices")
    public ApiResponse<PageResponse<InvoiceSummary>> invoices(@AuthenticationPrincipal KintexPrincipal principal,
                                                              @RequestParam String eventId,
                                                              @RequestParam(required = false) String status,
                                                              @RequestParam(defaultValue = "0") int page,
                                                              @RequestParam(defaultValue = "20") int size) {
        guard.requireEventAccess(principal, eventId);
        return ApiResponse.ok(service.listInvoices(eventId, status, page, size));
    }

    /** GET /api/settlement/invoices/{id} — 청구서 상세(라인아이템 + 수납 이력). */
    @GetMapping("/invoices/{id}")
    public ApiResponse<InvoiceDetail> detail(@AuthenticationPrincipal KintexPrincipal principal,
                                             @PathVariable String id) {
        guard.require(principal);
        return ApiResponse.ok(service.getDetail(id, principal));
    }

    /** POST /api/settlement/invoices/generate?eventId= — 참가업체별 청구서 집계 생성(매니저 이상). */
    @Audited(action = "SETTLEMENT_GENERATE", targetType = "invoice")
    @PostMapping("/invoices/generate")
    public ApiResponse<GenerateResult> generate(@AuthenticationPrincipal KintexPrincipal principal,
                                                @RequestParam String eventId) {
        guard.requireEventAccess(principal, eventId);
        return ApiResponse.ok(service.generate(eventId, principal));
    }

    /** POST /api/settlement/invoices/{id}/issue — 발행(pending→invoiced, 매니저 이상). */
    @Audited(action = "SETTLEMENT_ISSUE", targetType = "invoice")
    @PostMapping("/invoices/{id}/issue")
    public ApiResponse<InvoiceDetail> issue(@AuthenticationPrincipal KintexPrincipal principal,
                                            @PathVariable String id) {
        guard.require(principal);
        return ApiResponse.ok(service.issue(id, principal));
    }

    /** POST /api/settlement/invoices/{id}/payments — 수납 기록(수동, 매니저 이상). */
    @Audited(action = "SETTLEMENT_PAYMENT", targetType = "invoice_payment")
    @PostMapping("/invoices/{id}/payments")
    public ApiResponse<InvoiceDetail> recordPayment(@AuthenticationPrincipal KintexPrincipal principal,
                                                    @PathVariable String id,
                                                    @RequestBody RecordPaymentRequest req) {
        guard.require(principal);
        return ApiResponse.ok(service.recordPayment(id, principal, req));
    }

    // ── F085 환불·취소 규정 ────────────────────────────────────────────────────
    /** GET /api/settlement/invoices/{id}/refund-quote?cancelDate= — 환불 산정 미리보기(매니저 이상). */
    @GetMapping("/invoices/{id}/refund-quote")
    public ApiResponse<RefundQuote> refundQuote(@AuthenticationPrincipal KintexPrincipal principal,
                                                @PathVariable String id,
                                                @RequestParam(required = false) String cancelDate) {
        guard.require(principal);
        return ApiResponse.ok(service.refundQuote(id, principal, cancelDate));
    }

    /** POST /api/settlement/invoices/{id}/cancel — 청구 취소·환불 산정 기록(매니저 이상). 실 PG 환불 없음. */
    @Audited(action = "SETTLEMENT_CANCEL", targetType = "invoice")
    @PostMapping("/invoices/{id}/cancel")
    public ApiResponse<CancelResult> cancel(@AuthenticationPrincipal KintexPrincipal principal,
                                            @PathVariable String id,
                                            @RequestBody(required = false) CancelInvoiceRequest req) {
        guard.require(principal);
        return ApiResponse.ok(service.cancel(id, principal, req));
    }

    // ── F083 세금계산서 ────────────────────────────────────────────────────────
    /** GET /api/settlement/invoices/{id}/tax-invoice — 세금계산서 조회(없으면 data=null). */
    @GetMapping("/invoices/{id}/tax-invoice")
    public ApiResponse<TaxInvoiceDto> getTaxInvoice(@AuthenticationPrincipal KintexPrincipal principal,
                                                    @PathVariable String id) {
        guard.require(principal);
        return ApiResponse.ok(service.getTaxInvoice(id, principal));
    }

    /** POST /api/settlement/invoices/{id}/tax-invoice — 세금계산서 발행(매니저 이상, 멱등). 국세청 미전송. */
    @Audited(action = "SETTLEMENT_TAX_ISSUE", targetType = "tax_invoice")
    @PostMapping("/invoices/{id}/tax-invoice")
    public ApiResponse<TaxInvoiceDto> issueTaxInvoice(@AuthenticationPrincipal KintexPrincipal principal,
                                                      @PathVariable String id) {
        guard.require(principal);
        return ApiResponse.ok(service.issueTaxInvoice(id, principal));
    }

    // ── 정산 리포트 ────────────────────────────────────────────────────────────
    /** GET /api/settlement/report?eventId= — 카테고리/상태별 합계·수납율·미수 + 상세 행(CSV용). */
    @GetMapping("/report")
    public ApiResponse<SettlementReport> report(@AuthenticationPrincipal KintexPrincipal principal,
                                                @RequestParam String eventId) {
        guard.requireEventAccess(principal, eventId);
        return ApiResponse.ok(service.report(eventId));
    }
}
