package com.gnx.telemedicine.service;

import com.gnx.telemedicine.model.AccountingOfDisclosure;
import com.gnx.telemedicine.model.Patient;
import com.gnx.telemedicine.model.UserModel;
import com.gnx.telemedicine.model.enums.DisclosureType;
import com.gnx.telemedicine.repository.AccountingOfDisclosureRepository;
import com.gnx.telemedicine.repository.PatientRepository;
import com.gnx.telemedicine.repository.UserRepository;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
public class HipaaAccountingOfDisclosureService {
    
    private final AccountingOfDisclosureRepository disclosureRepository;
    private final PatientRepository patientRepository;
    private final UserRepository userRepository;

    @Transactional
    public AccountingOfDisclosure logDisclosure(
            UUID patientId,
            String userEmail,
            DisclosureType disclosureType,
            String purpose,
            String recipientName,
            String recipientAddress,
            String informationDisclosed,
            UUID authorizedByUserId,
            HttpServletRequest request) {
        
        Patient patient = patientRepository.findById(patientId)
                .orElseThrow(() -> new IllegalArgumentException("Patient not found"));
        
        UserModel user = userRepository.findByEmail(userEmail)
                .orElseThrow(() -> new IllegalArgumentException("User not found"));

        AccountingOfDisclosure disclosure = new AccountingOfDisclosure();
        disclosure.setPatient(patient);
        disclosure.setUser(user);
        disclosure.setDisclosureType(disclosureType);
        disclosure.setPurpose(purpose);
        disclosure.setRecipientName(recipientName);
        disclosure.setRecipientAddress(recipientAddress);
        disclosure.setInformationDisclosed(informationDisclosed);
        disclosure.setDisclosureDate(Instant.now());

        if (authorizedByUserId != null) {
            UserModel authorizedBy = userRepository.findById(authorizedByUserId)
                    .orElseThrow(() -> new IllegalArgumentException("Authorized user not found"));
            disclosure.setAuthorizedBy(authorizedBy);
            disclosure.setAuthorizationDate(Instant.now());
        }

        return disclosureRepository.save(disclosure);
    }

    @Transactional(readOnly = true)
    public List<AccountingOfDisclosure> getDisclosuresByPatient(UUID patientId) {
        Patient patient = patientRepository.findById(patientId)
                .orElseThrow(() -> new IllegalArgumentException("Patient not found"));
        
        return disclosureRepository.findByPatient(patient);
    }

    @Transactional(readOnly = true)
    public List<AccountingOfDisclosure> getDisclosuresByPatientAndDateRange(
            UUID patientId, Instant startDate, Instant endDate) {
        Patient patient = patientRepository.findById(patientId)
                .orElseThrow(() -> new IllegalArgumentException("Patient not found"));
        
        return disclosureRepository.findByPatientAndDisclosureDateBetween(patient, startDate, endDate);
    }

    @Transactional(readOnly = true)
    public List<AccountingOfDisclosure> getDisclosuresByUser(String userEmail) {
        UserModel user = userRepository.findByEmail(userEmail)
                .orElseThrow(() -> new IllegalArgumentException("User not found"));
        
        return disclosureRepository.findByUser(user);
    }
}

