import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import io.github.jwdeveloper.tiktok.TikTokLiveClient;
import io.github.jwdeveloper.tiktok.TikTokLiveClientBuilder;
import io.github.jwdeveloper.tiktok.TikTokLiveEventHandler;
import io.github.jwdeveloper.tiktok.models.ConnectionState;

public class Main {
    public static void main(String[] args) {
        // Check for config.yml
        File configFile = new File("config.yml");
        if (!configFile.exists()) {
            System.out.println("No config.yml found. Starting first-time setup...");
            firstTimeSetup();
        }

        // Ensure format.yml exists by generating a default if missing
        File formatFile = new File("format.yml");
        if (!formatFile.exists()) {
            String defaultFormat = "events:\n" +
                    "  follow:\n" +
                    "    file_format:\n" +
                    "      text: $userinfo followed\n" +
                    "    cli_format:\n" +
                    "      text: $date | $time | $userinfo | Follow\n" +
                    "  likes:\n" +
                    "    file_format:\n" +
                    "      text: $userinfo liked $amount\n" +
                    "    cli_format:\n" +
                    "      text: $date | $time | $userinfo | Likes x$amount\n" +
                    "  shares:\n" +
                    "    file_format:\n" +
                    "      text: $userinfo Shared\n" +
                    "    cli_format:\n" +
                    "      text: $date | $time | $userinfo | Shared\n" +
                    "  gifts:\n" +
                    "    file_format:\n" +
                    "      text: $userinfo sent x$amount $gift_name\n" +
                    "    cli_format:\n" +
                    "      text: $date | $time | $userinfo | x$amount $gift_name\n" +
                    "  chat:\n" +
                    "    file_format:\n" +
                    "      text: $userinfo > $msg\n" +
                    "    cli_format:\n" +
                    "      text: $date | $time | $userinfo | Message > $msg\n";
            try {
                Files.writeString(formatFile.toPath(), defaultFormat);
                System.out.println("format.yml created with default values.");
            } catch (IOException e) {
                System.err.println("Failed to create format.yml: " + e.getMessage());
            }
        }

        // Load config and format
        try {
            var config = ConfigLoader.loadConfig("config.yml");
            var format = FormatLoader.loadFormat("format.yml");

            int port = (int) config.getOrDefault("websocket_port", 3000);
            WebSocketServerApp wsServer = new WebSocketServerApp(port);
            wsServer.start();
            System.out.println("WebSocket server running on port " + port);

            TikTokEventListener tiktokListener = new TikTokEventListener(config, format, wsServer);


            // --- TikTokLiveJava Integration ---
            String username = (String) config.getOrDefault("TIKTOK_USERNAME", "");
            if (username.startsWith("@")) {
                username = username.substring(1);
            }
            try {
                TikTokLiveClient client = new TikTokLiveClientBuilder()
                        .setUniqueId(username)
                        .build();


                // Helper to extract user info based on config user_style
                java.util.function.Function<Object, String> getUserInfo = (event) -> {
                    try {
                        Object user = event.getClass().getMethod("getUser").invoke(event);
                        String userStyle = "username";
                        try {
                            Object eventsCfg = config.get("events");
                            if (eventsCfg instanceof java.util.Map) {
                                java.util.Map<?,?> eventsMap = (java.util.Map<?,?>) eventsCfg;
                                Object followCfg = eventsMap.get("follow");
                                if (followCfg instanceof java.util.Map) {
                                    Object style = ((java.util.Map<?,?>) followCfg).get("ws_enable");
                                    if (style instanceof java.util.Map) {
                                        Object us = ((java.util.Map<?,?>) style).get("user_style");
                                        if (us instanceof String) userStyle = (String) us;
                                    }
                                }
                            }
                        } catch (Exception ignore) {}
                        if (userStyle.equalsIgnoreCase("display_name")) {
                            return (String) user.getClass().getMethod("getDisplayName").invoke(user);
                        } else {
                            return (String) user.getClass().getMethod("getUsername").invoke(user);
                        }
                    } catch (Exception e) {
                        return "[unknown user]";
                    }
                };

                client.addEventHandler(new TikTokLiveEventHandler() {
                    @Override
                    public void onFollow(Object event) {
                        tiktokListener.onFollow(getUserInfo.apply(event));
                    }
                    @Override
                    public void onLike(Object event) {
                        try {
                            int count = (int) event.getClass().getMethod("getLikeCount").invoke(event);
                            tiktokListener.onLike(getUserInfo.apply(event), count);
                        } catch (Exception e) {
                            tiktokListener.onLike(getUserInfo.apply(event), 1);
                        }
                    }
                    @Override
                    public void onShare(Object event) {
                        tiktokListener.onShare(getUserInfo.apply(event));
                    }
                    @Override
                    public void onGift(Object event) {
                        try {
                            Object user = event.getClass().getMethod("getUser").invoke(event);
                            Object gift = event.getClass().getMethod("getGift").invoke(event);
                            String userInfo = getUserInfo.apply(event);
                            String giftName = (String) gift.getClass().getMethod("getName").invoke(gift);
                            int amount = (int) event.getClass().getMethod("getGiftCount").invoke(event);
                            tiktokListener.onGift(userInfo, giftName, amount);
                        } catch (Exception e) {
                            tiktokListener.onGift(getUserInfo.apply(event), "Gift", 1);
                        }
                    }
                    @Override
                    public void onComment(Object event) {
                        try {
                            String msg = (String) event.getClass().getMethod("getComment").invoke(event);
                            tiktokListener.onChat(getUserInfo.apply(event), msg);
                        } catch (Exception e) {
                            tiktokListener.onChat(getUserInfo.apply(event), "");
                        }
                    }
                });

                client.connect();

                // Optionally, wait for connection state
                while (client.getConnectionState() != ConnectionState.CONNECTED) {
                    Thread.sleep(500);
                }
                System.out.println("Connected to TikTok live for user: @" + username);
            } catch (Exception e) {
                System.err.println("Failed to connect to TikTok Live: " + e.getMessage());
            }
            // --- End TikTokLiveJava Integration ---

        } catch (Exception e) {
            System.err.println("Failed to load config or start server: " + e.getMessage());
        }
    }

