package com.gnx.telemedicine.service;

import com.gnx.telemedicine.model.DataRetentionPolicy;
import com.gnx.telemedicine.repository.DataRetentionPolicyRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
public class DataRetentionService {
    
    private final DataRetentionPolicyRepository policyRepository;

    @Transactional(readOnly = true)
    public List<DataRetentionPolicy> getAllPolicies() {
        return policyRepository.findAll();
    }

    @Transactional(readOnly = true)
    public Optional<DataRetentionPolicy> getPolicyByDataType(String dataType) {
        return policyRepository.findByDataType(dataType);
    }

    @Transactional
    public DataRetentionPolicy createOrUpdatePolicy(
            String dataType,
            Integer retentionPeriodDays,
            Boolean autoDeleteEnabled,
            String legalRequirement) {
        
        Optional<DataRetentionPolicy> existingPolicy = policyRepository.findByDataType(dataType);
        
        DataRetentionPolicy policy;
        if (existingPolicy.isPresent()) {
            policy = existingPolicy.get();
        } else {
            policy = new DataRetentionPolicy();
            policy.setDataType(dataType);
        }
        
        policy.setRetentionPeriodDays(retentionPeriodDays);
        policy.setAutoDeleteEnabled(autoDeleteEnabled != null ? autoDeleteEnabled : false);
        policy.setLegalRequirement(legalRequirement);
        
        return policyRepository.save(policy);
    }

    @Transactional
    @Scheduled(cron = "0 0 2 * * ?") // Run daily at 2 AM
    public void cleanupExpiredData() {
        log.info("Starting data retention cleanup job");
        
        List<DataRetentionPolicy> policies = policyRepository.findAll();
        
        for (DataRetentionPolicy policy : policies) {
            if (Boolean.TRUE.equals(policy.getAutoDeleteEnabled())) {
                cleanupDataByType(policy);
            }
        }
        
        log.info("Data retention cleanup job completed");
    }

    private void cleanupDataByType(DataRetentionPolicy policy) {
        Instant cutoffDate = Instant.now().minus(policy.getRetentionPeriodDays(), ChronoUnit.DAYS);
        
        try {
            switch (policy.getDataType()) {
                case "AUDIT_LOG":
                    // Cleanup would be implemented based on specific audit log repository
                    log.info("Cleaning up audit logs older than {}", cutoffDate);
                    // Example: auditLogRepository.deleteByTimestampBefore(cutoffDate);
                    break;
                case "PHI_ACCESS_LOG":
                    log.info("Cleaning up PHI access logs older than {}", cutoffDate);
                    // Example: phiAccessLogRepository.deleteByTimestampBefore(cutoffDate);
                    break;
                case "HIPAA_AUDIT_LOG":
                    log.info("Cleaning up HIPAA audit logs older than {}", cutoffDate);
                    // Example: hipaaAuditLogRepository.deleteByTimestampBefore(cutoffDate);
                    break;
                case "MESSAGE":
                    log.info("Cleaning up messages older than {}", cutoffDate);
                    // Example: messageRepository.deleteByCreatedAtBefore(cutoffDate);
                    break;
                default:
                    log.warn("Unknown data type for cleanup: {}", policy.getDataType());
            }
            
            policy.setLastCleanupAt(Instant.now());
            policyRepository.save(policy);
            
        } catch (Exception e) {
            log.error("Error cleaning up data for type {}: {}", policy.getDataType(), e.getMessage(), e);
        }
    }

    @Transactional(readOnly = true)
    public Instant getRetentionCutoffDate(String dataType) {
        return policyRepository.findByDataType(dataType)
                .map(policy -> Instant.now().minus(policy.getRetentionPeriodDays(), ChronoUnit.DAYS))
                .orElse(Instant.now().minus(365, ChronoUnit.DAYS)); // Default 1 year
    }
}

