package de.cannamanage.service;

import de.cannamanage.domain.entity.Consent;
import de.cannamanage.domain.entity.Distribution;
import de.cannamanage.domain.entity.Member;
import de.cannamanage.domain.entity.User;
import de.cannamanage.service.repository.ConsentRepository;
import de.cannamanage.service.repository.DistributionRepository;
import de.cannamanage.service.repository.MemberRepository;
import de.cannamanage.service.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.*;

/**
 * DSGVO compliance service — data export (Art. 15) and data deletion (Art. 17).
 */
@Service
public class DsgvoService {

    private static final Logger log = LoggerFactory.getLogger(DsgvoService.class);
    private static final String ANONYMIZED = "GELÖSCHT";

    private final UserRepository userRepository;
    private final MemberRepository memberRepository;
    private final DistributionRepository distributionRepository;
    private final ConsentRepository consentRepository;
    private final ConsentService consentService;

    public DsgvoService(UserRepository userRepository,
                        MemberRepository memberRepository,
                        DistributionRepository distributionRepository,
                        ConsentRepository consentRepository,
                        ConsentService consentService) {
        this.userRepository = userRepository;
        this.memberRepository = memberRepository;
        this.distributionRepository = distributionRepository;
        this.consentRepository = consentRepository;
        this.consentService = consentService;
    }

    /**
     * Export all personal data for a user (Art. 15 DSGVO).
     * Returns a structured map suitable for JSON serialization.
     */
    @Transactional(readOnly = true)
    public Map<String, Object> exportUserData(UUID userId, UUID tenantId) {
        Map<String, Object> export = new LinkedHashMap<>();
        export.put("exportDate", Instant.now().toString());
        export.put("legalBasis", "Art. 15 DSGVO — Auskunftsrecht der betroffenen Person");

        // Personal data from user account
        User user = userRepository.findById(userId).orElse(null);
        if (user != null) {
            Map<String, Object> personal = new LinkedHashMap<>();
            personal.put("email", user.getEmail());
            personal.put("role", user.getRole().name());
            personal.put("active", user.isActive());
            personal.put("lastLogin", user.getLastLogin() != null ? user.getLastLogin().toString() : null);
            personal.put("createdAt", user.getCreatedAt() != null ? user.getCreatedAt().toString() : null);
            export.put("personalData", personal);
        }

        // Member profile data
        if (user != null && user.getMemberId() != null) {
            memberRepository.findById(user.getMemberId()).ifPresent(member -> {
                Map<String, Object> profile = new LinkedHashMap<>();
                profile.put("firstName", member.getFirstName());
                profile.put("lastName", member.getLastName());
                profile.put("dateOfBirth", member.getDateOfBirth() != null ? member.getDateOfBirth().toString() : null);
                profile.put("memberNumber", member.getMembershipNumber());
                profile.put("status", member.getStatus().name());
                profile.put("joinedAt", member.getCreatedAt() != null ? member.getCreatedAt().toString() : null);
                export.put("memberProfile", profile);
            });
        }

        // Distribution history
        if (user != null && user.getMemberId() != null) {
            UUID memberId = user.getMemberId();
            List<Distribution> distributions = distributionRepository.findByMemberIdAndTenantId(memberId, tenantId);
            List<Map<String, Object>> distList = distributions.stream()
                    .map(d -> {
                        Map<String, Object> entry = new LinkedHashMap<>();
                        entry.put("id", d.getId().toString());
                        entry.put("amountGrams", d.getQuantityGrams());
                        entry.put("distributedAt", d.getDistributedAt() != null ? d.getDistributedAt().toString() : null);
                        return entry;
                    })
                    .toList();
            export.put("distributions", distList);
        }

        // Consent records
        List<Consent> consents = consentRepository.findByUserId(userId);
        List<Map<String, Object>> consentList = consents.stream()
                .map(c -> {
                    Map<String, Object> entry = new LinkedHashMap<>();
                    entry.put("type", c.getConsentType().name());
                    entry.put("granted", c.isGranted());
                    entry.put("grantedAt", c.getGrantedAt() != null ? c.getGrantedAt().toString() : null);
                    entry.put("revokedAt", c.getRevokedAt() != null ? c.getRevokedAt().toString() : null);
                    entry.put("version", c.getVersion());
                    return entry;
                })
                .toList();
        export.put("consents", consentList);

        return export;
    }

    /**
     * Delete/anonymize all personal data for a user (Art. 17 DSGVO).
     * - Anonymizes personal data (name, email → "GELÖSCHT")
     * - Keeps distribution records (compliance) but anonymizes member reference
     * - Revokes all consents
     * - Deactivates account
     */
    @Transactional
    public void deleteUserData(UUID userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("User not found: " + userId));

        // Anonymize member profile
        if (user.getMemberId() != null) {
            memberRepository.findById(user.getMemberId()).ifPresent(member -> {
                member.setFirstName(ANONYMIZED);
                member.setLastName(ANONYMIZED);
                member.setEmail(ANONYMIZED + "@deleted.local");
                memberRepository.save(member);
                log.info("Member profile anonymized: memberId={}", member.getId());
            });
        }

        // Revoke all consents
        consentService.revokeAllConsents(userId);

        // Anonymize and deactivate user account
        user.setEmail(ANONYMIZED + "_" + userId + "@deleted.local");
        user.setPasswordHash(ANONYMIZED);
        user.setRefreshTokenHash(null);
        user.setActive(false);
        userRepository.save(user);

        log.info("User data deleted/anonymized: userId={}", userId);
    }
}
