package com.jeesharp.business.modules.member.application;

import com.jeesharp.business.modules.member.dto.MemberFavoriteToggleDTO;
import com.jeesharp.business.modules.member.entity.MemberFavorite;
import com.jeesharp.business.modules.member.enums.MemberFavoriteBizTypeEnum;
import com.jeesharp.business.modules.member.service.MemberFavoriteService;
import com.jeesharp.business.modules.member.service.MemberService;
import com.jeesharp.business.modules.member.vo.MemberFavoriteListVO;
import com.jeesharp.business.modules.member.vo.MemberFavoriteQueryVO;
import com.jeesharp.framework.pojo.Page;
import com.jeesharp.framework.pojo.query.PageRespVO;
import com.jeesharp.framework.utils.base.ExceptionUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 会员统一收藏应用服务：收藏切换、列表、计数与校验。
 *
 * @author jeesharp
 * @since 2026-05-20
 */
@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class MemberFavoriteApplicationService {

    private static final DateTimeFormatter SAVED_AT_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

    private final MemberFavoriteService memberFavoriteService;
    private final MemberService memberService;

    /**
     * 切换收藏状态，返回切换后是否已收藏。
     */
    @Transactional(readOnly = false)
    public boolean toggle(String memberId, MemberFavoriteToggleDTO dto) {
        assertMember(memberId);
        String bizType = normalizeBizType(dto.getBizType());
        String bizId = dto.getBizId().trim();

        if (memberFavoriteService.exists(memberId, bizType, bizId)) {
            memberFavoriteService.removeFavorite(memberId, bizType, bizId);
            return false;
        }

        MemberFavorite favorite = new MemberFavorite();
        favorite.setMemberId(memberId);
        favorite.setBizType(bizType);
        favorite.setBizId(bizId);
        favorite.setTitle(dto.getTitle().trim());
        favorite.setSubtitle(trimToNull(dto.getSubtitle()));
        favorite.setCover(trimToNull(dto.getCover()));
        favorite.setJumpPath(trimToNull(dto.getJumpPath()));
        memberFavoriteService.saveFavorite(favorite);
        return true;
    }

    @Transactional(readOnly = false)
    public void remove(String memberId, String bizType, String bizId) {
        assertMember(memberId);
        memberFavoriteService.removeFavorite(memberId, normalizeBizType(bizType), bizId.trim());
    }

    public boolean isFavorite(String memberId, String bizType, String bizId) {
        assertMember(memberId);
        return memberFavoriteService.exists(memberId, normalizeBizType(bizType), bizId.trim());
    }

    public long countByMemberId(String memberId) {
        assertMember(memberId);
        return memberFavoriteService.countByMemberId(memberId);
    }

    public PageRespVO<MemberFavoriteListVO> findPage(String memberId, MemberFavoriteQueryVO query) {
        assertMember(memberId);
        if (query == null) {
            query = new MemberFavoriteQueryVO();
        }
        String bizType = trimToNull(query.getBizType());
        if (bizType != null) {
            normalizeBizType(bizType);
        }
        Page<MemberFavorite> page = new Page<>(query);
        Page<MemberFavorite> result = memberFavoriteService.findPageByMember(page, memberId, bizType);
        PageRespVO<MemberFavoriteListVO> resp = new PageRespVO<>();
        resp.setTotal(result.getTotal());
        resp.setPageNo(result.getPageNo());
        resp.setPageSize(result.getPageSize());
        resp.setRecords(result.getRecords().stream().map(this::toListVO).collect(Collectors.toList()));
        return resp;
    }

    public List<MemberFavoriteListVO> listAll(String memberId, String bizType, int limit) {
        assertMember(memberId);
        String normalized = bizType != null && !bizType.isBlank() ? normalizeBizType(bizType) : null;
        return memberFavoriteService.listByMember(memberId, normalized, limit).stream()
                .map(this::toListVO)
                .collect(Collectors.toList());
    }

    private MemberFavoriteListVO toListVO(MemberFavorite e) {
        MemberFavoriteListVO vo = new MemberFavoriteListVO();
        vo.setId(e.getId());
        vo.setBizType(e.getBizType());
        vo.setBizId(e.getBizId());
        vo.setTitle(e.getTitle());
        vo.setSubtitle(e.getSubtitle());
        vo.setCover(e.getCover());
        vo.setJumpPath(e.getJumpPath());
        LocalDateTime when = e.getCreateDate() != null ? e.getCreateDate() : LocalDateTime.now();
        vo.setSavedAt(when.format(SAVED_AT_FMT));
        return vo;
    }

    private void assertMember(String memberId) {
        if (memberService.get(memberId) == null) {
            ExceptionUtil.error("会员不存在");
        }
    }

    private String normalizeBizType(String bizType) {
        MemberFavoriteBizTypeEnum type = MemberFavoriteBizTypeEnum.fromValue(bizType);
        if (type == null) {
            ExceptionUtil.error("不支持的业务类型");
        }
        return type.getValue();
    }

    private String trimToNull(String value) {
        if (value == null) {
            return null;
        }
        String trimmed = value.trim();
        return trimmed.isEmpty() ? null : trimmed;
    }
}
