package com.gnx.telemedicine.controller;

import com.gnx.telemedicine.config.TurnConfig;
import com.gnx.telemedicine.dto.turn.TurnConfigResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v3/turn")
@RequiredArgsConstructor
@Tag(name = "TURN Configuration", description = "Endpoints for WebRTC TURN server configuration")
public class TurnController {

    private final TurnConfig turnConfig;
    
    @Value("${webrtc.turn.public-ip:193.194.155.249}")
    private String publicIp;
    
    @Value("${webrtc.turn.public-port:${webrtc.turn.port:3478}}")
    private Integer publicPort;

    @Operation(
            summary = "Get TURN server configuration",
            description = "Retrieve the TURN server configuration for WebRTC connections. This endpoint is public and does not require authentication."
    )
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "TURN configuration retrieved successfully"
            )
    })
    @GetMapping("/config")
    public ResponseEntity<TurnConfigResponseDto> getTurnConfig(HttpServletRequest request) {
        // Detect if request is from public IP, local network IP, or localhost
        String origin = request.getHeader("Origin");
        String host = request.getHeader("Host");
        String remoteAddr = request.getRemoteAddr();
        String serverIp = turnConfig.getServer();
        Integer port = turnConfig.getPort();
        
        // Check if request is from public IP (not localhost or private network)
        boolean isPublicAccess = false;
        String requestIp = null;
        
        // Extract IP from origin or host
        if (origin != null && !origin.contains("localhost") && !origin.contains("127.0.0.1")) {
            // Extract IP from origin (e.g., "https://192.168.1.6:4200")
            String originHost = origin.replace("https://", "").replace("http://", "").split(":")[0];
            requestIp = originHost;
        } else if (host != null && !host.contains("localhost") && !host.contains("127.0.0.1")) {
            // Extract IP from host header
            requestIp = host.split(":")[0];
        } else if (remoteAddr != null && !remoteAddr.equals("localhost") && !remoteAddr.equals("127.0.0.1")) {
            requestIp = remoteAddr;
        }
        
        // Determine if it's a public IP (not private network range)
        if (requestIp != null && !requestIp.equals("localhost") && !requestIp.equals("127.0.0.1")) {
            // Check if it's a private network IP
            boolean isPrivateNetwork = requestIp.startsWith("192.168.") || 
                                      requestIp.startsWith("10.") || 
                                      requestIp.startsWith("172.16.") || 
                                      requestIp.startsWith("172.17.") || 
                                      requestIp.startsWith("172.18.") || 
                                      requestIp.startsWith("172.19.") || 
                                      requestIp.startsWith("172.20.") || 
                                      requestIp.startsWith("172.21.") || 
                                      requestIp.startsWith("172.22.") || 
                                      requestIp.startsWith("172.23.") || 
                                      requestIp.startsWith("172.24.") || 
                                      requestIp.startsWith("172.25.") || 
                                      requestIp.startsWith("172.26.") || 
                                      requestIp.startsWith("172.27.") || 
                                      requestIp.startsWith("172.28.") || 
                                      requestIp.startsWith("172.29.") || 
                                      requestIp.startsWith("172.30.") || 
                                      requestIp.startsWith("172.31.");
            
            if (isPrivateNetwork) {
                // Use the local network IP for TURN server
                serverIp = requestIp;
                port = turnConfig.getPort(); // Use local port
            } else {
                // Public IP access
                isPublicAccess = true;
                serverIp = publicIp;
                port = publicPort;
            }
        }
        
        // Build STUN/TURN URLs with public STUN servers as fallback
        String stunUrls;
        String turnUrls;
        
        if (isPublicAccess) {
            // For public access, use public STUN servers and configured TURN
            stunUrls = String.format("stun:stun.l.google.com:19302,stun:stun1.l.google.com:19302,stun:%s:%d", serverIp, port);
            turnUrls = String.format("turn:%s:%d", serverIp, port);
        } else {
            // For localhost, use local TURN server
            stunUrls = String.format("stun:%s:%d", serverIp, port);
            turnUrls = String.format("turn:%s:%d", serverIp, port);
        }
        
        TurnConfigResponseDto config = TurnConfigResponseDto.builder()
                .server(serverIp)
                .port(port)
                .username(turnConfig.getUsername())
                .password(turnConfig.getPassword())
                .realm(turnConfig.getRealm())
                .stunUrls(stunUrls)
                .turnUrls(turnUrls)
                .build();
        
        return ResponseEntity.ok(config);
    }
}

