import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.requests.GatewayIntent;
import org.jetbrains.annotations.NotNull;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DiscordDownloadBot extends ListenerAdapter {

    // 🔴 [필수] 여기에 디스코드 봇 토큰을 붙여넣으세요
    private static final String BOT_TOKEN = "MTQ0Nzg1NjI1NTY4NjE0ODEzOA.GpvmOr.KRTrSGh1GrmlF_oHY1brKZbAXb3erfHBlPXHEI";

    // yt-dlp.exe 경로 (프로젝트 최상위 폴더 기준)
    private static final String YTDLP_PATH = System.getProperty("user.dir") + File.separator + "yt-dlp.exe";

    // 저장할 폴더 (프로젝트 폴더 아래 'Downloads')
    private static final String DOWNLOAD_DIR = System.getProperty("user.dir") + File.separator + "Downloads";

    // 동시에 3개까지만 다운로드 처리 (서버 부하 방지)
    private final ExecutorService executor = Executors.newFixedThreadPool(3);

    public static void main(String[] args) {
        // 1. 필수 파일 확인
        if (!new File(YTDLP_PATH).exists()) {
            System.err.println("❌ 오류: yt-dlp.exe 파일을 프로젝트 폴더(pom.xml 옆)에 넣어주세요!");
            return;
        }

        File folder = new File(DOWNLOAD_DIR);
        if (!folder.exists()) {
            boolean success = folder.mkdirs(); // 폴더가 없으면 생성
            if (success) {
                System.out.println("✅ 다운로드 폴더를 새로 만들었습니다: " + DOWNLOAD_DIR);
            } else {
                System.out.println("⚠️ 폴더 생성 실패! 권한을 확인하세요.");
            }
        }

        // 2. 봇 실행
        try {
            JDABuilder.createDefault(BOT_TOKEN)
                    .enableIntents(GatewayIntent.MESSAGE_CONTENT) // 메시지 내용 읽기 권한
                    .addEventListeners(new DiscordDownloadBot())
                    .build();
            System.out.println("🤖 봇 실행 완료! 유튜브/인스타 링크를 감지합니다.");
            System.out.println("📂 저장 경로: " + DOWNLOAD_DIR);
        } catch (Exception e) {
            System.err.println("❌ 봇 실행 실패: 토큰이 올바른지 확인하세요.");
            e.printStackTrace();
        }
    }

    @Override
    public void onMessageReceived(@NotNull MessageReceivedEvent event) {
        // 1. 봇 자신의 메시지는 무시
        if (event.getAuthor().isBot()) return;

        // 2. 메시지 내용 가져오기
        String message = event.getMessage().getContentRaw();
        System.out.println("👂 감지된 메시지: " + message);

        // 3. URL 추출 (작성하신 extractUrl 함수 사용)
        String foundUrl = extractUrl(message);

        // 4. 유효한 링크가 발견되면 다운로드 시작
        if (foundUrl != null) {
            System.out.println("✅ 다운로드 대상 링크 발견: " + foundUrl);
            event.getChannel().sendMessage("📥 영상을 감지했습니다! 다운로드를 시도합니다... (" + foundUrl + ")").queue();

            // 5. [핵심] 별도 스레드에서 다운로드 실행 (봇 멈춤 방지)
            executor.submit(() -> {
                processDownload(foundUrl, event);
            });
        }
    }

    // 유튜브, 인스타, 틱톡 등의 URL만 쏙 뽑아내는 함수
    private String extractUrl(String text) {
        // http 또는 https로 시작하는 주소 패턴
        String regex = "(https?://\\S+)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(text);

        if (matcher.find()) {
            String foundUrl = matcher.group(1);
            // 유튜브, 인스타, 틱톡 주소인지 한번 더 체크 (원하면 이 부분 삭제해서 모든 링크 허용 가능)
            if (foundUrl.contains("youtube.com") || foundUrl.contains("youtu.be") ||
                    foundUrl.contains("instagram.com") || foundUrl.contains("tiktok.com")) {
                return foundUrl;
            }
        }
        return null;
    }

    private void processDownload(String url, MessageReceivedEvent event) {
        // 진행 상황을 표시할 메시지 객체
        net.dv8tion.jda.api.entities.Message progressMessage = null;

        try {
            // 1. 처음에 "다운로드 시작" 메시지를 보내고, 그 메시지 객체를 가져옵니다.
            progressMessage = event.getChannel().sendMessage("⏳ **다운로드 준비 중...**").complete();

            File dir = new File(DOWNLOAD_DIR);
            if (!dir.exists()) dir.mkdirs();

            String outputPath = DOWNLOAD_DIR + File.separator + "%(title)s.%(ext)s";

            // 2. 명령어 설정 (--newline 옵션 추가가 핵심!)
            String[] command = {
                    YTDLP_PATH,
                    "--newline",      // 👈 [중요] 진행률을 한 줄씩 출력하게 함
                    "--no-warnings",
                    "-f", "bestvideo+bestaudio/best",
                    "--merge-output-format", "mp4",
                    "-o", outputPath,
                    url
            };

            ProcessBuilder pb = new ProcessBuilder(command);
            pb.redirectErrorStream(true); // 에러도 같이 읽음
            Process process = pb.start();

            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;

            // 시간 체크용 변수 (너무 잦은 업데이트 방지)
            long lastUpdateTime = 0;

            // 3. yt-dlp의 출력을 한 줄씩 읽음
            while ((line = reader.readLine()) != null) {
                System.out.println("[yt-dlp] " + line); // 콘솔에도 출력

                // "[download] 25.4%" 같은 패턴을 찾음
                if (line.contains("[download]") && line.contains("%")) {
                    long currentTime = System.currentTimeMillis();

                    // 3초(3000ms)가 지났을 때만 디스코드 메시지 수정
                    if (currentTime - lastUpdateTime > 3000) {
                        // 정규식으로 숫자만 쏙 뽑기 (예: 25.4%)
                        Matcher matcher = Pattern.compile("(\\d+\\.\\d+%)").matcher(line);
                        if (matcher.find()) {
                            String percent = matcher.group(1);
                            progressMessage.editMessage("📥 **다운로드 중...** " + percent).queue();
                            lastUpdateTime = currentTime;
                        }
                    }
                }
            }

            int exitCode = process.waitFor();

            // 4. 완료 시 메시지 수정
            if (exitCode == 0) {
                progressMessage.editMessage("✅ **다운로드 완료!**\n(파일은 서버 컴퓨터의 `Downloads` 폴더에 저장되었습니다.)").queue();
            } else {
                progressMessage.editMessage("❌ **다운로드 실패.** 콘솔 로그를 확인하세요.").queue();
            }

        } catch (Exception e) {
            e.printStackTrace();
            if (progressMessage != null) {
                progressMessage.editMessage("🔥 **오류 발생:** " + e.getMessage()).queue();
            }
        }
    }
}