package cn.edu.whu.boot.collection.service;

import cn.edu.whu.boot.collection.dto.SqlEnity;
import cn.edu.whu.boot.xml.domain.Task;
import cn.edu.whu.boot.xml.xmlreader.bean.Field;
import cn.edu.whu.boot.xml.xmlreader.bean.Table;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.Page;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * 这个接口也没有设计好，里面的方法太多了，后面也没办法优化!
 * 方法的作用看具体的方法注释!!!
 */
public interface IBaseService {

    /**
     * 插入数据方法，sqlEnity是封装的实体类用于获取主键Id
     */
    Long insertSqlEnity(SqlEnity sqlEnity);

    /**
     * 插入数据方法，sqlString是插入数据的Sql
     */
    String insertSqlString(String sqlString);

    /**
     * 根据updateSql进行数据更新
     */
    String updateSqlString(String sqlString);

    /**
     * 根据deleteSql进行数据删除
     */
    String delete(String deleteSql);

    /**
     * 根据表名获取主键id对应的version
     */
    Integer getVersionByLongId(String tableName , String primaryKeyName , Long primaryKeyValue);

    /**
     * 根据selectSql进行数据获取，结果将一条记录转换成Map<String,Object>
     * key 为字段名， value 为字段值
     */
    List<Map<String,Object>> selectData(String selectSql);

    /**
     * 获取某任务下，某个userId对应的用户是采集人员还是审核人员
     */
    Integer getUserWorkRole(Integer taskId , Integer userId);

    /**
     * 因为涉及到多个表的操作，为满足数据库ACID特性，将插入数据的方法全部放在service类中封装成一个方法
     * 然后使用@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)注解方法
     */
    Long insertData(Task task , Table table , int userId , JSONArray multimediaItemJsonArray , MultipartFile file);

    /**
     * 更新复核数据
     */
    Long updateRecheckData(Task task , Table table , int userId , JSONArray multimediaItemJsonArray,
                           Long polygonIdFromAndroid  , MultipartFile file) throws Exception;

    /**
     * 回退数据至某个版本
     */
    String rollBackDataForVersion(Task task , Table table , String updateSqlForRootTable , Long polygonId , int versionId) throws Exception;

    /**
     * 根据数据自动分配的结果，更新记录的reviewer字段
     */
    String updateRootTableDataForReviewer(Task task , Map<String, Map<Long, Integer>> reviewerInfo);

    /**
     * 更新数据的 status 字段值,其中 status 值有：
     *  -1  审核未通过
     *   0  已分配，未审核(经过韦瀚植的自动分配)
     *   1  已采集，未审核
     *   2  已审核
     */
    void updateTableStatus(String tableName , String primaryKey , Long polygonId , int status,
                           String reason);

    /**
     * 更新数据的reviewer字段值
     */
    String updateDataReviewer(String tableName , String primaryKey , Long polygonId , Integer reviewer);

    /**
     * 获取未通过数据的id 及未通过原因
     */
    List<Map<String,Object>> getNotPassDataId(String tableNameInDB , String primaryKey , Integer userId);

    /**
     * 统计GeoHash范围内的数据个数
     */
    Long getStatisticDataNumByGeoJson(String tableName, String geometryName, String geoJson);

    /**
     * 统计表内的所有数据个数：status = -1, 0, 1, 2,  都会被统计
     */
    Long getDataCount(String tableName);

    /**
     * 统计表内的已经采集或者巡查的数据个数，status = -1, 1, 2,  会被统计，也就是说 0 不会被统计进去
     */
    Long getHasCollectAndPatrolDataCount(String tableName);

    /**
     * 统计表内的某 user 采集或者巡查数据的数量按照日期分组
     */
    List<Map<String,Object>> getDataCountAndTimeByUser(String tableName, Integer userId);

    /**
     * 根据searchKey模糊搜索全部匹配数据
     */
    List<Map<String,Object>> getAllFuzzySearchData(String tableNameInDB, String fieldNameInDB, String searchKey);

    /**
     * 按页查询：根据searchKey模糊搜索，该接口用于搜索任务位置，所以获取坐标是数据的中心点
     */
    Page<Map<String,Object>> getAllFuzzySearchDataCenterPoint(String tableNameInDB, String fieldNameInDB, String geometryFieldNameInDB,
                                                              String searchKey);

    /**
     * 从表中抽取主键不在selectIdList中的前selectDataNum（数据按照primaryKey升序排序）
     */
    List<Map<String,Object>> randomSelectDataIdNotInList(String tableNameInDB, String primaryKey, List selectIdList, Integer selectDataNum, String whereClause);

    /**
     * 获取某个任务的某个表下，审核员为 reviewerId 的所有数据的主键
     * @param taskId      任务 id
     * @param tableName   表名
     * @param reviewerId  审核员 id
     */
    List<Integer> getIdsByReviewer(int taskId, String tableName, int reviewerId);

    /**
     * 获取某条数据对应的审核人员 id ，如果返回 -1， 说明这条数据没有审核人员
     * @param taskId      任务 id
     * @param tableName    表名
     * @param dataId     数据主键 id
     */
    Integer getReviewerByDataId(int taskId, String tableName, int dataId);

    List<String> getTableColumns(String databaseName, String tableName);

    /**
     * 返回某任务，某个区域下的所有表的数据的主键和空间字段
     * @param taskId      任务 id
     * @param geohash     geohash 字符串
     */
    Map<String, Map<Long, String>> getIdAndGeojsonByGeohash(int taskId, String geohash);

//    /**
//     * 执行 SQL 查询，返回单列数据
//     * @param sql    查询语句（SQL 语句）
//     * @param params SQL 参数（可选）
//     * @return List<String> 结果列表（只包含第一列数据）
//     */


    void encapPhotoInTable(Map<String, Field> data, Integer taskId, int userId);
    void decapPhotoInTable(Map<String, Field> data);

}
