package com.arms.api.configserver.controller;

import com.arms.api.configserver.model.ArmsApplicationProperties;
import com.arms.api.util.aspect.SlackSendAlarm;
import com.arms.api.util.slack.SlackNotificationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@RestController
@RequestMapping("/api/config-server")
@RequiredArgsConstructor
public class ConfigServerWebhookController {

    private final WebClient.Builder webClientBuilder;

    private final ArmsApplicationProperties armsApplicationProperties;

    @PostMapping("/config-changed")
    @SlackSendAlarm(messageOnEnd = "A-RMS MSA 환경 파일 리플레시 및 적용 완료")
    public ResponseEntity<String> handlerConfigChanged(@RequestBody Map<String, Object> payload) {

        List<String> changedFiles = extractChangedFiles(payload);

        Set<String> matchedKeys = extractMsaUrls(changedFiles);

        matchedKeys.forEach(serviceKey -> {
            ArmsApplicationProperties.ConfigClientUrl connectUrl = armsApplicationProperties.getUrls().get(serviceKey);
            if (connectUrl != null) {
                String refreshUrl = connectUrl.getUrl() + "/actuator/refresh";
                log.info("[ConfigServerWebhookController :: handlerConfigChanged ] :: refreshUrl => {}", refreshUrl);
                sendRefreshRequest(refreshUrl);
            }
        });

        return ResponseEntity.ok("Processed");
    }

    private List<String> extractChangedFiles(Map<String, Object> payload) {
        List<String> files = new ArrayList<>();

        // GitHub-style
        List<Map<String, Object>> commits = (List<Map<String, Object>>) payload.get("commits");
        if (commits != null) {
            for (Map<String, Object> commit : commits) {
                files.addAll((List<String>) commit.getOrDefault("added", Collections.emptyList()));
                files.addAll((List<String>) commit.getOrDefault("modified", Collections.emptyList()));
                files.addAll((List<String>) commit.getOrDefault("removed", Collections.emptyList()));
            }
        }
        log.info("[ConfigServerWebhookController :: extractChangedFiles ] :: files.size => {}", files.size());
        return files;
    }

    private void sendRefreshRequest(String url) {
        webClientBuilder.build()
                .post()
                .uri(url)
                .retrieve()
                .bodyToMono(String.class)
                .doOnSuccess(r -> System.out.println("Refreshed: " + url))
                .doOnError(e -> System.err.println("Error refreshing " + url + ": " + e.getMessage()))
                .subscribe();
    }

    private Set<String> extractMsaUrls(List<String> changedFiles) {
        Set<String> keys = new HashSet<>();

        Pattern pattern = Pattern.compile("javaServiceTreeFramework(\\w+?)(Core|Fire|Proxy|Hub|AI)?(?:-(dev|stg|live))?\\.yml"); //

        for (String file : changedFiles) {
            Matcher matcher = pattern.matcher(file);
            if (matcher.find()) {
                String rawKeyGroup1 = matcher.group(1).toLowerCase(); // e.g., "backend", "engine"
                String rawKeyGroup2 = matcher.group(2);               // e.g., "Core", "Fire", or null

                String rawKey = rawKeyGroup1;
                if (rawKeyGroup2 != null && !rawKeyGroup2.isEmpty()) {
                    rawKey += "-" + rawKeyGroup2.toLowerCase();
                }

                keys.add(rawKey);
            }
        }

        return keys;
    }

}
