package com.walkguide.service;

import com.walkguide.dto.request.VoiceCommandUpdateRequest;
import com.walkguide.dto.response.VoiceCommandResponse;
import com.walkguide.enums.PairingStatus;
import com.walkguide.enums.VoiceCommandKey;
import com.walkguide.exception.PairingException;
import com.walkguide.exception.ResourceNotFoundException;
import com.walkguide.repository.PairingRelationRepository;
import com.walkguide.repository.VoiceCommandConfigRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

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

@Service
@RequiredArgsConstructor
public class VoiceCommandService {

    private static final Map<VoiceCommandKey, String> DESCRIPTIONS = Map.ofEntries(
        Map.entry(VoiceCommandKey.OPEN_WALKGUIDE,    "Buka menu WalkGuide"),
        Map.entry(VoiceCommandKey.START_WALKGUIDE,   "Mulai deteksi WalkGuide"),
        Map.entry(VoiceCommandKey.STOP_WALKGUIDE,    "Hentikan WalkGuide"),
        Map.entry(VoiceCommandKey.CALL_GUARDIAN,     "Telepon Guardian"),
        Map.entry(VoiceCommandKey.OPEN_NOTIFICATION, "Buka menu Notifikasi"),
        Map.entry(VoiceCommandKey.READ_ALL_NOTIF,    "Baca semua notifikasi dengan TTS"),
        Map.entry(VoiceCommandKey.OPEN_SOS,         "Buka menu SOS"),
        Map.entry(VoiceCommandKey.SEND_SOS,         "Kirim sinyal darurat SOS"),
        Map.entry(VoiceCommandKey.WHERE_AM_I,       "Umumkan lokasi saat ini via TTS"),
        Map.entry(VoiceCommandKey.OPEN_ACTIVITY,    "Buka log aktivitas"),
        Map.entry(VoiceCommandKey.OPEN_NAVIGATION,  "Buka mode navigasi"),
        Map.entry(VoiceCommandKey.OPEN_SETTINGS,    "Buka pengaturan"),
        Map.entry(VoiceCommandKey.REPEAT_LAST,      "Ulangi TTS terakhir"),
        Map.entry(VoiceCommandKey.STOP_TTS,         "Hentikan TTS yang sedang berjalan")
    );

    private final VoiceCommandConfigRepository voiceCommandConfigRepository;
    private final PairingRelationRepository pairingRelationRepository;
    private final FcmService fcmService;

    public List<VoiceCommandResponse> getAll(Long userId) {
        return voiceCommandConfigRepository.findByUserId(userId).stream()
                .map(vc -> VoiceCommandResponse.builder()
                        .id(vc.getId())
                        .commandKey(vc.getCommandKey().name())
                        .triggerPhrase(vc.getTriggerPhrase())
                        .enabled(vc.getEnabled())
                        .description(DESCRIPTIONS.getOrDefault(vc.getCommandKey(), ""))
                        .build())
                .collect(Collectors.toList());
    }

    public VoiceCommandResponse updateByGuardian(Long guardianId, VoiceCommandUpdateRequest req) {
        var pairing = pairingRelationRepository
                .findByGuardian_IdAndStatus(guardianId, PairingStatus.ACTIVE)
                .orElseThrow(() -> new PairingException("Tidak ada user yang dipair"));
        Long userId = pairing.getUser().getId();

        VoiceCommandKey key = VoiceCommandKey.valueOf(req.getCommandKey());
        var vc = voiceCommandConfigRepository.findByUserIdAndCommandKey(userId, key)
                .orElseThrow(() -> new ResourceNotFoundException("Voice command tidak ditemukan"));

        if (req.getTriggerPhrase() != null && !req.getTriggerPhrase().isBlank())
            vc.setTriggerPhrase(req.getTriggerPhrase());
        if (req.getEnabled() != null)
            vc.setEnabled(req.getEnabled());

        vc = voiceCommandConfigRepository.save(vc);

        fcmService.sendToToken(pairing.getUser().getFcmToken(),
                "Voice Command Diperbarui",
                "Guardian mengubah perintah suara kamu",
                Map.of("type", "SETTINGS_UPDATED", "settingType", "VOICE_COMMAND"));

        return VoiceCommandResponse.builder()
                .id(vc.getId()).commandKey(vc.getCommandKey().name())
                .triggerPhrase(vc.getTriggerPhrase()).enabled(vc.getEnabled())
                .description(DESCRIPTIONS.getOrDefault(vc.getCommandKey(), "")).build();
    }
}
