using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Domain.Entities.Members;
using Domain.Entities.Payments.ValueObject;

namespace Domain.Entities.Payments.Danal;

/// <summary>
/// 다날 결제 승인 요청 + 응답 통합
/// confirm API 호출 시 요청 데이터를 먼저 저장하고, 응답 수신 시 업데이트
/// </summary>
public class DanalConfirm
{
    [ForeignKey(nameof(MemberID))]
    public virtual Member? Member { get; private set; }

    [ForeignKey(nameof(PaymentOrderID))]
    public virtual PaymentOrder? PaymentOrder { get; private set; }

    [Key]
    public int ID { get; private set; }

    public int MemberID { get; private set; }

    public int PaymentOrderID { get; private set; }

    public PaymentMethod Method { get; private set; }

    /// <summary>다날 거래번호</summary>
    public string TransactionID { get; private set; } = default!;

    /// <summary>가맹점 주문번호</summary>
    public string OrderID { get; private set; } = default!;

    /// <summary>요청 금액</summary>
    public int Amount { get; private set; }

    /// <summary>CPID</summary>
    public string MerchantID { get; private set; } = default!;

    /// <summary>도서문화상품권: 승인 요청 토큰</summary>
    public string? CertificateToken { get; private set; }

    // ── 응답 필드 (승인 완료 시 업데이트) ────────────────────────────

    /// <summary>응답 코드 (0000 = 성공)</summary>
    public string? ResponseCode { get; private set; }

    /// <summary>응답 메시지</summary>
    public string? ResponseMessage { get; private set; }

    /// <summary>승인된 상품명</summary>
    public string? OrderName { get; private set; }

    /// <summary>최종 승인 금액</summary>
    public int? TotalAmount { get; private set; }

    /// <summary>할인 금액</summary>
    public int? DiscountAmount { get; private set; }

    /// <summary>사용자 이름</summary>
    public string? UserName { get; private set; }

    // ── 카드 응답 ────────────────────────────────────────────────────

    /// <summary>승인일자 (YYYYMMDD)</summary>
    public string? TransDate { get; private set; }

    /// <summary>승인시간</summary>
    public string? TransTime { get; private set; }

    /// <summary>카드사 코드</summary>
    public string? CardCode { get; private set; }

    /// <summary>카드사 이름</summary>
    public string? CardName { get; private set; }

    /// <summary>카드번호 (마스킹)</summary>
    public string? CardNo { get; private set; }

    /// <summary>할부 개월 수 (0=일시불)</summary>
    public byte? InstallmentMonths { get; private set; }

    /// <summary>승인번호</summary>
    public string? ApproveNo { get; private set; }

    // ── 휴대폰 응답 ─────────────────────────────────────────────────

    /// <summary>결제 승인 일시</summary>
    public string? ApprovalDateTime { get; private set; }

    /// <summary>정기 결제 시 사용하는 키</summary>
    public string? AuthKey { get; private set; }

    // ── 계좌이체 응답 ────────────────────────────────────────────────

    /// <summary>출금계좌 뒷자리</summary>
    public string? AccountNumber { get; private set; }

    /// <summary>은행 코드</summary>
    public string? BankCode { get; private set; }

    /// <summary>구매자 ID</summary>
    public string? UserId { get; private set; }

    /// <summary>구매자 이메일</summary>
    public string? UserEmail { get; private set; }

    // ── 가상계좌 응답 ────────────────────────────────────────────────

    /// <summary>입금은행 이름</summary>
    public string? BankName { get; private set; }

    /// <summary>입금 마감 날짜 (YYYYMMDD)</summary>
    public string? ExpireDate { get; private set; }

    /// <summary>입금 마감 시간</summary>
    public string? ExpireTime { get; private set; }

    /// <summary>가상계좌 번호</summary>
    public string? VirtualAccountNumber { get; private set; }

    /// <summary>현금영수증 설정 유무</summary>
    public string? UseCashReceipt { get; private set; }

    public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;

    public DateTime? UpdatedAt { get; private set; }

    private DanalConfirm() { }

    /// <summary>승인 요청 시 생성 (응답 전)</summary>
    public static DanalConfirm CreateRequest(
        int memberID,
        int paymentOrderID,
        PaymentMethod method,
        string transactionID,
        string orderID,
        int amount,
        string merchantID,
        string? certificateToken = null
    ) {
        return new DanalConfirm
        {
            MemberID = memberID,
            PaymentOrderID = paymentOrderID,
            Method = method,
            TransactionID = transactionID,
            OrderID = orderID,
            Amount = amount,
            MerchantID = merchantID,
            CertificateToken = certificateToken
        };
    }

    /// <summary>승인 응답 수신 시 업데이트</summary>
    public void SetResponse(
        string code, string message, string? orderName = null,
        int? totalAmount = null, int? discountAmount = null, string? userName = null,
        string? transDate = null, string? transTime = null,
        string? cardCode = null, string? cardName = null, string? cardNo = null,
        byte? installmentMonths = null, string? approveNo = null,
        string? approvalDateTime = null, string? authKey = null,
        string? accountNumber = null, string? bankCode = null, string? userId = null, string? userEmail = null,
        string? bankName = null, string? expireDate = null, string? expireTime = null,
        string? virtualAccountNumber = null, string? useCashReceipt = null
    ) {
        ResponseCode = code;
        ResponseMessage = message;
        OrderName = orderName;
        TotalAmount = totalAmount;
        DiscountAmount = discountAmount;
        UserName = userName;
        TransDate = transDate;
        TransTime = transTime;
        CardCode = cardCode;
        CardName = cardName;
        CardNo = cardNo;
        InstallmentMonths = installmentMonths;
        ApproveNo = approveNo;
        ApprovalDateTime = approvalDateTime;
        AuthKey = authKey;
        AccountNumber = accountNumber;
        BankCode = bankCode;
        UserId = userId;
        UserEmail = userEmail;
        BankName = bankName;
        ExpireDate = expireDate;
        ExpireTime = expireTime;
        VirtualAccountNumber = virtualAccountNumber;
        UseCashReceipt = useCashReceipt;
        UpdatedAt = DateTime.UtcNow;
    }

    public bool IsSuccess => ResponseCode == "0000";
}