package com.zioinfo.kintex.webhook;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;
import java.util.Map;

/**
 * F099 웹훅 게이트웨이 매퍼. Map 반환 @Select 는 별칭에 쌍따옴표(AS "x")로 카멜케이스 키 보존.
 * <b>secret_hash·secret_enc 는 어떤 조회 SELECT 목록에도 포함하지 않는다</b>(응답 유출 차단) —
 * 예외: 인바운드 HMAC 검증 전용 {@link #findInboundSecretEnc}(내부 검증 경로만).
 */
@Mapper
public interface WebhookMapper {

    // ── 아웃바운드 구독 CRUD ──
    @Insert("""
            INSERT INTO webhook_subscription
                (tenant_id, id, event_type, callback_url, secret_hash, description, active, created_by)
            VALUES ('KINTEX', #{id}, #{eventType}, #{callbackUrl}, #{secretHash}, #{description}, true, #{createdBy})
            """)
    int insertSubscription(@Param("id") String id,
                           @Param("eventType") String eventType,
                           @Param("callbackUrl") String callbackUrl,
                           @Param("secretHash") String secretHash,
                           @Param("description") String description,
                           @Param("createdBy") String createdBy);

    /** secret_hash 는 응답 목록에서 제외. */
    @Select("""
            SELECT id, event_type AS "eventType", callback_url AS "callbackUrl",
                   description, active, created_at AS "createdAt", updated_at AS "updatedAt"
            FROM webhook_subscription
            WHERE tenant_id = 'KINTEX'
            ORDER BY created_at DESC, id DESC
            """)
    List<Map<String, Object>> findSubscriptions();

    @Select("""
            SELECT id, event_type AS "eventType", callback_url AS "callbackUrl",
                   description, active, created_at AS "createdAt", updated_at AS "updatedAt"
            FROM webhook_subscription
            WHERE tenant_id = 'KINTEX' AND id = #{id}
            """)
    Map<String, Object> findSubscription(@Param("id") String id);

    /**
     * 부분 수정 — null 필드는 COALESCE 로 미변경. secret_hash 는 blank 이면 미변경.
     * (comparison 연산자·&lt; 미사용 — script 규칙 준수)
     */
    @Update("""
            UPDATE webhook_subscription SET
                callback_url = COALESCE(#{callbackUrl}, callback_url),
                description  = COALESCE(#{description}, description),
                active       = COALESCE(#{active}, active),
                secret_hash  = CASE WHEN #{secretHash} IS NULL OR #{secretHash} = '' THEN secret_hash ELSE #{secretHash} END,
                updated_at   = now()
            WHERE tenant_id = 'KINTEX' AND id = #{id}
            """)
    int updateSubscription(@Param("id") String id,
                           @Param("callbackUrl") String callbackUrl,
                           @Param("secretHash") String secretHash,
                           @Param("description") String description,
                           @Param("active") Boolean active);

    @org.apache.ibatis.annotations.Delete(
            "DELETE FROM webhook_subscription WHERE tenant_id = 'KINTEX' AND id = #{id}")
    int deleteSubscription(@Param("id") String id);

    // ── 아웃바운드 발송 큐(스텁) ──
    @Insert("""
            INSERT INTO webhook_delivery
                (tenant_id, id, subscription_id, event_type, payload_json, status, note)
            VALUES ('KINTEX', #{id}, #{subscriptionId}, #{eventType}, #{payloadJson}, 'disabled', #{note})
            """)
    int insertDelivery(@Param("id") String id,
                       @Param("subscriptionId") String subscriptionId,
                       @Param("eventType") String eventType,
                       @Param("payloadJson") String payloadJson,
                       @Param("note") String note);

    @Select("""
            SELECT id, subscription_id AS "subscriptionId", event_type AS "eventType",
                   status, note, created_at AS "createdAt"
            FROM webhook_delivery
            WHERE tenant_id = 'KINTEX'
            ORDER BY created_at DESC, id DESC
            """)
    List<Map<String, Object>> findDeliveries();

    // ── 인바운드 엔드포인트 ──
    @Insert("""
            INSERT INTO webhook_inbound_endpoint
                (tenant_id, id, token, secret_enc, source_label, active, created_by)
            VALUES ('KINTEX', #{id}, #{token}, #{secretEnc}, #{sourceLabel}, true, #{createdBy})
            """)
    int insertInboundEndpoint(@Param("id") String id,
                              @Param("token") String token,
                              @Param("secretEnc") String secretEnc,
                              @Param("sourceLabel") String sourceLabel,
                              @Param("createdBy") String createdBy);

    /** secret_enc 는 응답 목록에서 제외. */
    @Select("""
            SELECT id, token, source_label AS "sourceLabel", active, created_at AS "createdAt"
            FROM webhook_inbound_endpoint
            WHERE tenant_id = 'KINTEX'
            ORDER BY created_at DESC, id DESC
            """)
    List<Map<String, Object>> findInboundEndpoints();

    /** 인바운드 검증 전용 — active 토큰의 봉인 시크릿(내부 경로만, 응답 절대 금지). */
    @Select("""
            SELECT secret_enc AS "secretEnc"
            FROM webhook_inbound_endpoint
            WHERE token = #{token} AND active = true
            """)
    Map<String, Object> findInboundSecretEnc(@Param("token") String token);

    // ── 인바운드 이벤트 로그 ──
    @Insert("""
            INSERT INTO webhook_inbound_event
                (tenant_id, id, endpoint_token, event_type, payload_json, signature_valid)
            VALUES ('KINTEX', #{id}, #{token}, #{eventType}, #{payloadJson}, #{signatureValid})
            """)
    int insertInboundEvent(@Param("id") String id,
                           @Param("token") String token,
                           @Param("eventType") String eventType,
                           @Param("payloadJson") String payloadJson,
                           @Param("signatureValid") boolean signatureValid);
}
