package com.saas.voip.controller;

import com.saas.admin.entity.PhoneNumber;
import com.saas.admin.entity.Tenant;
import com.saas.admin.repository.PhoneNumberRepository;
import com.saas.admin.repository.TenantRepository;
import com.saas.shared.core.TenantContext;
import com.saas.tenant.service.InboundCallService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;

import java.util.Enumeration;
import java.util.Optional;

@RestController
@RequestMapping("/api/voip/sms")
@Slf4j
@RequiredArgsConstructor
public class TwilioSmsCallbackController {

    private final InboundCallService inboundCallService;
    private final PhoneNumberRepository phoneNumberRepository;
    private final TenantRepository tenantRepository;

    @PostMapping(value = "/status-callback", produces = MediaType.APPLICATION_XML_VALUE)
    public String handleSmsStatusCallback(HttpServletRequest request) {
        MultiValueMap<String, String> formData = extractFormData(request);
        
        String messageSid = formData.getFirst("MessageSid");
        String messageStatus = formData.getFirst("MessageStatus");
        String to = formData.getFirst("To");
        String from = formData.getFirst("From"); // Numéro Twilio (notre numéro)
        
        log.info("📬 Callback SMS reçu - SID: {} | Statut: {} | From (Twilio): {} | To (Patient): {}", 
                messageSid, messageStatus, from, to);
        
        // Log all parameters for debugging
        formData.forEach((key, values) -> 
            log.debug("SMS Callback param - {}: {}", key, values.get(0))
        );
        
        String errorCode = formData.getFirst("ErrorCode");
        String errorMessage = formData.getFirst("ErrorMessage");
        
        if (errorCode != null) {
            log.error("❌ SMS Error - Code: {}, Message: {}", errorCode, errorMessage);
        }
        
        try {
            // STEP 1: Identifier le tenant via le numéro Twilio (From)
            // On cherche dans la table admin TwilioPhoneNumber
            TenantContext.setTenantId("admin"); // Set admin context for lookup
            
            Optional<PhoneNumber> phoneNumberOpt = phoneNumberRepository.findByPhoneNumber(from);
            
            if (phoneNumberOpt.isEmpty()) {
                log.warn("⚠️ Numéro inconnu: {} - Impossible d'identifier le tenant", from);
                return "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response></Response>";
            }
            
            PhoneNumber phoneNumber = phoneNumberOpt.get();
            String tenantId = phoneNumber.getTenantId();
            
            // STEP 2: Get tenant schema name from Tenant table
            Optional<Tenant> tenantOpt = tenantRepository.findByTenantId(tenantId);
            
            if (tenantOpt.isEmpty()) {
                log.warn("⚠️ Tenant non trouvé pour ID: {}", tenantId);
                return "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response></Response>";
            }
            
            String schemaName = tenantOpt.get().getSchemaName();
            
            log.info("🏢 Tenant identifié via numéro Twilio {} → Tenant ID: {} | Schema: {}", 
                    from, tenantId, schemaName);
            
            // STEP 3: Switch vers le schéma du tenant
            TenantContext.setTenantId(schemaName);
            
            // STEP 4: Mettre à jour le statut SMS dans la base tenant
            boolean updated = inboundCallService.updateSmsStatus(messageSid, messageStatus);
            
            if (updated) {
                log.info("✅ Statut SMS mis à jour dans {} : {} → {}", schemaName, messageSid, messageStatus);
            } else {
                log.warn("⚠️ SMS non trouvé dans {} pour SID: {}", schemaName, messageSid);
            }
            
        } catch (Exception e) {
            log.error("❌ Erreur lors de la mise à jour du statut SMS: {}", e.getMessage(), e);
        } finally {
            // STEP 5: Nettoyer le contexte tenant
            TenantContext.clear();
        }
        
        // Return empty TwiML response (Twilio expects a response)
        return "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response></Response>";
    }
    
    @GetMapping(value = "/status-callback", produces = MediaType.APPLICATION_XML_VALUE)
    public String handleSmsStatusCallbackGet(HttpServletRequest request) {
        return handleSmsStatusCallback(request);
    }
    
    private MultiValueMap<String, String> extractFormData(HttpServletRequest request) {
        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();
        
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            String[] paramValues = request.getParameterValues(paramName);
            for (String paramValue : paramValues) {
                formData.add(paramName, paramValue);
            }
        }
        
        return formData;
    }
}
