<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.datacenter.mapper.ExperienceGiftInviteGrantMapper">

    <resultMap id="candidateMap" type="com.datacenter.job.vo.InviteGrantCandidateVo">
        <result column="positionId"      property="positionId"/>
        <result column="memberId"        property="memberId"/>
        <result column="inviterId"       property="inviterId"/>
        <result column="inviterEmail"    property="inviterEmail"/>
        <result column="openValue"       property="openValue"/>
        <result column="holdMinutes"     property="holdMinutes"/>
        <result column="coinSymbol"      property="coinSymbol"/>
        <result column="productId"       property="productId"/>
        <result column="productName"     property="productName"/>
        <result column="amount"          property="amount"/>
        <result column="maxProfitPerCard" property="maxProfitPerCard"/>
        <result column="validityDays"    property="validityDays"/>
        <result column="totalQuantity"   property="totalQuantity"/>
        <result column="issuedCount"     property="issuedCount"/>
        <result column="perUserLimit"    property="perUserLimit"/>
        <result column="leverage"        property="leverage"/>
        <result column="clientIp"        property="clientIp"/>
    </resultMap>

    <!--
        扫描满足直邀发放条件的合约仓位，无论是否已平仓：

        【持仓中】status IN (0,1)：用 NOW() 计算已持仓时长，达到产品配置的 min_hold_minutes 即可触发。
        【已平仓】status = 2：用实际平仓时长（close_time - open_time）判断，无额外时间窗口限制。
                              数据范围由产品 activity_start_time JOIN 条件自然收敛，
                              NOT EXISTS 去重日志保证每个仓位仅处理一次。

        其他条件：
          - 不限保证金类型（money_type），交易对已由 coin_symbol JOIN 限定
          - total_position * open_price 为开仓价值，需 >= min_open_value
          - 被邀人有邀请关系（member.inviter_id IS NOT NULL）
          - 被邀人注册时间必须在活动开始时间之后（registration_time >= activity_start_time，无结束时间限制）
          - 体验金产品：status=1（启用）、grant_type=1（系统触发）、trigger_type=1（直邀赠送）
          - 活动已开始：activity_start_time <= NOW()（无结束时间限制）
          - total_quantity=0 表示不限量；否则 issued_count < total_quantity
          - NOT EXISTS 去重（唯一键 position_id + product_id）
          - 同一被邀人在同一产品下只触发一次（不管开多少仓位）
    -->
    <select id="findQualifyingCandidates" resultMap="candidateMap">
        SELECT
            p.id                                                              AS positionId,
            p.member_id                                                       AS memberId,
            m.inviter_id                                                      AS inviterId,
            mi.email                                                          AS inviterEmail,
            (p.total_position * p.open_price)                                 AS openValue,
            TIMESTAMPDIFF(MINUTE, p.open_time, IFNULL(p.close_time, NOW()))   AS holdMinutes,
            cc.symbol                                                         AS coinSymbol,
            egp.id                                                            AS productId,
            egp.name                                                          AS productName,
            egp.amount                                                        AS amount,
            egp.max_profit_per_card                                           AS maxProfitPerCard,
            egp.validity_days                                                 AS validityDays,
            egp.total_quantity                                                AS totalQuantity,
            egp.issued_count                                                  AS issuedCount,
            egp.per_user_limit                                                AS perUserLimit,
            egpc.leverage                                                     AS leverage,
            m.registration_ip                                                 AS clientIp
        FROM member_contract_position p
        INNER JOIN member m
            ON m.id = p.member_id
            AND m.inviter_id IS NOT NULL
        INNER JOIN member mi
            ON mi.id = m.inviter_id
        INNER JOIN contract_coin cc
            ON cc.id = p.contract_id
        INNER JOIN experience_gift_product_coin egpc
            ON egpc.coin_symbol = cc.symbol
        INNER JOIN experience_gift_product egp
            ON egp.id            = egpc.product_id
            AND egp.status       = 1
            AND egp.grant_type   = 1
            AND egp.trigger_type = 1
            AND egp.activity_start_time &lt;= NOW()
            AND p.open_time             &gt;= egp.activity_start_time
            AND (p.total_position * p.open_price) &gt;= egp.min_open_value
            AND TIMESTAMPDIFF(MINUTE, p.open_time, IFNULL(p.close_time, NOW())) &gt;= egp.min_hold_minutes
            AND (egp.total_quantity = 0 OR egp.issued_count &lt; egp.total_quantity)
        WHERE p.status IN (0, 1, 2)
          and p.follow_position_id is null
          and p.experience_record_id is null
          AND m.registration_time &gt;= egp.activity_start_time
          AND NOT EXISTS (
              SELECT 1
              FROM experience_gift_invite_grant_log gl
              WHERE gl.position_id = p.id
                AND gl.product_id  = egp.id
          )
          AND NOT EXISTS (
              SELECT 1
              FROM experience_gift_record egr
              WHERE egr.inviter_id = m.id
                AND egr.product_id = egp.id
          )
          AND (
              egp.per_user_limit = 0
              OR (
                  SELECT COUNT(*)
                  FROM experience_gift_record egr
                  WHERE egr.member_id   = m.inviter_id
                    AND egr.product_id  = egp.id
              ) &lt; egp.per_user_limit
          )
    </select>

</mapper>
