<?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="auditLog">

  <!-- 감사 로그 목록 조회 (페이지네이션 + 필터) -->
  <select id="selectAuditLogs" parameterType="map" resultType="map">
    SELECT SAL.*, CI.COMPANY_NAME
    FROM SYSTEM_AUDIT_LOG SAL
    LEFT JOIN COMPANY_MNG CI ON SAL.COMPANY_CODE = CI.COMPANY_CODE
    WHERE 1=1
    <if test="filter_company != null and filter_company != ''">
      AND (SAL.COMPANY_CODE = #{filter_company} OR SAL.COMPANY_CODE = '*')
    </if>
    <if test="user_id != null and user_id != ''">
      AND SAL.USER_ID = #{user_id}
    </if>
    <if test="resource_type != null and resource_type != ''">
      AND SAL.RESOURCE_TYPE = #{resource_type}
    </if>
    <if test="action != null and action != ''">
      AND SAL.ACTION = #{action}
    </if>
    <if test="table_name != null and table_name != ''">
      AND SAL.TABLE_NAME = #{table_name}
    </if>
    <if test="date_from != null and date_from != ''">
      AND SAL.CREATED_AT >= #{date_from}::TIMESTAMPTZ
    </if>
    <if test="date_to != null and date_to != ''">
      AND SAL.CREATED_AT &lt;= #{date_to}::TIMESTAMPTZ
    </if>
    <if test="search != null and search != ''">
      AND (SAL.SUMMARY ILIKE CONCAT('%', #{search}, '%')
        OR SAL.RESOURCE_NAME ILIKE CONCAT('%', #{search}, '%')
        OR SAL.USER_NAME ILIKE CONCAT('%', #{search}, '%'))
    </if>
    ORDER BY SAL.CREATED_AT DESC
    LIMIT #{limit} OFFSET #{offset}
  </select>

  <!-- 감사 로그 총 건수 -->
  <select id="selectAuditLogsCount" parameterType="map" resultType="int">
    SELECT COUNT(*)
    FROM SYSTEM_AUDIT_LOG SAL
    WHERE 1=1
    <if test="filter_company != null and filter_company != ''">
      AND (SAL.COMPANY_CODE = #{filter_company} OR SAL.COMPANY_CODE = '*')
    </if>
    <if test="user_id != null and user_id != ''">
      AND SAL.USER_ID = #{user_id}
    </if>
    <if test="resource_type != null and resource_type != ''">
      AND SAL.RESOURCE_TYPE = #{resource_type}
    </if>
    <if test="action != null and action != ''">
      AND SAL.ACTION = #{action}
    </if>
    <if test="table_name != null and table_name != ''">
      AND SAL.TABLE_NAME = #{table_name}
    </if>
    <if test="date_from != null and date_from != ''">
      AND SAL.CREATED_AT >= #{date_from}::TIMESTAMPTZ
    </if>
    <if test="date_to != null and date_to != ''">
      AND SAL.CREATED_AT &lt;= #{date_to}::TIMESTAMPTZ
    </if>
    <if test="search != null and search != ''">
      AND (SAL.SUMMARY ILIKE CONCAT('%', #{search}, '%')
        OR SAL.RESOURCE_NAME ILIKE CONCAT('%', #{search}, '%')
        OR SAL.USER_NAME ILIKE CONCAT('%', #{search}, '%'))
    </if>
  </select>

  <!-- 일별 감사 로그 건수 -->
  <select id="selectDailyCounts" parameterType="map" resultType="map">
    SELECT DATE(CREATED_AT) AS DATE, COUNT(*)::INT AS COUNT
    FROM SYSTEM_AUDIT_LOG
    WHERE CREATED_AT >= NOW() - INTERVAL '1 day' * #{days}
    <if test="company_code != null and company_code != ''">
      AND (COMPANY_CODE = #{company_code} OR COMPANY_CODE = '*')
    </if>
    GROUP BY DATE(CREATED_AT)
    ORDER BY DATE DESC
  </select>

  <!-- 리소스 타입별 건수 -->
  <select id="selectResourceTypeCounts" parameterType="map" resultType="map">
    SELECT RESOURCE_TYPE, COUNT(*)::INT AS COUNT
    FROM SYSTEM_AUDIT_LOG
    WHERE CREATED_AT >= NOW() - INTERVAL '1 day' * #{days}
    <if test="company_code != null and company_code != ''">
      AND (COMPANY_CODE = #{company_code} OR COMPANY_CODE = '*')
    </if>
    GROUP BY RESOURCE_TYPE
    ORDER BY COUNT DESC
  </select>

  <!-- 액션별 건수 -->
  <select id="selectActionCounts" parameterType="map" resultType="map">
    SELECT ACTION, COUNT(*)::INT AS COUNT
    FROM SYSTEM_AUDIT_LOG
    WHERE CREATED_AT >= NOW() - INTERVAL '1 day' * #{days}
    <if test="company_code != null and company_code != ''">
      AND (COMPANY_CODE = #{company_code} OR COMPANY_CODE = '*')
    </if>
    GROUP BY ACTION
    ORDER BY COUNT DESC
  </select>

  <!-- 상위 사용자 (로그 건수 기준) -->
  <select id="selectTopUsers" parameterType="map" resultType="map">
    SELECT USER_ID, COALESCE(MAX(USER_NAME), USER_ID) AS USER_NAME, COUNT(*)::INT AS COUNT
    FROM SYSTEM_AUDIT_LOG
    WHERE CREATED_AT >= NOW() - INTERVAL '1 day' * #{days}
    <if test="company_code != null and company_code != ''">
      AND (COMPANY_CODE = #{company_code} OR COMPANY_CODE = '*')
    </if>
    GROUP BY USER_ID
    ORDER BY COUNT DESC
    LIMIT 10
  </select>

  <!-- 감사 로그가 있는 활성 사용자 목록 -->
  <select id="selectAuditLogUsers" parameterType="map" resultType="map">
    SELECT
      U.USER_ID,
      U.USER_NAME,
      COALESCE(SAL.LOG_COUNT, '0')::INT AS COUNT
    FROM USER_INFO U
    LEFT JOIN (
      SELECT USER_ID, COUNT(*) AS LOG_COUNT
      FROM SYSTEM_AUDIT_LOG
      GROUP BY USER_ID
    ) SAL ON U.USER_ID = SAL.USER_ID
    WHERE LOWER(U.STATUS) = 'active'
    <if test="company_code != null and company_code != ''">
      AND (U.COMPANY_CODE = #{company_code} OR U.COMPANY_CODE = '*')
    </if>
    <if test="exclude_wildcard != null and exclude_wildcard == true">
      AND U.COMPANY_CODE != '*'
    </if>
    ORDER BY COUNT DESC, U.USER_NAME ASC
  </select>

  <!-- 감사 로그 INSERT.
       PROCESSOR_ID/PROCESSOR_NAME 은 대무(代務) 처리 추적용 (086 마이그레이션 이후).
       평시는 USER_ID == PROCESSOR_ID. -->
  <insert id="insertAuditLog" parameterType="map">
    INSERT INTO SYSTEM_AUDIT_LOG (
      COMPANY_CODE, USER_ID, USER_NAME, ACTION, RESOURCE_TYPE,
      RESOURCE_ID, RESOURCE_NAME, TABLE_NAME, SUMMARY, CHANGES,
      IP_ADDRESS, REQUEST_PATH,
      PROCESSOR_ID, PROCESSOR_NAME
    ) VALUES (
      #{company_code}, #{user_id}, #{user_name}, #{action}, #{resource_type},
      #{resource_id}, #{resource_name}, #{table_name}, #{summary},
      CAST(#{changes} AS JSONB),
      #{ip_address}, #{request_path},
      #{processor_id}, #{processor_name}
    )
  </insert>

  <!-- 처리자 이름 lookup (대무 시 USER_INFO 에서 1회 조회). -->
  <select id="selectUserNameById" parameterType="map" resultType="string">
    SELECT USER_NAME
    FROM USER_INFO
    WHERE USER_ID = #{user_id}
      AND (COMPANY_CODE = #{company_code} OR COMPANY_CODE = '*')
    LIMIT 1
  </select>

</mapper>
