package incheon.uis.uld.mapper;

import incheon.uis.uld.service.LayerSyncSqlProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.UpdateProvider;

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

/**
 * 레이어 동기화 Mapper
 * 업로드된 레이어 데이터를 DB에 동기화
 */
@org.egovframe.rte.psl.dataaccess.mapper.Mapper
@incheon.com.config.annotation.MainDB
public interface LayerSyncMapper {

    /**
     * 테이블 컬럼 메타데이터 조회
     * gid, geom 컬럼은 제외하고 조회
     */
    @Select("""
        SELECT column_name, data_type, is_nullable
        FROM information_schema.columns
        WHERE table_schema = #{schemaName} AND table_name = #{tableName}
        AND column_name != 'gid' AND column_name != 'geom'
        ORDER BY ordinal_position
        """)
    List<Map<String, Object>> selectTableColumns(@Param("schemaName") String schemaName,
                                                  @Param("tableName") String tableName);

    /**
     * 테이블의 Primary Key 컬럼 조회
     * ordinal_position 순서로 정렬하여 반환 (예: ftc, idn)
     */
    @Select("""
        SELECT kcu.column_name
        FROM information_schema.table_constraints tc
        JOIN information_schema.key_column_usage kcu
            ON tc.constraint_name = kcu.constraint_name
            AND tc.table_schema = kcu.table_schema
        WHERE tc.constraint_type = 'PRIMARY KEY'
            AND tc.table_schema = #{schemaName}
            AND tc.table_name = #{tableName}
        ORDER BY kcu.ordinal_position
        """)
    List<String> selectPrimaryKeyColumns(@Param("schemaName") String schemaName,
                                          @Param("tableName") String tableName);

    /**
     * 배치 UPDATE
     * CASE WHEN 방식으로 배치 처리
     */
    @UpdateProvider(type = LayerSyncSqlProvider.class, method = "batchUpdateFeatures")
    int batchUpdateFeatures(@Param("param") Map<String, Object> param);

    /**
     * 이력 테이블에 INSERT
     * 원본 테이블에서 SELECT하여 _h 테이블에 INSERT
     */
    @InsertProvider(type = LayerSyncSqlProvider.class, method = "insertHistory")
    int insertHistory(@Param("param") Map<String, Object> param);

    /**
     * Soft Delete (use_yn = 'N' 으로 UPDATE)
     */
    @UpdateProvider(type = LayerSyncSqlProvider.class, method = "softDeleteFeatures")
    int softDeleteFeatures(@Param("param") Map<String, Object> param);

    /**
     * PK로 기존 데이터 조회 (use_yn 포함)
     * @return pk_value, use_yn 맵 목록
     */
    @org.apache.ibatis.annotations.SelectProvider(type = LayerSyncSqlProvider.class, method = "selectExistingByPk")
    List<Map<String, Object>> selectExistingByPk(@Param("param") Map<String, Object> param);

    /**
     * 삭제된 데이터 재활성화 + UPDATE
     * use_yn = 'N' -> 'Y'로 변경하면서 값 UPDATE
     */
    @UpdateProvider(type = LayerSyncSqlProvider.class, method = "reactivateFeatures")
    int reactivateFeatures(@Param("param") Map<String, Object> param);

    /**
     * 신규 INSERT (gid 제외 - DB 시퀀스로 자동 생성)
     */
    @InsertProvider(type = LayerSyncSqlProvider.class, method = "insertNewFeature")
    int insertNewFeature(@Param("param") Map<String, Object> param);

    /**
     * 신규 INSERT용 이력 테이블 INSERT
     */
    @InsertProvider(type = LayerSyncSqlProvider.class, method = "insertHistoryForNew")
    int insertHistoryForNew(@Param("param") Map<String, Object> param);

    /**
     * 이력 테이블에 원본 데이터 직접 INSERT (배치용)
     * 프론트에서 넘어온 features 데이터를 직접 이력 테이블에 INSERT
     */
    @InsertProvider(type = LayerSyncSqlProvider.class, method = "insertHistoryDirect")
    int insertHistoryDirect(@Param("param") Map<String, Object> param);

    /**
     * 신규 INSERT용 이력 테이블에 원본 데이터 직접 INSERT (단건용)
     * @deprecated insertHistoryByGid 사용 권장
     */
    @InsertProvider(type = LayerSyncSqlProvider.class, method = "insertHistoryDirectForNew")
    @Deprecated
    int insertHistoryDirectForNew(@Param("param") Map<String, Object> param);

    /**
     * 신규 INSERT (gid 반환 - RETURNING 사용)
     * @return 생성된 gid
     */
    @org.apache.ibatis.annotations.SelectProvider(type = LayerSyncSqlProvider.class, method = "insertNewFeatureReturning")
    Long insertNewFeatureReturning(@Param("param") Map<String, Object> param);

    /**
     * gid로 원본 테이블에서 SELECT하여 이력 테이블에 INSERT
     * INSERT 후 실제 DB 데이터로 이력 저장
     */
    @InsertProvider(type = LayerSyncSqlProvider.class, method = "insertHistoryByGid")
    int insertHistoryByGid(@Param("param") Map<String, Object> param);
}
