// app.js - 普通脚本（非模块）

const { createApp, ref, reactive, computed, onMounted } = Vue;

// ============================================================
// 1. 基础 API
// ============================================================
const API_BASE = "/api";

function getToken() {
    return localStorage.getItem("frpc_token") || "";
}

function getHeaders() {
    return {
        "Content-Type": "application/json",
        Authorization: "Bearer " + getToken(),
    };
}

async function apiFetch(endpoint, options = {}) {
    const url = API_BASE + endpoint;
    const headers =
        options.body instanceof FormData
            ? { Authorization: "Bearer " + getToken() }
            : getHeaders();
    const res = await fetch(url, {
        ...options,
        headers: { ...headers, ...(options.headers || {}) },
    });
    return res.json();
}

// ============================================================
// 2. Auth
// ============================================================
function parseJwtExpire(token) {
    try {
        const payload = JSON.parse(atob(token.split(".")[1]));
        return payload.exp * 1000;
    } catch {
        return Date.now() + 7 * 24 * 60 * 60 * 1000;
    }
}

function saveAuthState(token, username) {
    const expire = parseJwtExpire(token);
    localStorage.setItem("frpc_token", token);
    localStorage.setItem("frpc_token_expire", String(expire));
    localStorage.setItem("frpc_username", username);
    return expire;
}

function loadAuthState() {
    const token = localStorage.getItem("frpc_token");
    const expire = parseInt(localStorage.getItem("frpc_token_expire") || "0", 10);
    const username = localStorage.getItem("frpc_username") || "";
    if (token && expire > Date.now()) {
        return { token, expire, username, valid: true };
    }
    clearAuthState();
    return { token: "", expire: 0, username: "", valid: false };
}

function clearAuthState() {
    localStorage.removeItem("frpc_token");
    localStorage.removeItem("frpc_token_expire");
    localStorage.removeItem("frpc_username");
}

async function login(username, password) {
    const data = await apiFetch("/login", {
        method: "POST",
        body: JSON.stringify({ username, password }),
    });
    if (data.code === 0) {
        const token = data.data.token;
        const expire = saveAuthState(token, username);
        return { success: true, token, expire };
    }
    return { success: false, error: data.msg || "登录失败" };
}

// ============================================================
// 3. Config
// ============================================================
const defaultConfig = {
    serverAddr: "frp.whitetop.xyz",
    serverPort: 9358,
    token: "",
    logLevel: "info",
    logMaxDays: 3,
    tcpMux: true,
    tcpMuxKeepalive: 30,
    heartbeatInterval: 15,
    heartbeatTimeout: 70,
    poolCount: 8,
};

async function loadConfig() {
    try {
        const data = await apiFetch("/config");
        if (data.code === 0) {
            return { ...defaultConfig, ...data.data };
        }
    } catch (e) {
        console.warn("加载配置失败", e);
    }
    return { ...defaultConfig };
}

async function saveConfigApi(config) {
    const data = await apiFetch("/config", {
        method: "PUT",
        body: JSON.stringify(config),
    });
    return data;
}

// ============================================================
// 4. Proxies
// ============================================================
async function loadProxies() {
    try {
        const data = await apiFetch("/proxies");
        if (data.code === 0) {
            return data.data || [];
        }
    } catch (e) {
        console.warn("加载隧道失败", e);
    }
    return [];
}

async function createProxy(proxy) {
    const data = await apiFetch("/proxy", {
        method: "POST",
        body: JSON.stringify(proxy),
    });
    return data;
}

async function updateProxy(proxy) {
    const data = await apiFetch("/proxy/" + proxy.id, {
        method: "PUT",
        body: JSON.stringify(proxy),
    });
    return data;
}

async function deleteProxy(id) {
    const data = await apiFetch("/proxy/" + id, {
        method: "DELETE",
    });
    return data;
}

function filterProxies(list, keyword) {
    if (!keyword) return list;
    const kw = keyword.toLowerCase();
    return list.filter(
        (p) =>
            p.name.toLowerCase().includes(kw) ||
            p.localIP.includes(kw) ||
            String(p.remotePort).includes(kw)
    );
}

// ============================================================
// 5. Frpc
// ============================================================
async function getFrpcStatus() {
    try {
        const data = await apiFetch("/frpc/status");
        if (data.code === 0) {
            return data.data.running || false;
        }
    } catch (e) {
        console.warn("获取 frpc 状态失败", e);
    }
    return false;
}

// ============================================================
// 6. UI State
// ============================================================
const activeTab = ref("proxies");
const dialogVisible = ref(false);
const dialogMode = ref("add");
const dialogForm = ref({
    id: null,
    name: "",
    type: "tcp",
    localIP: "",
    localPort: 0,
    remotePort: 0,
});
const searchKeyword = ref("");

function openAddDialog() {
    dialogMode.value = "add";
    dialogForm.value = {
        id: null,
        name: "",
        type: "tcp",
        localIP: "",
        localPort: 0,
        remotePort: 0,
    };
    dialogVisible.value = true;
}

