package pl.polskalokalnie.lead;

import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;

@Service
public class TargetGroupService {

    private static final int PREVIEW_SAMPLE_SIZE = 20;

    private final TargetGroupRepository targetGroupRepository;
    private final LeadQueryService leadQueryService;

    public TargetGroupService(TargetGroupRepository targetGroupRepository, LeadQueryService leadQueryService) {
        this.targetGroupRepository = targetGroupRepository;
        this.leadQueryService = leadQueryService;
    }

    public List<TargetGroupResponse> list() {
        return targetGroupRepository.findAll().stream()
                .sorted(Comparator.comparing(TargetGroup::getCreatedAt).reversed())
                .map(group -> TargetGroupResponse.from(group, leadQueryService.count(group)))
                .toList();
    }

    @Transactional
    public TargetGroupResponse create(TargetGroupRequest request) {
        TargetGroup group = new TargetGroup();
        apply(group, request);
        TargetGroup saved = targetGroupRepository.save(group);
        return TargetGroupResponse.from(saved, leadQueryService.count(saved));
    }

    @Transactional
    public TargetGroupResponse update(Long id, TargetGroupRequest request) {
        TargetGroup group = requireGroup(id);
        apply(group, request);
        TargetGroup saved = targetGroupRepository.save(group);
        return TargetGroupResponse.from(saved, leadQueryService.count(saved));
    }

    @Transactional
    public void delete(Long id) {
        TargetGroup group = requireGroup(id);
        targetGroupRepository.delete(group);
    }

    public TargetGroupPreviewResponse preview(Long id) {
        TargetGroup group = requireGroup(id);
        List<Lead> members = leadQueryService.resolve(group);
        List<LeadResponse> sample = members.stream()
                .limit(PREVIEW_SAMPLE_SIZE)
                .map(LeadResponse::from)
                .toList();
        return new TargetGroupPreviewResponse(members.size(), sample);
    }

    TargetGroup requireGroup(Long id) {
        return targetGroupRepository.findById(id)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Grupa docelowa nie istnieje"));
    }

    private void apply(TargetGroup group, TargetGroupRequest request) {
        group.setName(request.name().trim());
        group.setDescription(trimToNull(request.description()));
        group.setSources(request.sources() == null ? new LinkedHashSet<>() : new LinkedHashSet<>(request.sources()));
        group.setCity(trimToNull(request.city()));
        group.setTag(trimToNull(request.tag()));
        group.setStatus(request.status());
        group.setRequireEmail(request.requireEmail());
        group.setRequirePhone(request.requirePhone());
        group.setRequireEmailConsent(request.requireEmailConsent());
        group.setRequireSmsConsent(request.requireSmsConsent());
    }

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