package incheon.product.geoview2d.layer.mapper;

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

import incheon.com.config.annotation.MainDB;
import incheon.product.geoview2d.layer.vo.TaskLayerSearchVO;
import incheon.product.geoview2d.layer.vo.TaskLayerVO;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.egovframe.rte.psl.dataaccess.mapper.Mapper;

/**
 * 레이어 Mapper.
 * 동적 SQL은 LayerSqlProvider 사용, 정적 쿼리는 XML 매핑.
 */
@Mapper("productLayerMapper")
@MainDB
public interface LayerMapper {

    // ========== 레이어 메타데이터 (XML 매핑) ==========

    Map<String, Object> selectUserLayerMetadata(String layerId);

    Map<String, Object> selectTaskLayerMetadata(String layerId);

    @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);

    // ========== 피처 편집 (동적 SQL) ==========

    @SelectProvider(type = LayerSqlProvider.class, method = "batchInsertLayerFeatures")
    List<Map<String, Object>> batchInsertLayerFeatures(Map<String, Object> params);

    @UpdateProvider(type = LayerSqlProvider.class, method = "batchUpdateLayerFeatures")
    int batchUpdateLayerFeatures(Map<String, Object> params);

    @DeleteProvider(type = LayerSqlProvider.class, method = "deleteLayerFeatures")
    int deleteLayerFeatures(Map<String, Object> params);

    @SelectProvider(type = LayerSqlProvider.class, method = "selectLayerFeature")
    Map<String, Object> selectLayerFeature(Map<String, Object> params);

    // ========== 이력 테이블 ==========

    @Select("""
        SELECT EXISTS (
            SELECT 1 FROM information_schema.tables
            WHERE table_schema = #{schemaName}
            AND table_name = #{tableName}
        )
        """)
    Boolean checkHistoryTableExists(@Param("schemaName") String schemaName, @Param("tableName") String tableName);

    @InsertProvider(type = LayerSqlProvider.class, method = "batchInsertHistoryAdded")
    int batchInsertHistoryAdded(Map<String, Object> params);

    @InsertProvider(type = LayerSqlProvider.class, method = "batchInsertHistoryModified")
    int batchInsertHistoryModified(Map<String, Object> params);

    @InsertProvider(type = LayerSqlProvider.class, method = "batchInsertHistoryDeleted")
    int batchInsertHistoryDeleted(Map<String, Object> params);

    // ========== 업무 레이어 조회 (XML 매핑) ==========

    List<TaskLayerVO> selectTaskLayerList(TaskLayerSearchVO searchVO);

    List<TaskLayerVO> selectTaskLayerListNotInGroupCd(@Param("request") TaskLayerSearchVO searchVO, @Param("removedGroupCd") Set<String> removedGroupCd);

    long selectTaskLayerListTotCnt(TaskLayerSearchVO searchVO);

    long selectTaskLayerListNotInGroupCdTotCnt(@Param("request") TaskLayerSearchVO searchVO, @Param("removedGroupCd") Set<String> removedGroupCd);

    TaskLayerVO selectTaskLayerById(int taskLyrId);

    // ========== 업무 레이어 CRUD (XML 매핑) ==========

    List<TaskLayerVO> findAll();

    List<TaskLayerVO> findAllWithPaging(@Param("searchKeyword") String searchKeyword, @Param("searchType") String searchType,
                                        @Param("limit") int limit, @Param("offset") int offset);

    int count(@Param("searchKeyword") String searchKeyword, @Param("searchType") String searchType);

    void insert(TaskLayerVO taskLayer);

    void update(TaskLayerVO taskLayer);

    void delete(Integer taskLyrId);

    List<Map<String, Object>> selectGroupCodes();

    List<Map<String, Object>> verifyGeometryTable(@Param("schema") String schema, @Param("tableNm") String tableNm);

    Integer verifyTaskPhyTable(Map<String, Object> params);

    Integer verifyTaskSrvTable(Map<String, Object> params);
}
