<?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.tasteby.mapper.RestaurantMapper">

    <!-- ===== Result Maps ===== -->

    <resultMap id="restaurantMap" type="Restaurant">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="address" column="address"/>
        <result property="region" column="region"/>
        <result property="latitude" column="latitude"/>
        <result property="longitude" column="longitude"/>
        <result property="cuisineType" column="cuisine_type"/>
        <result property="priceRange" column="price_range"/>
        <result property="phone" column="phone"/>
        <result property="website" column="website"/>
        <result property="googlePlaceId" column="google_place_id"/>
        <result property="tablingUrl" column="tabling_url"/>
        <result property="catchtableUrl" column="catchtable_url"/>
        <result property="businessStatus" column="business_status"/>
        <result property="rating" column="rating"/>
        <result property="ratingCount" column="rating_count"/>
        <result property="updatedAt" column="updated_at"/>
        <result property="hidden" column="hidden" javaType="java.lang.Boolean"/>
        <result property="hiddenReason" column="hidden_reason"/>
        <result property="verifiedAt" column="verified_at"/>
    </resultMap>

    <!-- ===== Queries ===== -->

    <select id="findAll" resultMap="restaurantMap">
        SELECT DISTINCT r.id, r.name, r.address, r.region, r.latitude, r.longitude,
               r.cuisine_type, r.price_range, r.google_place_id, r.tabling_url, r.catchtable_url,
               r.business_status, r.rating, r.rating_count, r.updated_at,
               r.hidden, r.hidden_reason, r.verified_at
        FROM restaurants r
        <if test="channel != null and channel != ''">
            JOIN video_restaurants vr_f ON vr_f.restaurant_id = r.id
            JOIN videos v_f ON v_f.id = vr_f.video_id
            JOIN channels c_f ON c_f.id = v_f.channel_id
        </if>
        <where>
            r.latitude IS NOT NULL
            AND EXISTS (SELECT 1 FROM video_restaurants vr0 WHERE vr0.restaurant_id = r.id)
            <if test="includeHidden == null or !includeHidden">
                AND r.hidden = 0
            </if>
            <if test="cuisine != null and cuisine != ''">
                AND r.cuisine_type = #{cuisine}
            </if>
            <if test="region != null and region != ''">
                AND r.region LIKE '%' || #{region} || '%'
            </if>
            <if test="channel != null and channel != ''">
                AND c_f.channel_name = #{channel}
            </if>
        </where>
        ORDER BY r.updated_at DESC
        OFFSET #{offset} ROWS FETCH NEXT #{limit} ROWS ONLY
    </select>

    <select id="findById" resultMap="restaurantMap">
        SELECT r.id, r.name, r.address, r.region, r.latitude, r.longitude,
               r.cuisine_type, r.price_range, r.phone, r.website, r.google_place_id,
               r.tabling_url, r.catchtable_url, r.business_status, r.rating, r.rating_count
        FROM restaurants r
        WHERE r.id = #{id}
    </select>

    <select id="findVideoLinks" resultType="map">
        SELECT v.video_id, v.title, v.url,
               TO_CHAR(v.published_at, 'YYYY-MM-DD"T"HH24:MI:SS') AS published_at,
               vr.foods_mentioned, vr.evaluation, vr.guests,
               c.channel_name, c.channel_id
        FROM video_restaurants vr
        JOIN videos v ON v.id = vr.video_id
        JOIN channels c ON c.id = v.channel_id
        WHERE vr.restaurant_id = #{restaurantId}
        ORDER BY v.published_at DESC
    </select>

    <!-- ===== Insert ===== -->

    <insert id="insertRestaurant">
        INSERT INTO restaurants (id, name, address, region, latitude, longitude,
                                cuisine_type, price_range, google_place_id,
                                phone, website, business_status, rating, rating_count)
        VALUES (#{id}, #{name}, #{address}, #{region}, #{latitude}, #{longitude},
                #{cuisineType}, #{priceRange}, #{googlePlaceId},
                #{phone}, #{website}, #{businessStatus}, #{rating}, #{ratingCount})
    </insert>

    <!-- ===== Update with COALESCE ===== -->

    <update id="updateRestaurant">
        UPDATE restaurants SET
            name = #{name},
            address = COALESCE(#{address}, address),
            region = COALESCE(#{region}, region),
            latitude = COALESCE(#{latitude}, latitude),
            longitude = COALESCE(#{longitude}, longitude),
            cuisine_type = COALESCE(#{cuisineType}, cuisine_type),
            price_range = COALESCE(#{priceRange}, price_range),
            google_place_id = COALESCE(#{googlePlaceId}, google_place_id),
            phone = COALESCE(#{phone}, phone),
            website = COALESCE(#{website}, website),
            business_status = COALESCE(#{businessStatus}, business_status),
            rating = COALESCE(#{rating}, rating),
            rating_count = COALESCE(#{ratingCount}, rating_count),
            updated_at = SYSTIMESTAMP
        WHERE id = #{id}
    </update>

    <!-- ===== Dynamic field update ===== -->

    <update id="updateFields">
        UPDATE restaurants SET
        <trim suffixOverrides=",">
            <if test="fields.containsKey('name')">
                name = #{fields.name},
            </if>
            <if test="fields.containsKey('address')">
                address = #{fields.address},
            </if>
            <if test="fields.containsKey('region')">
                region = #{fields.region},
            </if>
            <if test="fields.containsKey('cuisine_type')">
                cuisine_type = #{fields.cuisine_type},
            </if>
            <if test="fields.containsKey('price_range')">
                price_range = #{fields.price_range},
            </if>
            <if test="fields.containsKey('phone')">
                phone = #{fields.phone},
            </if>
            <if test="fields.containsKey('website')">
                website = #{fields.website},
            </if>
            <if test="fields.containsKey('tabling_url')">
                tabling_url = #{fields.tabling_url},
            </if>
            <if test="fields.containsKey('catchtable_url')">
                catchtable_url = #{fields.catchtable_url},
            </if>
            <if test="fields.containsKey('latitude')">
                latitude = #{fields.latitude},
            </if>
            <if test="fields.containsKey('longitude')">
                longitude = #{fields.longitude},
            </if>
            <if test="fields.containsKey('google_place_id')">
                google_place_id = #{fields.google_place_id},
            </if>
            <if test="fields.containsKey('business_status')">
                business_status = #{fields.business_status},
            </if>
            <if test="fields.containsKey('rating')">
                rating = #{fields.rating},
            </if>
            <if test="fields.containsKey('rating_count')">
                rating_count = #{fields.rating_count},
            </if>
            updated_at = SYSTIMESTAMP,
        </trim>
        WHERE id = #{id}
    </update>

    <!-- ===== Cascade deletes ===== -->

    <delete id="deleteVectors">
        DELETE FROM restaurant_vectors WHERE restaurant_id = #{id}
    </delete>

    <delete id="deleteReviews">
        DELETE FROM user_reviews WHERE restaurant_id = #{id}
    </delete>

    <delete id="deleteFavorites">
        DELETE FROM user_favorites WHERE restaurant_id = #{id}
    </delete>

    <delete id="deleteVideoRestaurants">
        DELETE FROM video_restaurants WHERE restaurant_id = #{id}
    </delete>

    <delete id="deleteRestaurant">
        DELETE FROM restaurants WHERE id = #{id}
    </delete>

    <!-- ===== Link video-restaurant ===== -->

    <insert id="linkVideoRestaurant">
        INSERT INTO video_restaurants (id, video_id, restaurant_id, foods_mentioned, evaluation, guests)
        VALUES (#{id}, #{videoId}, #{restaurantId}, #{foods,jdbcType=CLOB}, #{evaluation,jdbcType=CLOB}, #{guests,jdbcType=CLOB})
    </insert>

    <!-- ===== Lookups ===== -->

    <select id="findIdByPlaceId" resultType="string">
        SELECT id FROM restaurants WHERE google_place_id = #{placeId} FETCH FIRST 1 ROWS ONLY
    </select>

    <select id="findIdByName" resultType="string">
        SELECT id FROM restaurants WHERE name = #{name} FETCH FIRST 1 ROWS ONLY
    </select>

    <!-- ===== Batch enrichment queries ===== -->

    <select id="findChannelsByRestaurantIds" resultType="map">
        SELECT DISTINCT vr.restaurant_id, c.channel_name
        FROM video_restaurants vr
        JOIN videos v ON v.id = vr.video_id
        JOIN channels c ON c.id = v.channel_id
        WHERE vr.restaurant_id IN
        <foreach item="id" collection="ids" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>

    <select id="findFoodsByRestaurantIds" resultType="map">
        SELECT vr.restaurant_id, vr.foods_mentioned
        FROM video_restaurants vr
        WHERE vr.restaurant_id IN
        <foreach item="id" collection="ids" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>

    <select id="findWithoutTabling" resultMap="restaurantMap">
        SELECT r.id, r.name, r.address, r.region
        FROM restaurants r
        WHERE r.tabling_url IS NULL
          AND r.latitude IS NOT NULL
          AND EXISTS (SELECT 1 FROM video_restaurants vr WHERE vr.restaurant_id = r.id)
        ORDER BY r.name
    </select>

    <select id="findWithoutCatchtable" resultMap="restaurantMap">
        SELECT r.id, r.name, r.address, r.region
        FROM restaurants r
        WHERE r.catchtable_url IS NULL
          AND r.latitude IS NOT NULL
          AND EXISTS (SELECT 1 FROM video_restaurants vr WHERE vr.restaurant_id = r.id)
        ORDER BY r.name
    </select>

    <update id="resetTablingUrls">
        UPDATE restaurants SET tabling_url = NULL WHERE tabling_url IS NOT NULL
    </update>

    <update id="resetCatchtableUrls">
        UPDATE restaurants SET catchtable_url = NULL WHERE catchtable_url IS NOT NULL
    </update>

    <!-- ===== Remap operations ===== -->

    <update id="updateCuisineType">
        UPDATE restaurants SET cuisine_type = #{cuisineType} WHERE id = #{id}
    </update>

    <update id="updateFoodsMentioned">
        UPDATE video_restaurants SET foods_mentioned = #{foods,jdbcType=CLOB} WHERE id = #{id}
    </update>

    <select id="findForRemapCuisine" resultType="map">
        SELECT r.id, r.name, r.cuisine_type,
               (SELECT LISTAGG(TO_CHAR(DBMS_LOB.SUBSTR(vr.foods_mentioned, 500, 1)), '|')
                    WITHIN GROUP (ORDER BY vr.id)
                FROM video_restaurants vr WHERE vr.restaurant_id = r.id) AS foods
        FROM restaurants r
        WHERE EXISTS (SELECT 1 FROM video_restaurants vr2 WHERE vr2.restaurant_id = r.id)
        ORDER BY r.name
    </select>

    <select id="findForRemapFoods" resultType="map">
        SELECT vr.id, r.name, r.cuisine_type,
               TO_CHAR(vr.foods_mentioned) AS foods_mentioned,
               v.title
        FROM video_restaurants vr
        JOIN restaurants r ON r.id = vr.restaurant_id
        JOIN videos v ON v.id = vr.video_id
        ORDER BY r.name
    </select>

    <!-- ===== #322 LLM 검증 ===== -->

    <update id="updateVerification">
        UPDATE restaurants
        SET hidden = #{hidden},
            hidden_reason = #{hiddenReason,jdbcType=VARCHAR},
            verified_at = CURRENT_TIMESTAMP
        WHERE id = #{id}
    </update>

    <update id="clearHidden">
        UPDATE restaurants
        SET hidden = 0,
            hidden_reason = NULL,
            verified_at = CURRENT_TIMESTAMP
        WHERE id = #{id}
    </update>

    <select id="findUnverified" resultMap="restaurantMap">
        SELECT r.id, r.name, r.address, r.region, r.cuisine_type, r.price_range,
               r.hidden, r.hidden_reason, r.verified_at
        FROM restaurants r
        WHERE r.verified_at IS NULL
        ORDER BY r.updated_at DESC
        FETCH FIRST #{limit} ROWS ONLY
    </select>

    <select id="countUnverified" resultType="int">
        SELECT COUNT(*) FROM restaurants WHERE verified_at IS NULL
    </select>

</mapper>
