package com.bizzan.bitrade.service;

import com.bizzan.bitrade.dao.AnnouncementDao;
import com.bizzan.bitrade.dao.MemberAnnouncementReadDao;
import com.bizzan.bitrade.entity.Announcement;
import com.bizzan.bitrade.entity.MemberAnnouncementRead;
import com.bizzan.bitrade.entity.QAnnouncement;
import com.querydsl.core.types.dsl.BooleanExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Iterator;
import java.util.List;

@Service
public class MemberAnnouncementReadService {

    @Autowired
    private MemberAnnouncementReadDao memberAnnouncementReadDao;

    @Autowired
    private AnnouncementDao announcementDao;

    public Announcement findLatest() {
        BooleanExpression predicate = QAnnouncement.announcement.isShow.eq(true)
                .and(QAnnouncement.announcement.publishTime.loe(new Date())
                        .or(QAnnouncement.announcement.publishTime.isNull()));
        PageRequest page = new PageRequest(0, 1, new Sort(Sort.Direction.DESC, "id"));
        Iterator<Announcement> it = announcementDao.findAll(predicate, page).iterator();
        return it.hasNext() ? it.next() : null;
    }

    public List<Long> getReadIds(Long memberId) {
        return memberAnnouncementReadDao.findReadIdsByMemberId(memberId);
    }

    public long countUnread(Long memberId) {
        List<Long> readIds = getReadIds(memberId);
        BooleanExpression predicate = QAnnouncement.announcement.isShow.eq(true)
                .and(QAnnouncement.announcement.publishTime.loe(new Date())
                        .or(QAnnouncement.announcement.publishTime.isNull()));
        if (!readIds.isEmpty()) {
            predicate = predicate.and(QAnnouncement.announcement.id.notIn(readIds));
        }
        return announcementDao.count(predicate);
    }

    @Transactional(rollbackFor = Exception.class)
    public void markRead(Long memberId, Long announcementId) {
        if (memberAnnouncementReadDao.existsByMemberIdAndAnnouncementId(memberId, announcementId)) {
            return;
        }
        MemberAnnouncementRead record = new MemberAnnouncementRead();
        record.setMemberId(memberId);
        record.setAnnouncementId(announcementId);
        record.setReadTime(new Date());
        memberAnnouncementReadDao.save(record);
    }
}
