package com.zioinfo.kintex.work.approval;

import org.apache.ibatis.annotations.*;

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

/**
 * 전자결재 매퍼(F028). 결재 문서·결재선·이력 CRUD 및 결재함 조회.
 * ★ &lt;script&gt; 내 비교연산은 escape(&gt;) 사용 — MapperAnnotationParseTest 회귀 방지.
 */
@Mapper
public interface ApprovalMapper {

    // ─────────────────────────────── 결재 문서
    @Insert("""
            INSERT INTO approval (id, tenant_id, event_id, doc_type, title, content, ref_type, ref_id,
                                  drafter_id, drafter_name, status, cur_step, version)
            VALUES (#{id}, COALESCE(#{tenantId},'kintex'), #{eventId}, COALESCE(#{docType},'GENERAL'),
                    #{title}, #{content}, #{refType}, #{refId}, #{drafterId}, #{drafterName},
                    'DRAFT', 0, 1)
            """)
    int insert(Map<String, Object> p);

    @Select("""
            SELECT id, tenant_id AS "tenantId", event_id AS "eventId", doc_type AS "docType",
                   title, content, ref_type AS "refType", ref_id AS "refId",
                   drafter_id AS "drafterId", drafter_name AS "drafterName",
                   status, cur_step AS "curStep", version,
                   to_char(submitted_at AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"') AS "submittedAt",
                   to_char(completed_at AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"') AS "completedAt",
                   to_char(created_at   AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"') AS "createdAt"
            FROM approval WHERE id = #{id}
            """)
    Map<String, Object> findById(@Param("id") String id);

    @Update("""
            <script>
            UPDATE approval
            <set>
              <if test="title != null">title=#{title},</if>
              <if test="content != null">content=#{content},</if>
              <if test="docType != null">doc_type=#{docType},</if>
              <if test="refType != null">ref_type=#{refType},</if>
              <if test="refId != null">ref_id=#{refId},</if>
              <if test="status != null">status=#{status},</if>
              <if test="curStep != null">cur_step=#{curStep},</if>
              <if test="version != null">version=#{version},</if>
              <if test="submittedAt != null">submitted_at=now(),</if>
              <if test="completedAt != null">completed_at=now(),</if>
              <if test="clearCompleted != null">completed_at=NULL,</if>
              updated_at=now()
            </set>
            WHERE id = #{id}
            </script>
            """)
    int updateDoc(Map<String, Object> p);

    // ─────────────────────────────── 결재함 조회(box: DRAFT/DRAFTED/PENDING/DONE)
    @Select("""
            <script>
            SELECT a.id, a.doc_type AS "docType", a.title, a.status,
                   a.drafter_id AS "drafterId", a.drafter_name AS "drafterName",
                   a.cur_step AS "curStep", a.version,
                   a.event_id AS "eventId", a.ref_type AS "refType", a.ref_id AS "refId",
                   (SELECT count(*) FROM approval_line l WHERE l.approval_id = a.id) AS "totalSteps",
                   to_char(a.submitted_at AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"') AS "submittedAt",
                   to_char(a.created_at   AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"') AS "createdAt"
            FROM approval a
            <where>
              a.tenant_id = #{tenantId}
              <choose>
                <when test="box == 'DRAFT'">
                  AND a.drafter_id = #{me} AND a.status = 'DRAFT'
                </when>
                <when test="box == 'DRAFTED'">
                  AND a.drafter_id = #{me}
                </when>
                <when test="box == 'PENDING'">
                  AND a.status IN ('SUBMITTED','IN_PROGRESS')
                  AND EXISTS (SELECT 1 FROM approval_line l
                              WHERE l.approval_id = a.id AND l.approver_id = #{me}
                                AND l.line_status = 'CURRENT')
                </when>
                <when test="box == 'DONE'">
                  AND EXISTS (SELECT 1 FROM approval_line l
                              WHERE l.approval_id = a.id AND l.approver_id = #{me}
                                AND l.line_status IN ('APPROVED','REJECTED'))
                </when>
              </choose>
              <if test="keyword != null and keyword != ''">AND a.title ILIKE '%'||#{keyword}||'%'</if>
            </where>
            ORDER BY a.updated_at DESC LIMIT #{size} OFFSET #{offset}
            </script>
            """)
    List<Map<String, Object>> searchBox(Map<String, Object> q);

