package cn.reghao.tnb.file.app.zdisk.service;

import cn.reghao.file.api.dto.VideoMeta;
import cn.reghao.file.api.iface.OssService;
import cn.reghao.jutil.jdk.converter.DateTimeConverter;
import cn.reghao.jutil.jdk.web.db.Page;
import cn.reghao.jutil.jdk.web.result.Result;
import cn.reghao.jutil.jdk.web.result.ResultStatus;
import cn.reghao.tnb.file.app.zdisk.db.mapper.CamDeviceMapper;
import cn.reghao.tnb.file.app.zdisk.db.mapper.CamRecordMapper;
import cn.reghao.tnb.file.app.zdisk.model.constant.AlbumType;
import cn.reghao.tnb.file.app.zdisk.model.query.CamDeviceQuery;
import cn.reghao.tnb.file.app.zdisk.model.vo.CamRecordDetail;
import cn.reghao.tnb.file.app.zdisk.model.vo.CamRecordInfo;
import cn.reghao.oss.api.dto.media.VideoInfo;
import cn.reghao.tnb.common.auth.UserContext;
import cn.reghao.tnb.file.app.zdisk.model.dto.CamRecordDto;
import cn.reghao.tnb.file.app.zdisk.model.po.CamDevice;
import cn.reghao.tnb.file.app.zdisk.model.po.CamRecord;
import cn.reghao.tnb.common.util.IdService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author reghao
 * @date 2023-12-08 16:06:39
 */
@Slf4j
@Service
public class CamRecordService {
    @DubboReference(check = false, timeout = 60_000)
    private OssService ossService;
    private int camChannelCode = 107;

    private final IdService idService;
    private final CamDeviceMapper camDeviceMapper;
    private final CamRecordMapper camRecordMapper;
    private final DiskShareService diskShareService;

    public CamRecordService(IdService idService, CamDeviceMapper camDeviceMapper,
                            CamRecordMapper camRecordMapper, DiskShareService diskShareService) {
        this.idService = idService;
        this.camDeviceMapper = camDeviceMapper;
        this.camRecordMapper = camRecordMapper;
        this.diskShareService = diskShareService;
    }

    public Result addCamRecord(CamRecordDto camRecordDto) {
        String camName = camRecordDto.getCamName();
        CamDeviceQuery camDeviceQuery = new CamDeviceQuery.Builder()
                .camName(camName)
                .build();
        Page page = new Page(1, 10);
        List<CamDevice> camDeviceList = camDeviceMapper.findCamDeviceQueryByPage(page, camDeviceQuery);
        if (camDeviceList.isEmpty()) {
            return Result.fail("cam not exist");
        }

        CamDevice camDevice = camDeviceList.get(0);
        long loginUser = UserContext.getUserId();
        if (camDevice.getAddBy() != loginUser) {
            return Result.fail("not owner");
        }

        long camId = camDevice.getCamId();
        try {
            int videoChannelCode = camRecordDto.getVideoChannelCode();
            String videoFileId = camRecordDto.getVideoFileId();
            VideoMeta videoMeta = ossService.getVideoMeta(videoFileId);
            int duration = videoMeta.getDuration();
            long recordId = idService.getLongId();
            long startAt = camRecordDto.getStartAt();
            LocalDateTime startAt1 = DateTimeConverter.localDateTime(startAt);
            CamRecord camRecord = new CamRecord(camId, recordId, videoFileId, duration, startAt1);
            camRecordMapper.save(camRecord);
            return Result.success();
        } catch (Exception e) {
            log.error("{}", e.getMessage());
        }

        return Result.fail("");
    }

    private Result checkCamOwner(long camId) {
        CamDeviceQuery camDeviceQuery = new CamDeviceQuery.Builder()
                .camId(camId)
                .build();
        Page page = new Page(1, 1);
        List<CamDevice> camDeviceList = camDeviceMapper.findCamDeviceQueryByPage(page, camDeviceQuery);
        if (camDeviceList.isEmpty()) {
            return Result.fail("cam not exist");
        }

        CamDevice camDevice = camDeviceList.get(0);
        long loginUser = UserContext.getUserId();
        Set<Long> sharedCamIds = new HashSet<>(diskShareService.getSharedAlbumIds(AlbumType.cam.getValue(), loginUser));
        if (camDevice.getAddBy() != loginUser && !sharedCamIds.contains(camId)) {
            return Result.fail("not owner");
        }

        return Result.success();
    }

    /**
     * 获取某天的监控录像
     *
     * @param dayStr 2024-08-31 格式的字符串
     * @return
     * @date 2024-08-31 18:08:972
     */
    public List<CamRecordInfo> getCamRecordByDay(Long camId, String dayStr) {
        Result result = checkCamOwner(camId);
        if (result.getCode() != ResultStatus.SUCCESS.getCode()) {
            return Collections.emptyList();
        }

        return camRecordMapper.findByCamIdAndStartAt(camId, dayStr);
    }

    public CamRecordDetail getCamRecordDetail(long recordId) {
        CamRecord camRecord = camRecordMapper.findByRecordId(recordId);
        if (camRecord != null && checkCamOwner(camRecord.getCamId()).getCode() == ResultStatus.SUCCESS.getCode()) {
            return getCamRecordDetail(camRecord);
        }

        return null;
    }

    /**
     * 某月中的哪些天有监控录像
     *
     * @param yearMonth 2024-08 格式的字符串
     * @return
     * @date 2024-08-31 20:08:873
     */
    public List<String> getDaysInMonth(Long camId, String yearMonth) {
        Result result = checkCamOwner(camId);
        if (result.getCode() != ResultStatus.SUCCESS.getCode()) {
            return Collections.emptyList();
        }

        return camRecordMapper.findGroupByYearMonth(camId, yearMonth);
    }

    private CamRecordDetail getCamRecordDetail(CamRecord camRecord) {
        long camId = camRecord.getCamId();
        Result result = checkCamOwner(camId);
        if (result.getCode() != ResultStatus.SUCCESS.getCode()) {
            return null;
        }

        String videoFileId = camRecord.getVideoFileId();
        try {
            String signedUrl = ossService.getSignedUrl(videoFileId, null);
            return new CamRecordDetail(camRecord, signedUrl);
        } catch (Exception e) {
            log.error("{}", e.getMessage());
        }

        return null;
    }
}
