<?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">
<!--
  BoothMapper — M2 플로어플랜 공간 SQL (PostGIS). SRID 0 = 홀 로컬 평면(미터).
  판매면적 ST_Area · 통로폭 ST_Distance/ST_DWithin · 비상구 차단 ST_Intersects/ST_Buffer.

  파라미터 계약(백엔드 조립):
   - upsertLayout params: {layoutId?, eventId, hallId, version, name, status}
   - replaceBooths booths[i]: {boothId?, boothNo, type, wkt(POLYGON WKT), sizeW, sizeD,
                               heightM, floorLoad, assignedCompanyName, premium}
     · wkt 예: 'POLYGON((0 0,6 0,6 3,0 3,0 0))'
   - findBooths 반환: polygon 은 GeoJSON 문자열(polygonJson) — 백엔드가 좌표배열로 파싱.
-->
<mapper namespace="com.zioinfo.kintex.module.m2.mapper.BoothMapper">

    <!-- 배치안 헤더(version=null → 최신). -->
    <select id="findLayout" resultType="map">
        SELECT id     AS "layoutId",
               version,
               name,
               status,
               to_char(updated_at AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS"Z"') AS "updatedAt"
        FROM layout
        WHERE event_id = #{eventId}
          AND hall_id  = #{hallId}
        <if test="version != null">
          AND version = #{version}
        </if>
        ORDER BY version DESC
        LIMIT 1
    </select>

    <!-- 배치안 부스 목록(폴리곤은 GeoJSON). -->
    <select id="findBooths" resultType="map">
        SELECT id                    AS "boothId",
               booth_no              AS "boothNo",
               booth_type            AS "type",
               ST_AsGeoJSON(geom)    AS "polygonJson",
               size_w_m              AS "sizeW",
               size_d_m              AS "sizeD",
               height_m              AS "heightM",
               floor_load_t_per_m2   AS "floorLoadTPerM2",
               assigned_company_name AS "assignedCompanyName",
               premium
        FROM booth
        WHERE layout_id = #{layoutId}
        ORDER BY booth_no
    </select>

    <!-- 배치안 헤더 upsert → layoutId 반환. INSERT ... RETURNING(PG). -->
    <select id="upsertLayout" resultType="string">
        INSERT INTO layout (id, event_id, hall_id, version, name, status, updated_at)
        VALUES (COALESCE(#{params.layoutId}, gen_random_uuid()::text),
                #{params.eventId}, #{params.hallId},
                COALESCE(#{params.version}, 1),
                #{params.name},
                COALESCE(#{params.status}, 'draft'),
                now())
        ON CONFLICT (event_id, hall_id, version) DO UPDATE
            SET name       = EXCLUDED.name,
                status     = EXCLUDED.status,
                updated_at = now()
        RETURNING id
    </select>

    <!-- 배치안 단위 부스 교체 저장: 데이터 수정 CTE 로 삭제 후 일괄 INSERT(단일 statement). -->
    <insert id="replaceBooths">
        WITH del AS (DELETE FROM booth WHERE layout_id = #{layoutId})
        INSERT INTO booth (id, layout_id, booth_no, booth_type, geom,
                           size_w_m, size_d_m, height_m, floor_load_t_per_m2,
                           assigned_company_name, premium)
        VALUES
        <foreach collection="booths" item="b" separator=",">
            (COALESCE(#{b.boothId}, gen_random_uuid()::text),
             #{layoutId}, #{b.boothNo}, #{b.type},
             ST_GeomFromText(#{b.wkt}, 0),
             #{b.sizeW}, #{b.sizeD}, #{b.heightM}, #{b.floorLoad},
             #{b.assignedCompanyName}, #{b.premium})
        </foreach>
    </insert>

    <!-- 판매 면적 합계(㎡). -->
    <select id="sumSalesArea" resultType="double">
        SELECT COALESCE(SUM(ST_Area(geom)), 0)
        FROM booth
        WHERE layout_id = #{layoutId}
    </select>

    <!-- 최소 통로 폭(m): 10m 이내 인접 부스 폴리곤 쌍의 최소 이격거리. -->
    <select id="minAisleWidth" resultType="double">
        SELECT MIN(ST_Distance(a.geom, b.geom))
        FROM booth a
        JOIN booth b
             ON a.layout_id = b.layout_id
            AND a.id <![CDATA[<]]> b.id
            AND ST_DWithin(a.geom, b.geom, 10)
        WHERE a.layout_id = #{layoutId}
    </select>

    <!-- 비상구를 차단하는 부스 수: 비상구 이격 버퍼와 교차하는 부스. -->
    <select id="countExitsBlocked" resultType="int">
        SELECT COUNT(DISTINCT bo.id)
        FROM booth bo
        JOIN hall_exit ex ON ex.hall_id = #{hallId}
        WHERE bo.layout_id = #{layoutId}
          AND ST_Intersects(bo.geom, ST_Buffer(ex.geom, ex.clearance_m))
    </select>

    <!-- 내부가 겹치는 부스 쌍 수: 경계만 맞닿는(ST_Touches) 경우는 제외하고 내부 교차만 계수.
         ST_Overlaps는 포함/동일을 놓치므로 ST_Intersects AND NOT ST_Touches 로 포괄 판정. -->
    <select id="countOverlappingBooths" resultType="int">
        SELECT COUNT(*)
        FROM booth a
        JOIN booth b
             ON a.layout_id = b.layout_id
            AND a.id <![CDATA[<]]> b.id
            AND ST_Intersects(a.geom, b.geom)
            AND NOT ST_Touches(a.geom, b.geom)
        WHERE a.layout_id = #{layoutId}
    </select>

</mapper>
