package ru.soune.nocopy.service.violation;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.soune.nocopy.dto.violation.ViolationNotionResponse;
import ru.soune.nocopy.dto.violation.ViolationNotionsListResponse;
import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.entity.violation.Violation;
import ru.soune.nocopy.entity.violation.ViolationNotion;
import ru.soune.nocopy.repository.UserRepository;
import ru.soune.nocopy.repository.ViolationNotionRepository;
import ru.soune.nocopy.repository.ViolationRepository;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ViolationNotionService {

    private final ViolationNotionRepository notionRepository;
    private final UserRepository userRepository;
    private final ViolationRepository violationRepository;

    @Transactional(readOnly = true)
    public ViolationNotionsListResponse getNotionsByViolationId(Long violationId, Long userId) {
        Violation violation = violationRepository.findById(violationId)
                .orElseThrow(() -> new IllegalArgumentException("Violation not found: " + violationId));

        List<ViolationNotion> notions = notionRepository.findByViolationId(violationId);
        long totalCount = notionRepository.countByViolationId(violationId);

        List<ViolationNotionResponse> notionResponses = notions.stream()
                .map(this::mapToResponse)
                .collect(Collectors.toList());

        return ViolationNotionsListResponse.builder()
                .violationId(violationId)
                .url(violation.getUrl())
                .host(violation.getHost())
                .totalCount((int) totalCount)
                .notions(notionResponses)
                .build();
    }

    @Transactional(readOnly = true)
    public ViolationNotionResponse getNotionById(Long notionId, Long userId) {
        ViolationNotion notion = notionRepository.findById(notionId)
                .orElseThrow(() -> new IllegalArgumentException("Notion not found: " + notionId));

        if (!notion.getUser().getId().equals(userId)) {
            throw new SecurityException("User does not have access to this notion");
        }

        return mapToResponse(notion);
    }

    @Transactional
    public ViolationNotionResponse createNotion(Long violationId, Long userId, String message) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("User not found: " + userId));

        Violation violation = violationRepository.findById(violationId)
                .orElseThrow(() -> new IllegalArgumentException("Violation not found: " + violationId));

        ViolationNotion notion = new ViolationNotion();
        notion.setUser(user);
        notion.setViolation(violation);
        notion.setMessage(message);

        ViolationNotion saved = notionRepository.save(notion);
        log.info("Created notion for violation: {} by user: {}", violationId, userId);

        return mapToResponse(saved);
    }

    @Transactional
    public ViolationNotionResponse updateNotion(Long notionId, Long userId, String message) {
        ViolationNotion notion = notionRepository.findById(notionId)
                .orElseThrow(() -> new IllegalArgumentException("Notion not found: " + notionId));

        if (!notion.getUser().getId().equals(userId)) {
            throw new SecurityException("Only author can update this notion");
        }

        notion.setMessage(message);
        ViolationNotion updated = notionRepository.save(notion);
        log.info("Updated notion: {} by user: {}", notionId, userId);

        return mapToResponse(updated);
    }

    @Transactional
    public void deleteNotion(Long notionId, Long userId) {
        ViolationNotion notion = notionRepository.findById(notionId)
                .orElseThrow(() -> new IllegalArgumentException("Notion not found: " + notionId));

        if (!notion.getUser().getId().equals(userId)) {
            throw new SecurityException("Only author can delete this notion");
        }

        notionRepository.delete(notion);
        log.info("Deleted notion: {} by user: {}", notionId, userId);
    }

    private ViolationNotionResponse mapToResponse(ViolationNotion notion) {
        return ViolationNotionResponse.builder()
                .id(notion.getId())
                .message(notion.getMessage())
                .createdAt(notion.getCreatedAt())
                .updatedAt(notion.getUpdatedAt())
                .user(ViolationNotionResponse.UserInfo.builder()
                        .id(notion.getUser().getId())
                        .fullName(notion.getUser().getFullName())
                        .email(notion.getUser().getEmail())
                        .build())
                .violation(ViolationNotionResponse.ViolationInfo.builder()
                        .id(notion.getViolation().getId())
                        .url(notion.getViolation().getPageUrl())
                        .host(notion.getViolation().getHost())
                        .build())
                .build();
    }
}
