<?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.ga.core.mapper.accounting.ContractAccountingEntryMapper">

    <!-- contract, agent 조인 포함 응답 매핑 -->
    <resultMap id="RespMap" type="com.ga.core.vo.accounting.ContractAccountingEntryResp"/>

    <!-- 목록/상세 공통 SELECT 컬럼 -->
    <sql id="joinCols">
        cae.entry_id,
        cae.contract_id,
        ac.policy_no AS contract_no,
        cae.payment_id,
        a.agent_id,
        a.agent_name,
        cae.entry_date,
        cae.debit_account,
        cae.credit_account,
        cae.amount,
        cae.description,
        cae.journal_no,
        cae.created_at
    </sql>

    <!-- 공통 FROM + JOIN -->
    <sql id="joinFrom">
        FROM contract_accounting_entry cae
        JOIN contract ac ON ac.contract_id = cae.contract_id
        JOIN agent    a  ON a.agent_id     = ac.agent_id
    </sql>

    <!-- ===== 목록 조회 ===== -->
    <select id="selectList" resultMap="RespMap">
        SELECT <include refid="joinCols"/>
        <include refid="joinFrom"/>
        <where>
            <if test="contractId != null">AND cae.contract_id = #{contractId}</if>
            <if test="paymentId  != null">AND cae.payment_id  = #{paymentId}</if>
            <if test="entryDateFrom != null">AND cae.entry_date &gt;= #{entryDateFrom}</if>
            <if test="entryDateTo   != null">AND cae.entry_date &lt;= #{entryDateTo}</if>
            <if test="journalNo != null and journalNo != ''">AND cae.journal_no = #{journalNo}</if>
            <!-- unpostedOnly=true이면 미전기(journal_no IS NULL)만 조회 -->
            <if test="unpostedOnly != null and unpostedOnly == true">
                AND cae.journal_no IS NULL
            </if>
            <if test="searchKeyword != null and searchKeyword != ''">
                AND (ac.policy_no LIKE CONCAT('%', #{searchKeyword}, '%')
                  OR a.agent_name LIKE CONCAT('%', #{searchKeyword}, '%'))
            </if>
        </where>
        ORDER BY cae.entry_date DESC, cae.entry_id DESC
    </select>

    <!-- ===== 단건 상세 ===== -->
    <select id="selectDetailById" resultMap="RespMap">
        SELECT <include refid="joinCols"/>
        <include refid="joinFrom"/>
        WHERE cae.entry_id = #{entryId}
    </select>

    <!-- ===== 일괄 INSERT =====
         회계 자동분개 배치 step에서 한 번에 다수 엔트리 저장.
         foreach로 멀티 VALUES 구문 생성.
    -->
    <insert id="insertBatch" useGeneratedKeys="true" keyProperty="entryId">
        INSERT INTO contract_accounting_entry
            (contract_id, payment_id, entry_date,
             debit_account, credit_account, amount, description, settle_month)
        VALUES
        <foreach collection="list" item="e" separator=",">
            (#{e.contractId}, #{e.paymentId}, #{e.entryDate},
             #{e.debitAccount}, #{e.creditAccount}, #{e.amount}, #{e.description}, #{e.settleMonth})
        </foreach>
    </insert>

    <!-- ===== 미전기 분개 정산월 단위 삭제 (재생성 멱등성) ===== -->
    <delete id="deleteUnpostedBySettleMonth">
        DELETE FROM contract_accounting_entry
         WHERE settle_month = #{settleMonth}
           AND journal_no IS NULL
    </delete>

    <!-- ===== 마감 처리 (journalNo 채번) ===== -->
    <update id="closeJournal">
        UPDATE contract_accounting_entry
           SET journal_no = #{journalNo}
         WHERE entry_id IN
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
           AND journal_no IS NULL
    </update>

    <!--
        배치 step용: 정산월 기준 분개 대상 원장 조회.
        recruit_ledger + maintain_ledger UNION → contract_id 포함.
        AccountingEntryGenerateStep에서 호출.
    -->
    <!--
        분개 구조 (원천세 반영, 차변합=대변합 균형):
          (차) 8350 지급수수료 gross  /  (대) 2530 미지급금 net + (대) 2540 예수금 원천세
        ledger 1건당 net leg(8350/2530) + tax leg(8350/2540, 원천세>0 일 때만) 로 분리 생성.
        net = agent_amount − COALESCE(tax_amount, 0)
    -->
    <select id="selectBySettleMonth" resultType="com.ga.core.vo.accounting.ContractAccountingEntryVO">
        <!-- 모집수수료: 미지급금(net) -->
        SELECT l.contract_id, NULL::BIGINT AS payment_id, CURRENT_DATE AS entry_date,
               '8350' AS debit_account, '2530' AS credit_account,
               (l.agent_amount - COALESCE(l.tax_amount, 0)) AS amount,
               CONCAT('모집수수료 미지급금 ', l.settle_month) AS description,
               l.settle_month AS settle_month, NULL AS journal_no
        FROM recruit_ledger l
        WHERE l.settle_month = #{settleMonth} AND l.agent_amount > 0
        UNION ALL
        <!-- 모집수수료: 원천세 예수금 -->
        SELECT l.contract_id, NULL::BIGINT, CURRENT_DATE,
               '8350', '2540', l.tax_amount,
               CONCAT('모집수수료 원천세 ', l.settle_month),
               l.settle_month, NULL
        FROM recruit_ledger l
        WHERE l.settle_month = #{settleMonth} AND l.agent_amount > 0
          AND COALESCE(l.tax_amount, 0) > 0
        UNION ALL
        <!-- 유지수수료: 미지급금(net) -->
        SELECT l.contract_id, NULL::BIGINT, CURRENT_DATE,
               '8350', '2530',
               (l.agent_amount - COALESCE(l.tax_amount, 0)),
               CONCAT('유지수수료 미지급금 ', l.settle_month),
               l.settle_month, NULL
        FROM maintain_ledger l
        WHERE l.settle_month = #{settleMonth} AND l.agent_amount > 0
        UNION ALL
        <!-- 유지수수료: 원천세 예수금 -->
        SELECT l.contract_id, NULL::BIGINT, CURRENT_DATE,
               '8350', '2540', l.tax_amount,
               CONCAT('유지수수료 원천세 ', l.settle_month),
               l.settle_month, NULL
        FROM maintain_ledger l
        WHERE l.settle_month = #{settleMonth} AND l.agent_amount > 0
          AND COALESCE(l.tax_amount, 0) > 0
    </select>

</mapper>
