package com.ycwl.basic.service.pc.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.exception.BaseException;
import com.ycwl.basic.biz.FaceStatusManager;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.model.pc.source.req.SourceReqQuery;
import com.ycwl.basic.model.pc.source.resp.SourceRespVO;
import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.repository.MemberRelationRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.repository.SourceRepository;
import com.ycwl.basic.service.pc.ScenicService;
import com.ycwl.basic.service.pc.SourceService;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.task.VideoPieceGetter;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.SnowFlakeUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.ycwl.basic.storage.StorageFactory;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.ycwl.basic.constant.StorageConstant.PHOTO_PATH;

/**
 * @Author：longbinbin
 * @Date：2024/12/3 15:49
 */
@Service
public class SourceServiceImpl implements SourceService {
    @Autowired
    private SourceMapper sourceMapper;
    @Autowired
    private SourceRepository sourceRepository;
    @Autowired
    private ScenicService scenicService;
    @Autowired
    private ScenicRepository scenicRepository;
    @Autowired
    private DeviceRepository deviceRepository;
    @Autowired
    private MemberRelationRepository memberRelationRepository;
    @Autowired
    private FaceStatusManager faceStatusManager;

    @Override
    public ApiResponse<PageInfo<SourceRespVO>> pageQuery(SourceReqQuery sourceReqQuery) {
        PageHelper.startPage(sourceReqQuery.getPageNum(), sourceReqQuery.getPageSize());
        List<SourceRespVO> list = sourceMapper.list(sourceReqQuery);
        
        // 批量获取景区名称
        List<Long> scenicIds = list.stream()
                .map(SourceRespVO::getScenicId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, String> scenicNames = scenicRepository.batchGetScenicNames(scenicIds);
        
        // 批量获取设备名称
        List<Long> deviceIds = list.stream()
                .map(SourceRespVO::getDeviceId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, String> deviceNames = deviceRepository.batchGetDeviceNames(deviceIds);
        
        list.forEach(sourceRespVO -> {
            // 设置景区名称
            if (sourceRespVO.getScenicId() != null) {
                sourceRespVO.setScenicName(scenicNames.get(sourceRespVO.getScenicId()));
            }
            // 设置设备名称
            if (sourceRespVO.getDeviceId() != null) {
                sourceRespVO.setDeviceName(deviceNames.get(sourceRespVO.getDeviceId()));
            }
        });
        PageInfo<SourceRespVO> pageInfo = new PageInfo<>(list);
        return ApiResponse.success(pageInfo);
    }

    @Override
    public ApiResponse<List<SourceRespVO>> list(SourceReqQuery sourceReqQuery) {
        List<SourceRespVO> list = sourceMapper.list(sourceReqQuery);
        
        // 批量获取景区名称
        List<Long> scenicIds = list.stream()
                .map(SourceRespVO::getScenicId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, String> scenicNames = scenicRepository.batchGetScenicNames(scenicIds);
        
        // 批量获取设备名称
        List<Long> deviceIds = list.stream()
                .map(SourceRespVO::getDeviceId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, String> deviceNames = deviceRepository.batchGetDeviceNames(deviceIds);
        
        list.forEach(sourceRespVO -> {
            // 设置景区名称
            if (sourceRespVO.getScenicId() != null) {
                sourceRespVO.setScenicName(scenicNames.get(sourceRespVO.getScenicId()));
            }
            // 设置设备名称  
            if (sourceRespVO.getDeviceId() != null) {
                sourceRespVO.setDeviceName(deviceNames.get(sourceRespVO.getDeviceId()));
            }
        });
        return ApiResponse.success(list);
    }

    @Override
    public ApiResponse<SourceRespVO> getById(Long id, Long userId) {
        SourceRespVO sourceRespVO = sourceMapper.userGetById(id, userId);
        try {
            ScenicV2DTO scenicBasic = scenicRepository.getScenicBasic(sourceRespVO.getScenicId());
            sourceRespVO.setScenicName(scenicBasic.getName());
        } catch (Exception e) {
            sourceRespVO.setScenicName("");
        }
        return ApiResponse.success(sourceRespVO);
    }

    @Override
    public ApiResponse<Integer> add(SourceEntity source) {
        source.setId(SnowFlakeUtil.getLongId());
        int add = sourceMapper.add(source);
        if (add > 0) {
            return ApiResponse.success(add);
        }else {
            return ApiResponse.fail("添加失败");
        }
    }

    @Override
    public ApiResponse<Integer> deleteById(Long id) {
        int i = sourceMapper.deleteById(id);
        if (i > 0) {
            return ApiResponse.success(i);
        }else {
            return ApiResponse.fail("删除失败");
        }
    }

    @Override
    public ApiResponse<Integer> update(SourceEntity source) {
        int i = sourceMapper.update(source);
        if (i > 0) {
            return ApiResponse.success(i);
        }else {
            return ApiResponse.fail("修改失败");
        }
    }

    @Override
    public ApiResponse cutVideo(Long id) {
        SourceEntity source = sourceRepository.getSource(id);
        if (Integer.valueOf(2).equals(source.getType())) {
            // 下载切片
            VideoPieceGetter.Task task = new VideoPieceGetter.Task();
            task.faceSampleIds = Collections.singletonList(source.getFaceSampleId());
            task.force = true;
            VideoPieceGetter.addTask(task);
        }
        return ApiResponse.success("任务已下发");
    }

    @Override
    public String uploadAndUpdateUrl(Long id, File file) {
        SourceRespVO source = sourceMapper.getById(id);
        if (source == null) {
            throw new BaseException("该素材不存在");
        }
        try {
            IStorageAdapter adapter = scenicService.getScenicStorageAdapter(source.getScenicId());
            String uploadedUrl = adapter.uploadFile("image/jpeg", file, PHOTO_PATH, id + "_q_.jpg");
            
            SourceEntity sourceUpd = new SourceEntity();
            sourceUpd.setId(id);
            sourceUpd.setUrl(uploadedUrl);
            
            int updateResult = sourceMapper.update(sourceUpd);
            if (updateResult > 0) {
                return uploadedUrl;
            } else {
                throw new BaseException("更新URL失败");
            }
        } catch (Exception e) {
            throw new BaseException("文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public ApiResponse<Map<Long, Long>> getFaceIdsBySourceIds(List<Long> sourceIds) {
        if (sourceIds == null || sourceIds.isEmpty()) {
            return ApiResponse.success(Collections.emptyMap());
        }
        List<MemberSourceEntity> relations = sourceMapper.listFaceIdsBySourceIds(sourceIds);
        Map<Long, Long> faceIdMap = relations.stream()
                .collect(Collectors.toMap(
                        MemberSourceEntity::getSourceId,
                        MemberSourceEntity::getFaceId,
                        (existing, replacement) -> existing,
                        LinkedHashMap::new
                ));
        // 对于没有关联的sourceId，填充null
        Map<Long, Long> result = new LinkedHashMap<>();
        for (Long sourceId : sourceIds) {
            result.put(sourceId, faceIdMap.get(sourceId));
        }
        return ApiResponse.success(result);
    }

    @Override
    public ApiResponse<PageInfo<SourceRespVO>> pageByFaceId(SourceReqQuery sourceReqQuery) {
        PageHelper.startPage(sourceReqQuery.getPageNum(), sourceReqQuery.getPageSize());
        List<SourceRespVO> list = sourceMapper.pageByFaceId(sourceReqQuery);
        PageInfo<SourceRespVO> pageInfo = new PageInfo<>(list);
        return ApiResponse.success(pageInfo);
    }

    @Override
    public ApiResponse<Void> cancelRelation(Long id) {
        MemberSourceEntity entity = sourceMapper.getMemberSourceById(id);
        if (entity == null) {
            return ApiResponse.fail("关联记录不存在");
        }
        int rows = sourceMapper.softDeleteRelation(id);
        if (rows == 0) {
            return ApiResponse.fail("记录已取消或不存在");
        }
        invalidateCacheByFace(entity.getFaceId());
        return ApiResponse.success(null);
    }

    @Override
    public ApiResponse<Void> reactivateRelation(Long id) {
        MemberSourceEntity entity = sourceMapper.getMemberSourceById(id);
        if (entity == null) {
            return ApiResponse.fail("关联记录不存在");
        }
        int rows = sourceMapper.reactivateRelation(id);
        if (rows == 0) {
            return ApiResponse.fail("记录未处于取消状态");
        }
        invalidateCacheByFace(entity.getFaceId());
        return ApiResponse.success(null);
    }

    @Override
    public ApiResponse<PageInfo<SourceRespVO>> pageDeletedByFaceId(SourceReqQuery sourceReqQuery) {
        PageHelper.startPage(sourceReqQuery.getPageNum(), sourceReqQuery.getPageSize());
        List<SourceRespVO> list = sourceMapper.pageDeletedByFaceId(sourceReqQuery);
        PageInfo<SourceRespVO> pageInfo = new PageInfo<>(list);
        return ApiResponse.success(pageInfo);
    }

    private void invalidateCacheByFace(Long faceId) {
        if (faceId != null) {
            memberRelationRepository.clearSCacheByFace(faceId);
            faceStatusManager.invalidatePuzzleSourceVersion(faceId);
        }
    }
}