    @Select("""
            <script>
            SELECT count(*)
            FROM approval a
            <where>
              a.tenant_id = #{tenantId}
              <choose>
                <when test="box == 'DRAFT'">
                  AND a.drafter_id = #{me} AND a.status = 'DRAFT'
                </when>
                <when test="box == 'DRAFTED'">
                  AND a.drafter_id = #{me}
                </when>
                <when test="box == 'PENDING'">
                  AND a.status IN ('SUBMITTED','IN_PROGRESS')
                  AND EXISTS (SELECT 1 FROM approval_line l
                              WHERE l.approval_id = a.id AND l.approver_id = #{me}
                                AND l.line_status = 'CURRENT')
                </when>
                <when test="box == 'DONE'">
                  AND EXISTS (SELECT 1 FROM approval_line l
                              WHERE l.approval_id = a.id AND l.approver_id = #{me}
                                AND l.line_status IN ('APPROVED','REJECTED'))
                </when>
              </choose>
              <if test="keyword != null and keyword != ''">AND a.title ILIKE '%'||#{keyword}||'%'</if>
            </where>
            </script>
            """)
    long countBox(Map<String, Object> q);

    // ─────────────────────────────── 결재선
    @Delete("DELETE FROM approval_line WHERE approval_id = #{approvalId}")
    int deleteLines(@Param("approvalId") String approvalId);

    @Insert("""
            INSERT INTO approval_line (id, approval_id, step_no, approver_id, approver_name, line_status)
            VALUES (#{id}, #{approvalId}, #{stepNo}, #{approverId}, #{approverName}, 'WAIT')
            """)
    int insertLine(Map<String, Object> p);

    @Select("""
            SELECT id, step_no AS "stepNo", approver_id AS "approverId", approver_name AS "approverName",
                   line_status AS "lineStatus",
                   to_char(acted_at AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"') AS "actedAt",
                   comment
            FROM approval_line WHERE approval_id = #{approvalId} ORDER BY step_no ASC
            """)
    List<Map<String, Object>> findLines(@Param("approvalId") String approvalId);

    @Update("""
            <script>
            UPDATE approval_line
            <set>
              line_status=#{lineStatus},
              <if test="comment != null">comment=#{comment},</if>
              <if test="acted != null">acted_at=now(),</if>
            </set>
            WHERE id = #{id}
            </script>
            """)
    int updateLine(Map<String, Object> p);

    /** 상신/재상신 시 전 단계 초기화(WAIT·의견/처리시각 제거). */
    @Update("""
            UPDATE approval_line
            SET line_status='WAIT', acted_at=NULL, comment=NULL
            WHERE approval_id = #{approvalId}
            """)
    int resetLines(@Param("approvalId") String approvalId);

    // ─────────────────────────────── 이력
    @Insert("""
            INSERT INTO approval_history (id, approval_id, step_no, actor_id, actor_name, action, comment)
            VALUES (#{id}, #{approvalId}, #{stepNo}, #{actorId}, #{actorName}, #{action}, #{comment})
            """)
    int insertHistory(Map<String, Object> p);

    @Select("""
            SELECT id, step_no AS "stepNo", actor_id AS "actorId", actor_name AS "actorName",
                   action, comment,
                   to_char(acted_at AT TIME ZONE 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"') AS "actedAt"
            FROM approval_history WHERE approval_id = #{approvalId} ORDER BY acted_at ASC, id ASC
            """)
    List<Map<String, Object>> findHistory(@Param("approvalId") String approvalId);
}
