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

  <!-- ========== 레이아웃 검색 조건 ========== -->
  <sql id="layoutSearchCondition">
    <if test="keyword != null and keyword != ''">
      AND (L.LAYOUT_NAME ILIKE '%' || #{keyword} || '%'
           OR L.DESCRIPTION ILIKE '%' || #{keyword} || '%')
    </if>
    <if test="external_db_connection_id != null">
      AND L.EXTERNAL_DB_CONNECTION_ID = #{external_db_connection_id}
    </if>
    <if test="warehouse_key != null and warehouse_key != ''">
      AND L.WAREHOUSE_KEY = #{warehouse_key}
    </if>
  </sql>

  <!-- ========== 레이아웃 목록 ========== -->
  <select id="getDigitalTwinLayoutList" parameterType="map" resultType="map">
    SELECT
        L.*
        , U1.USER_NAME AS CREATED_BY_NAME
        , U2.USER_NAME AS UPDATED_BY_NAME
        , COUNT(O.ID) AS OBJECT_COUNT
    FROM DIGITAL_TWIN_LAYOUT L
    LEFT JOIN USER_INFO U1
        ON L.CREATED_BY = U1.USER_ID
    LEFT JOIN USER_INFO U2
        ON L.UPDATED_BY = U2.USER_ID
    LEFT JOIN DIGITAL_TWIN_OBJECTS O
        ON L.ID = O.LAYOUT_ID
    WHERE 1=1
    <if test='company_code != null and company_code != "*"'>
      AND (L.COMPANY_CODE = #{company_code} OR L.COMPANY_CODE = '*')
    </if>
    <include refid="layoutSearchCondition"/>
    GROUP BY L.ID, U1.USER_NAME, U2.USER_NAME
    ORDER BY L.UPDATED_DATE DESC
    <include refid="common.pagination"/>
  </select>

  <select id="getDigitalTwinLayoutListCnt" parameterType="map" resultType="int">
    SELECT COUNT(DISTINCT L.ID)
    FROM DIGITAL_TWIN_LAYOUT L
    WHERE 1=1
    <if test='company_code != null and company_code != "*"'>
      AND (L.COMPANY_CODE = #{company_code} OR L.COMPANY_CODE = '*')
    </if>
    <include refid="layoutSearchCondition"/>
  </select>

  <!-- ========== 레이아웃 상세 ========== -->
  <select id="getDigitalTwinLayoutInfo" parameterType="map" resultType="map">
    SELECT L.*
    FROM DIGITAL_TWIN_LAYOUT L
    WHERE L.ID = #{id}
    <if test='company_code != null and company_code != "*"'>
      AND (L.COMPANY_CODE = #{company_code} OR L.COMPANY_CODE = '*')
    </if>
  </select>

  <!-- ========== 레이아웃 객체 목록 ========== -->
  <select id="getDigitalTwinObjectListByLayoutId" parameterType="map" resultType="map">
    SELECT *
    FROM DIGITAL_TWIN_OBJECTS
    WHERE LAYOUT_ID = #{layout_id}
    ORDER BY DISPLAY_ORDER ASC, CREATED_DATE ASC
  </select>

  <!-- ========== 레이아웃 생성 ========== -->
  <insert id="insertDigitalTwinLayout" parameterType="map" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO DIGITAL_TWIN_LAYOUT (
        COMPANY_CODE
        , EXTERNAL_DB_CONNECTION_ID
        , WAREHOUSE_KEY
        , LAYOUT_NAME
        , DESCRIPTION
        , HIERARCHY_CONFIG
        , CREATED_BY
        , UPDATED_BY
        , CREATED_DATE
        , UPDATED_DATE
    ) VALUES (
        #{company_code}
        , #{external_db_connection_id}
        , #{warehouse_key}
        , #{layout_name}
        , #{description}
        , <choose>
            <when test="hierarchy_config != null">#{hierarchy_config}::jsonb</when>
            <otherwise>NULL</otherwise>
          </choose>
        , #{created_by}
        , #{created_by}
        , NOW()
        , NOW()
    )
  </insert>

  <!-- ========== 레이아웃 객체 생성 ========== -->
  <insert id="insertDigitalTwinObject" parameterType="map" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO DIGITAL_TWIN_OBJECTS (
        LAYOUT_ID
        , OBJECT_TYPE
        , OBJECT_NAME
        , POSITION_X
        , POSITION_Y
        , POSITION_Z
        , SIZE_X
        , SIZE_Y
        , SIZE_Z
        , ROTATION
        , COLOR
        , AREA_KEY
        , LOCA_KEY
        , LOC_TYPE
        , MATERIAL_COUNT
        , MATERIAL_PREVIEW_HEIGHT
        , PARENT_ID
        , DISPLAY_ORDER
        , LOCKED
        , HIERARCHY_LEVEL
        , PARENT_KEY
        , EXTERNAL_KEY
        , CREATED_DATE
    ) VALUES (
        #{layout_id}
        , #{type}
        , #{name}
        , #{pos_x}
        , #{pos_y}
        , #{pos_z}
        , #{size_x}
        , #{size_y}
        , #{size_z}
        , COALESCE(#{rotation}, 0)
        , #{color}
        , #{area_key}
        , #{loca_key}
        , #{loc_type}
        , COALESCE(#{material_count}, 0)
        , #{material_preview_height}
        , #{parent_db_id}
        , COALESCE(#{display_order}, 0)
        , COALESCE(#{locked}, FALSE)
        , COALESCE(#{hierarchy_level}, 1)
        , #{parent_key}
        , #{external_key}
        , NOW()
    )
  </insert>

  <!-- ========== 레이아웃 수정 ========== -->
  <update id="updateDigitalTwinLayout" parameterType="map">
    UPDATE DIGITAL_TWIN_LAYOUT
    SET
        LAYOUT_NAME = COALESCE(#{layout_name}, LAYOUT_NAME)
        , DESCRIPTION = COALESCE(#{description}, DESCRIPTION)
        , HIERARCHY_CONFIG =
            <choose>
                <when test="hierarchy_config != null">#{hierarchy_config}::jsonb</when>
                <otherwise>HIERARCHY_CONFIG</otherwise>
            </choose>
        , EXTERNAL_DB_CONNECTION_ID = COALESCE(#{external_db_connection_id}, EXTERNAL_DB_CONNECTION_ID)
        , WAREHOUSE_KEY = COALESCE(#{warehouse_key}, WAREHOUSE_KEY)
        , UPDATED_BY = COALESCE(#{updated_by}, UPDATED_BY)
        , UPDATED_DATE = NOW()
    WHERE ID = #{id}
    <if test='company_code != null and company_code != "*"'>
      AND (COMPANY_CODE = #{company_code} OR COMPANY_CODE = '*')
    </if>
  </update>

  <!-- ========== 레이아웃 삭제 ========== -->
  <delete id="deleteDigitalTwinLayout" parameterType="map">
    DELETE FROM DIGITAL_TWIN_LAYOUT
    WHERE ID = #{id}
    <if test='company_code != null and company_code != "*"'>
      AND (COMPANY_CODE = #{company_code} OR COMPANY_CODE = '*')
    </if>
  </delete>

  <!-- ========== 레이아웃 객체 전체 삭제 ========== -->
  <delete id="deleteDigitalTwinObjectsByLayoutId" parameterType="map">
    DELETE FROM DIGITAL_TWIN_OBJECTS
    WHERE LAYOUT_ID = #{layout_id}
  </delete>

  <!-- ========== 매핑 템플릿 검색 조건 ========== -->
  <sql id="templateSearchCondition">
    <if test="keyword != null and keyword != ''">
      AND (NAME ILIKE '%' || #{keyword} || '%'
           OR DESCRIPTION ILIKE '%' || #{keyword} || '%')
    </if>
    <if test="external_db_connection_id != null">
      AND EXTERNAL_DB_CONNECTION_ID = #{external_db_connection_id}
    </if>
    <if test="layout_type != null and layout_type != ''">
      AND LAYOUT_TYPE = #{layout_type}
    </if>
  </sql>

  <!-- ========== 매핑 템플릿 목록 ========== -->
  <select id="getDigitalTwinTemplateList" parameterType="map" resultType="map">
    SELECT *
    FROM DIGITAL_TWIN_LAYOUT_TEMPLATE
    WHERE 1=1
    <include refid="common.companyCodeFilter"/>
    <include refid="templateSearchCondition"/>
    ORDER BY UPDATED_DATE DESC, NAME ASC
    <include refid="common.pagination"/>
  </select>

  <select id="getDigitalTwinTemplateListCnt" parameterType="map" resultType="int">
    SELECT COUNT(*)
    FROM DIGITAL_TWIN_LAYOUT_TEMPLATE
    WHERE 1=1
    <include refid="common.companyCodeFilter"/>
    <include refid="templateSearchCondition"/>
  </select>

  <!-- ========== 매핑 템플릿 상세 ========== -->
  <select id="getDigitalTwinTemplateInfo" parameterType="map" resultType="map">
    SELECT *
    FROM DIGITAL_TWIN_LAYOUT_TEMPLATE
    WHERE ID = #{id}
    <include refid="common.companyCodeFilter"/>
  </select>

  <!-- ========== 매핑 템플릿 생성 ========== -->
  <insert id="insertDigitalTwinTemplate" parameterType="map" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO DIGITAL_TWIN_LAYOUT_TEMPLATE (
        COMPANY_CODE
        , NAME
        , DESCRIPTION
        , EXTERNAL_DB_CONNECTION_ID
        , LAYOUT_TYPE
        , CONFIG
        , CREATED_BY
        , CREATED_DATE
        , UPDATED_BY
        , UPDATED_DATE
    ) VALUES (
        #{company_code}
        , #{name}
        , #{description}
        , #{external_db_connection_id}
        , COALESCE(#{layout_type}, 'yard-3d')
        , #{config}::jsonb
        , #{created_by}
        , NOW()
        , #{created_by}
        , NOW()
    )
  </insert>

</mapper>
