package com.saas.tenant.service;

import com.saas.tenant.dto.request.CreateMedicalServiceRequest;
import com.saas.tenant.dto.request.UpdateMedicalServiceRequest;
import com.saas.tenant.dto.response.MedicalServiceResponse;
import com.saas.tenant.entity.MedicalService;
import com.saas.tenant.entity.ServiceType;
import com.saas.tenant.repository.MedicalServiceRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@RequiredArgsConstructor
@Slf4j
public class MedicalServiceService {

    private final MedicalServiceRepository medicalServiceRepository;

    @Transactional
    public MedicalServiceResponse createMedicalService(CreateMedicalServiceRequest request) {
        log.info("Creating new medical service: {}", request.getName());

        MedicalService medicalService = new MedicalService();
        medicalService.setName(request.getName());
        medicalService.setDescription(request.getDescription());
        medicalService.setType(request.getType());
        medicalService.setDurationMinutes(request.getDurationMinutes());
        medicalService.setStandardPrice(request.getStandardPrice());
        medicalService.setDoctorSpecificPrice(request.getDoctorSpecificPrice());
        medicalService.setKeywords(request.getKeywords());
        medicalService.setAssociatedSymptoms(request.getAssociatedSymptoms());
        medicalService.setDoctorId(request.getDoctorId());
        medicalService.setRequiresResource(request.getRequiresResource());
        medicalService.setRequiredResourceType(request.getRequiredResourceType());

        MedicalService savedService = medicalServiceRepository.save(medicalService);
        log.info("Medical service created successfully with ID: {}", savedService.getId());

        return mapToResponse(savedService);
    }

    @Transactional
    public MedicalServiceResponse updateMedicalService(Long id, UpdateMedicalServiceRequest request) {
        log.info("Updating medical service with ID: {}", id);

        MedicalService medicalService = medicalServiceRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Medical service not found with ID: " + id));

        if (request.getName() != null)
            medicalService.setName(request.getName());
        if (request.getDescription() != null)
            medicalService.setDescription(request.getDescription());
        if (request.getType() != null)
            medicalService.setType(request.getType());
        if (request.getDurationMinutes() != null)
            medicalService.setDurationMinutes(request.getDurationMinutes());
        if (request.getStandardPrice() != null)
            medicalService.setStandardPrice(request.getStandardPrice());
        if (request.getDoctorSpecificPrice() != null)
            medicalService.setDoctorSpecificPrice(request.getDoctorSpecificPrice());
        if (request.getKeywords() != null)
            medicalService.setKeywords(request.getKeywords());
        if (request.getAssociatedSymptoms() != null)
            medicalService.setAssociatedSymptoms(request.getAssociatedSymptoms());
        if (request.getDoctorId() != null)
            medicalService.setDoctorId(request.getDoctorId());
        if (request.getRequiresResource() != null)
            medicalService.setRequiresResource(request.getRequiresResource());
        if (request.getRequiredResourceType() != null)
            medicalService.setRequiredResourceType(request.getRequiredResourceType());

        MedicalService updatedService = medicalServiceRepository.save(medicalService);
        log.info("Medical service updated successfully: {}", updatedService.getId());

        return mapToResponse(updatedService);
    }

    @Transactional(readOnly = true)
    public MedicalServiceResponse getMedicalServiceById(Long id) {
        log.info("Fetching medical service with ID: {}", id);
        MedicalService medicalService = medicalServiceRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Medical service not found with ID: " + id));
        return mapToResponse(medicalService);
    }

    @Transactional(readOnly = true)
    public List<MedicalServiceResponse> getAllMedicalServices() {
        log.info("Fetching all medical services");
        return medicalServiceRepository.findAll().stream()
                .map(this::mapToResponse)
                .collect(Collectors.toList());
    }

    @Transactional(readOnly = true)
    public List<MedicalServiceResponse> getMedicalServicesByType(ServiceType type) {
        log.info("Fetching medical services by type: {}", type);
        return medicalServiceRepository.findByType(type).stream()
                .map(this::mapToResponse)
                .collect(Collectors.toList());
    }

    @Transactional(readOnly = true)
    public List<MedicalServiceResponse> searchBySymptom(String symptom) {
        log.info("Searching medical services by symptom: {}", symptom);
        return medicalServiceRepository.findBySymptom(symptom).stream()
                .map(this::mapToResponse)
                .collect(Collectors.toList());
    }

    @Transactional(readOnly = true)
    public List<MedicalServiceResponse> searchByKeyword(String keyword) {
        log.info("Searching medical services by keyword: {}", keyword);
        return medicalServiceRepository.findByKeyword(keyword).stream()
                .map(this::mapToResponse)
                .collect(Collectors.toList());
    }

    @Transactional(readOnly = true)
    public List<MedicalServiceResponse> searchByNameOrDescription(String searchTerm) {
        log.info("Searching medical services by name or description: {}", searchTerm);
        return medicalServiceRepository.searchByNameOrDescription(searchTerm).stream()
                .map(this::mapToResponse)
                .collect(Collectors.toList());
    }

    @Transactional
    public void deleteMedicalService(Long id) {
        log.info("Deleting medical service with ID: {}", id);
        medicalServiceRepository.deleteById(id);
        log.info("Medical service deleted successfully: {}", id);
    }

    private MedicalServiceResponse mapToResponse(MedicalService medicalService) {
        return MedicalServiceResponse.builder()
                .id(medicalService.getId())
                .name(medicalService.getName())
                .description(medicalService.getDescription())
                .type(medicalService.getType())
                .durationMinutes(medicalService.getDurationMinutes())
                .standardPrice(medicalService.getStandardPrice())
                .doctorSpecificPrice(medicalService.getDoctorSpecificPrice())
                .keywords(medicalService.getKeywords())
                .associatedSymptoms(medicalService.getAssociatedSymptoms())
                .doctorId(medicalService.getDoctorId())
                .requiresResource(medicalService.getRequiresResource())
                .requiredResourceType(medicalService.getRequiredResourceType())
                .createdAt(medicalService.getCreatedAt())
                .updatedAt(medicalService.getUpdatedAt())
                .build();
    }
}