function openEditDialog(proxy) {
    dialogMode.value = "edit";
    dialogForm.value = { ...proxy };
    dialogVisible.value = true;
}

function closeDialog() {
    dialogVisible.value = false;
}

// ============================================================
// 7. Vue App
// ============================================================
const app = createApp({
    setup() {
        // ---- 登录态 ----
        const loggedIn = ref(false);
        const loading = ref(false);
        const loginError = ref("");
        const loginForm = reactive({ username: "", password: "" });
        const token = ref("");
        const tokenExpireTime = ref(0);
        const transitioning = ref(false);
        const contentVisible = ref(false);
        let expireTimer = null;

        // ---- 注册 ----
        const isFirstRun = ref(false);
        const registerForm = reactive({
            username: "",
            password: "",
            confirmPassword: "",
        });
        const registerError = ref("");
        const registering = ref(false);

        // ---- 数据 ----
        const globalConfig = reactive({});
        const proxies = ref([]);
        const frpcRunning = ref(false);
        const showDetail = ref(false);

        // ---- 修改密码 ----
        const passwordChange = reactive({
            oldPassword: "",
            newPassword: "",
            confirmPassword: "",
        });
        const passwordChangeError = ref("");
        const passwordChangeSuccess = ref("");

        // ---- 初始化 ----
        onMounted(() => {
            const saved = loadAuthState();
            if (saved.valid) {
                token.value = saved.token;
                tokenExpireTime.value = saved.expire;
                loginForm.username = saved.username;
                loggedIn.value = true;
                loadAllData().then(() => {
                    contentVisible.value = true;
                    startExpireTimer();
                });
            } else {
                checkUsers();
            }
        });

        async function checkUsers() {
            try {
                const res = await fetch("/api/check/users");
                const data = await res.json();
                if (data.code === 0) {
                    isFirstRun.value = !data.data.hasUsers;
                }
            } catch (e) {
                console.warn("检查用户状态失败", e);
            }
        }

        function startExpireTimer() {
            if (expireTimer) clearInterval(expireTimer);
            expireTimer = setInterval(() => {
                if (Date.now() >= tokenExpireTime.value) {
                    doLogout();
                    alert("登录已超时，请重新登录");
                }
            }, 5000);
        }

        async function loadAllData() {
            const [cfg, list, running] = await Promise.all([
                loadConfig(),
                loadProxies(),
                getFrpcStatus(),
            ]);
            Object.assign(globalConfig, cfg);
            proxies.value = list;
            frpcRunning.value = running;
        }

        // ---- 登录 ----
        const doLogin = async () => {
            if (!loginForm.username || !loginForm.password) {
                loginError.value = "请输入用户名和密码";
                return;
            }
            loading.value = true;
            loginError.value = "";
            const result = await login(loginForm.username, loginForm.password);
            if (result.success) {
                token.value = result.token;
                tokenExpireTime.value = result.expire;
                transitioning.value = true;
                loggedIn.value = true;
                setTimeout(async () => {
                    transitioning.value = false;
                    await loadAllData();
                    loading.value = false;
                    setTimeout(() => {
                        contentVisible.value = true;
                        startExpireTimer();
                    }, 300);
                }, 500);
            } else {
                loginError.value = result.error;
                loading.value = false;
            }
        };

        // ---- 注册 ----
        const doRegister = async () => {
            if (registerForm.username.length < 5) {
                registerError.value = "用户名至少 5 位";
                return;
            }
            if (registerForm.password !== registerForm.confirmPassword) {
                registerError.value = "两次输入的密码不一致";
                return;
            }
            if (registerForm.password.length < 8) {
                registerError.value = "密码至少 8 位";
                return;
            }
            registering.value = true;
            registerError.value = "";
            try {
                const res = await fetch("/api/register", {
                    method: "POST",
                    headers: { "Content-Type": "application/json" },
                    body: JSON.stringify({
                        username: registerForm.username,
                        password: registerForm.password,
                    }),
                });
                const data = await res.json();
                if (data.code === 0) {
                    // ✅ 注册成功，不再是首次启动
                    isFirstRun.value = false;

                    const token = data.data.token;
                    const expire = saveAuthState(token, registerForm.username);
                    token.value = token;
                    tokenExpireTime.value = expire;
                    loginForm.username = registerForm.username;
                    loggedIn.value = true;
                    transitioning.value = true;
                    setTimeout(async () => {
                        transitioning.value = false;
                        await loadAllData();
                        setTimeout(() => {
                            contentVisible.value = true;
                            startExpireTimer();
                        }, 300);
                    }, 500);
                } else {
                    registerError.value = data.msg || "注册失败";
                }
            } catch (e) {
                registerError.value = "网络错误，请重试";
            }
            registering.value = false;
        };

        // ---- 退出 ----
        const doLogout = () => {
            if (expireTimer) clearInterval(expireTimer);
            contentVisible.value = false;
            loggedIn.value = false;
            token.value = "";
            tokenExpireTime.value = 0;
            loginForm.username = "";
            loginForm.password = "";
            loading.value = false;
            transitioning.value = false;
            clearAuthState();

            // ✅ 重置注册相关状态
            isFirstRun.value = false;
            registerForm.username = "";
            registerForm.password = "";
            registerForm.confirmPassword = "";
            registerError.value = "";
            registering.value = false;
        };

        // ---- 修改密码 ----
        const changePassword = async () => {
            passwordChangeError.value = "";
            passwordChangeSuccess.value = "";
            if (passwordChange.newPassword !== passwordChange.confirmPassword) {
                passwordChangeError.value = "两次输入的密码不一致";
                return;
            }
            if (passwordChange.newPassword.length < 8) {
                passwordChangeError.value = "密码至少 8 位";
                return;
            }
            try {
                const res = await fetch("/api/user/password", {
                    method: "PUT",
                    headers: getHeaders(),
                    body: JSON.stringify({
                        oldPassword: passwordChange.oldPassword,
                        newPassword: passwordChange.newPassword,
                    }),
                });
                const data = await res.json();
                if (data.code === 0) {
                    passwordChangeSuccess.value = "密码修改成功！";
                    passwordChange.oldPassword = "";
                    passwordChange.newPassword = "";
                    passwordChange.confirmPassword = "";
                } else {
                    passwordChangeError.value = data.msg || "修改失败";
                }
            } catch (e) {
                passwordChangeError.value = "网络错误，请重试";
            }
        };

        // ---- 保存配置 ----
        const saveConfig = async () => {
            const result = await saveConfigApi(globalConfig);
            if (result.code === 0) {
                frpcRunning.value = await getFrpcStatus();
                alert("配置已更新并热加载");
            } else {
                alert("保存失败: " + result.msg);
            }
        };

        // ---- 隧道操作 ----
        const toggleProxy = async (p) => {
            const result = await updateProxy(p);
            if (result.code !== 0) {
                alert("更新失败: " + result.msg);
                proxies.value = await loadProxies();
            } else {
                frpcRunning.value = await getFrpcStatus();
            }
        };

        const removeProxy = async (id) => {
            if (!confirm("确定要删除这条隧道吗？")) return;
            const result = await deleteProxy(id);
            if (result.code === 0) {
                proxies.value = await loadProxies();
                frpcRunning.value = await getFrpcStatus();
            } else {
                alert("删除失败: " + result.msg);
            }
        };

        const confirmDialog = async () => {
            const form = dialogForm.value;
            if (!form.name || !form.localIP || !form.localPort || !form.remotePort) {
                alert("请填写完整信息");
                return;
            }
            const result =
                dialogMode.value === "add"
                    ? await createProxy(form)
                    : await updateProxy(form);
            if (result.code === 0) {
                closeDialog();
                proxies.value = await loadProxies();
                frpcRunning.value = await getFrpcStatus();
            } else {
                alert("操作失败: " + result.msg);
            }
        };

        // ---- 导入导出（已移入 setup，可访问 loadAllData） ----
        const triggerImport = () => {
            document.getElementById("tomlFileInput").click();
        };

        const handleImport = async (e) => {
            const file = e.target.files[0];
            if (!file) return;
            const formData = new FormData();
            formData.append("file", file);
            try {
                const res = await fetch("/api/import/toml", {
                    method: "POST",
                    headers: { Authorization: "Bearer " + getToken() },
                    body: formData,
                });
                const data = await res.json();
                if (data.code === 0) {
                    alert(data.msg);
                    await loadAllData();
                } else {
                    alert("导入失败: " + data.msg);
                }
            } catch (err) {
                alert("网络错误: " + err.message);
            }
            e.target.value = "";
        };

        const exportToml = async () => {
            try {
                const res = await fetch("/api/export/toml", {
                    method: "GET",
                    headers: { Authorization: "Bearer " + getToken() },
                });
                if (!res.ok) {
                    const data = await res.json();
                    alert("导出失败: " + (data.msg || "未知错误"));
                    return;
                }
                const blob = await res.blob();
                const a = document.createElement("a");
                a.href = URL.createObjectURL(blob);
                a.download = "frpc.toml";
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(a.href);
            } catch (e) {
                alert("导出失败: " + e.message);
            }
        };

        // ---- 计算属性 ----
        const filteredProxies = computed(() =>
            filterProxies(proxies.value, searchKeyword.value)
        );

        // ---- 返回 ----
        return {
            loggedIn,
            loading,
            loginError,
            loginForm,
            doLogin,
            doLogout,

            isFirstRun,
            registerForm,
            registerError,
            registering,
            doRegister,

            activeTab,
            globalConfig,
            showDetail,
            saveConfig,

            proxies,
            filteredProxies,
            toggleProxy,
            removeProxy,
            frpcRunning,

            dialogVisible,
            dialogMode,
            dialogForm,
            openAddDialog,
            openEditDialog,
            closeDialog,
            confirmDialog,

            searchKeyword,
            transitioning,
            contentVisible,

            triggerImport,
            handleImport,
            exportToml,

            passwordChange,
            passwordChangeError,
            passwordChangeSuccess,
            changePassword,
        };
    },
});

app.mount("#app");