package de.cannamanage.service;

import de.cannamanage.domain.entity.Club;
import de.cannamanage.domain.enums.BatchStatus;
import de.cannamanage.domain.enums.MemberStatus;
import de.cannamanage.service.repository.BatchRepository;
import de.cannamanage.service.repository.ClubRepository;
import de.cannamanage.service.repository.DistributionRepository;
import de.cannamanage.service.repository.MemberRepository;
import de.cannamanage.service.repository.StaffAccountRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

@Slf4j
@Service
@RequiredArgsConstructor
public class ClubService {

    private final ClubRepository clubRepository;
    private final MemberRepository memberRepository;
    private final StaffAccountRepository staffAccountRepository;
    private final DistributionRepository distributionRepository;
    private final BatchRepository batchRepository;

    @Transactional(readOnly = true)
    public Club getClubByTenantId(UUID tenantId) {
        return clubRepository.findByTenantId(tenantId)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Club not found for tenant"));
    }

    @Transactional
    public Club updateClub(UUID tenantId, String name, String registrationNumber,
                           String contactEmail, String contactPhone,
                           String addressStreet, String addressCity,
                           String addressPostalCode, String addressState,
                           LocalDate foundedDate,
                           Integer maxPreventionOfficers, String allowedEmailPattern) {
        Club club = getClubByTenantId(tenantId);

        // Validate regex pattern if provided
        if (allowedEmailPattern != null && !allowedEmailPattern.isBlank()) {
            validateRegexPattern(allowedEmailPattern);
        }

        club.setName(name);
        club.setRegistrationNumber(registrationNumber);
        club.setContactEmail(contactEmail);
        club.setContactPhone(contactPhone);
        club.setAddressStreet(addressStreet);
        club.setAddressCity(addressCity);
        club.setAddressPostalCode(addressPostalCode);
        club.setAddressState(addressState);
        club.setFoundedDate(foundedDate);
        if (maxPreventionOfficers != null) {
            club.setMaxPreventionOfficers(maxPreventionOfficers);
        }
        club.setAllowedEmailPattern(allowedEmailPattern);

        return clubRepository.save(club);
    }

    @Transactional(readOnly = true)
    public ClubStats getClubStats(UUID tenantId) {
        long totalMembers = memberRepository.countByTenantId(tenantId);
        long activeMembers = memberRepository.countByTenantIdAndStatus(tenantId, MemberStatus.ACTIVE);
        long totalStaff = staffAccountRepository.countByTenantId(tenantId);
        long activeStaff = staffAccountRepository.countByTenantIdAndActiveTrue(tenantId);

        // Distributions this month
        Instant startOfMonth = LocalDate.now().withDayOfMonth(1)
                .atStartOfDay(ZoneOffset.UTC).toInstant();
        long totalDistributionsThisMonth = distributionRepository
                .countByTenantIdAndDistributedAtAfter(tenantId, startOfMonth);
        BigDecimal totalGramsThisMonth = distributionRepository
                .sumGramsByTenantIdAndDistributedAtAfter(tenantId, startOfMonth);

        long activeBatches = batchRepository.countByTenantIdAndStatus(tenantId, BatchStatus.AVAILABLE);
        long preventionOfficerCount = staffAccountRepository.countByTenantIdAndPreventionOfficerTrue(tenantId);

        return new ClubStats(
                totalMembers, activeMembers,
                totalStaff, activeStaff,
                totalDistributionsThisMonth,
                totalGramsThisMonth != null ? totalGramsThisMonth : BigDecimal.ZERO,
                activeBatches, preventionOfficerCount
        );
    }

    private void validateRegexPattern(String pattern) {
        try {
            Pattern.compile(pattern);
        } catch (PatternSyntaxException e) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
                    "Invalid regex pattern for allowedEmailPattern: " + e.getDescription());
        }
    }

    public record ClubStats(
            long totalMembers,
            long activeMembers,
            long totalStaff,
            long activeStaff,
            long totalDistributionsThisMonth,
            BigDecimal totalGramsDistributedThisMonth,
            long activeBatches,
            long preventionOfficerCount
    ) {}
}