    private static void firstTimeSetup() {
        try (Scanner scanner = new Scanner(System.in)) {
            String username;
            do {
                System.out.print("Enter the TikTok username to follow (include @): ");
                username = scanner.nextLine();
            } while (!username.startsWith("@"));

            System.out.print("Enter websocket port (default 3000): ");
            String portInput = scanner.nextLine();
            int port = 3000;
            if (!portInput.isBlank()) {
                try {
                    port = Integer.parseInt(portInput);
                } catch (NumberFormatException e) {
                    System.out.println("Invalid port. Using default 3000.");
                }
            }

            // Write full config.yml with all event settings (valid YAML)
                            String config = "# tiktok username to follow\n" +
                                "TIKTOK_USERNAME: '" + username + "'\n" +
                                "\n" +
                                "websocket_port: " + port + " # Requires program restart to take effect\n" +
                                "\n" +
                                "events:\n" +
                                "  follow:\n" +
                                "    enabled: true\n" +
                                "    ws_enable:\n" +
                                "      enabled: true\n" +
                                "      profile_img: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "    file_enable:\n" +
                                "      enabled: true\n" +
                                "      profile_img: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "      output_path: 'C:/Users/Tiktok/Follows'\n" +
                                "    cli_enable:\n" +
                                "      enabled: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "  likes:\n" +
                                "    enabled: true\n" +
                                "    ws_enable:\n" +
                                "      enabled: true\n" +
                                "      profile_img: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "      amount: true\n" +
                                "    file_enable:\n" +
                                "      enabled: true\n" +
                                "      profile_img: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "      amount: true\n" +
                                "      output_path: 'C:/Users/Tiktok/Likes'\n" +
                                "    cli_enable:\n" +
                                "      enabled: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "      amount: true\n" +
                                "  shares:\n" +
                                "    enabled: true\n" +
                                "    ws_enable:\n" +
                                "      enabled: true\n" +
                                "      profile_img: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "    file_enable:\n" +
                                "      enabled: true\n" +
                                "      profile_img: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "      output_path: 'C:/Users/Tiktok/Shares'\n" +
                                "    cli_enable:\n" +
                                "      enabled: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "    follower_only_share: true\n" +
                                "  gifts:\n" +
                                "    enabled: true\n" +
                                "    ws_enable:\n" +
                                "      enabled: true\n" +
                                "      profile_img: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "      gift_name: true\n" +
                                "      amount: true\n" +
                                "    file_enable:\n" +
                                "      enabled: true\n" +
                                "      profile_img: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "      gift_name: true\n" +
                                "      amount: true\n" +
                                "      output_path: 'C:/Users/Tiktok/Gifts'\n" +
                                "    cli_enable:\n" +
                                "      enabled: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "      gift_name: true\n" +
                                "      amount: true\n" +
                                "  chat:\n" +
                                "    enabled: true\n" +
                                "    ws_enable:\n" +
                                "      enabled: true\n" +
                                "      profile_img: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n" +
                                "    file_enable:\n" +
                                "      enabled: false\n" +
                                "      profile_img: false\n" +
                                "      userinfo: false\n" +
                                "      user_style: username\n" +
                                "      output_path: 'C:/Users/Tiktok/Chat'\n" +
                                "    cli_enable:\n" +
                                "      enabled: true\n" +
                                "      userinfo: true\n" +
                                "      user_style: username\n";
            try {
                Files.writeString(Paths.get("config.yml"), config);
                System.out.println("config.yml created with all event settings. Please edit it for more options as needed.");
            } catch (IOException e) {
                System.err.println("Failed to write config.yml: " + e.getMessage());
            }
        }
    }
}
