package com.hepl.tunefortwo.service.impl;


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

import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;

import com.hepl.tunefortwo.dto.AccessControlStatus;
import com.hepl.tunefortwo.dto.InstrumentImagesDTO;
import com.hepl.tunefortwo.dto.InstrumentRequestDto;
import com.hepl.tunefortwo.entity.Instrument;
import com.hepl.tunefortwo.repository.InstrumentRepository;
import com.hepl.tunefortwo.service.InstrumentService;
import com.hepl.tunefortwo.utils.AppMessages;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class InstrumentServiceImpl implements InstrumentService {

	private final InstrumentRepository instrumentRepository;

	private final MongoTemplate mongoTemplate;

	public InstrumentServiceImpl(InstrumentRepository instrumentRepository, MongoTemplate mongoTemplate) {
		this.instrumentRepository = instrumentRepository;
		this.mongoTemplate = mongoTemplate;
	}

	@Override
	public Instrument saveInstrument(InstrumentRequestDto data) {
		log.info("save Instrument");
		Instrument instrument = new Instrument();
		Instrument existingInstrument = instrumentRepository.findByName(data.getName());
		if (existingInstrument != null) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
					"An Instrument already exists with the " + "name :" + data.getName());
		}
		instrument.setName(data.getName());
		instrument.setPrice(data.getPrice());
		instrument.setAudio(data.getAudioPath());
		instrument.setAudioDuration(data.getAudioDuration());
		instrument.setDescription(data.getDescription());
		instrument.setImage(data.getImage());
		instrument.setImage(data.getImage());
		instrument.setImageTitle(data.getImageTitle());
		instrument.setBestSeller(data.isBestSeller());
		if(data.getInstrumentCategory()!=null){
			instrument.setInstrumentCategory(data.getInstrumentCategory());
		}
		return instrumentRepository.save(instrument);
	}

//	@Override
//	public java.util.List<Instrument> getAllInstruments() {
//		log.info("Get all Instruments");
//		return instrumentRepository.findAll();
//	}
	@Override
	public List<Instrument> getAllInstrumentsSortedByPrice(Sort.Direction direction) {
	    log.info("Get all Instruments sorted by price in {} order", direction);
	    return instrumentRepository.findActiveInstrumentsSortedByPrice(direction);
	}
	
	@Override
	public java.util.List<Instrument> getAllInstrumentsByActive() {
		log.info("Get all Instruments");
		return instrumentRepository.findActiveInstruments(Sort.by(Sort.Order.asc("price")));
	}

	@Override
	public void updateInstrument(InstrumentRequestDto requestDto, String id) {
		log.info("Updating instrument with ID: {}", id);
		Instrument existingInstrument = instrumentRepository.findById(id)
				.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
						AppMessages.INSTRUMENT_NOT_FOUND + "with ID: " + id));
		if (!existingInstrument.getName().equals(requestDto.getName())) {
			Instrument instrumentWithSameName = instrumentRepository.findByName(requestDto.getName());
			if (instrumentWithSameName != null && !instrumentWithSameName.getId().equals(id)) {
				throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
						"An Instrument already exists with the " + "name :" + requestDto.getName());
			}
		}
		existingInstrument.setName(requestDto.getName());
		existingInstrument.setPrice(requestDto.getPrice());
		if(requestDto.getAudio()!=null) {
			existingInstrument.setAudio(requestDto.getAudioPath());
		}
		existingInstrument.setImage(requestDto.getImage());
		existingInstrument.setDescription(requestDto.getDescription());
		existingInstrument.setImageTitle(requestDto.getImageTitle());
		existingInstrument.setBestSeller(requestDto.isBestSeller());
		if(requestDto.getAudioDuration()!=null) {
			existingInstrument.setAudioDuration(requestDto.getAudioDuration());	
		}
		if(requestDto.getInstrumentCategory()!=null) {
			existingInstrument.setInstrumentCategory(requestDto.getInstrumentCategory());
		}
		
		instrumentRepository.save(existingInstrument);
	}	

	@Override
	public Instrument getInstrumentById(String id) {
		log.info("Get instrument by id");
		Instrument instrument = instrumentRepository.findById(id)
				.orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, AppMessages.RESOURCE_NOT_FOUND));
		return instrument;
	}
	
	@Override
	public void updateActionControlStatus(AccessControlStatus status, String id) {
		log.info("Change action status .. ", id);
		instrumentRepository.updateAccessControlStatus(id, status.toString(), mongoTemplate);
	}
//	@Override
	public Long countAllInstrument() {
		log.info("Count all instrument");
		return instrumentRepository.count();
	}
	@Override
	public void deleteInstrument(String id) {
		log.info("Delete instrument");
		 instrumentRepository.deleteById(id);
	}
	
	@Override
	public void deleteAllInstrument(List<String> ids) {
	    log.info("Delete all instrument");
	    for (String id : ids) {
	        instrumentRepository.deleteById(id);
	    }
	}

	@Override
	public void updateAllActionControlStatus(AccessControlStatus status, List<String> ids) {
		log.info("Change action status .. {} "+ ids);
		for(String id : ids) {
			instrumentRepository.updateAccessControlStatus(id, status.toString(), mongoTemplate);
		}
		
	}

	@Override
	public List<InstrumentImagesDTO> getAllImagesForInstruments() {
	    List<Instrument> allInst = instrumentRepository.findAll();
	    if (allInst.isEmpty()) {
	        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, AppMessages.RESOURCE_NOT_FOUND);
	    }
	    List<InstrumentImagesDTO> instrumentImages = allInst.stream()
	            .map(inst -> new InstrumentImagesDTO(inst.getName(), inst.getImage(),inst.getImageTitle()))
	            .collect(Collectors.toList());
	    Map<String, Object> data = new HashMap<>();
	    data.put("allInstrumentImages", instrumentImages);

	    return instrumentImages;
	}








}
