import { world, system } from "@minecraft/server";
import { ModalFormData, ActionFormData, MessageFormData } from "@minecraft/server-ui";

///////////////////////////////////////PROTECAO DE AREA/////////////////

/* ================= CONFIG ================= */
const AREA_RADIUS = 30;
const BLOCO_PROTECAO = "well:estandarde_base";
const PARTICULA_AREA = "minecraft:endrod";
const PASSO_CIRCULO = 30;
const TEMPO_LIMPAR_CAMERA = 100;
const MODAL_COOLDOWN = 20;

/* ================= BASES ================= */
// key => { dono: string, membros: [], solicitacoes: [] }
const BASES = new Map();
const MODAL_ABERTA = new Set();

/* ================= PERSISTÊNCIA ================= */
function loadBases() {
    const data = world.getDynamicProperty("basesData");
    if (data) {
        const parsed = JSON.parse(data);
        BASES.clear();
        for (const [key, value] of parsed) {
            BASES.set(key, value);
        }
    }
}

function saveBases() {
    world.setDynamicProperty("basesData", JSON.stringify(Array.from(BASES.entries())));
}

// Carrega os dados no próximo tick, após a inicialização
system.run(() => {
    loadBases();
});

/* ================= UTIL ================= */
function baseKey(loc, dim) {
    return `${Math.floor(loc.x)}_${Math.floor(loc.y)}_${Math.floor(loc.z)}_${dim.id}`;
}

function distancia(a, b) {
    return Math.sqrt((a.x - b.x) ** 2 + (a.z - b.z) ** 2);
}

function podeMexer(player, center) {
    const base = BASES.get(baseKey(center, player.dimension));
    if (!base) return false;
    return base.membros.includes(player.name);
}

function avisar(player) {
    player.sendMessage("§c🚫 Esta área está protegida!");
}

/* ================= ACHAR BLOCO CENTRAL ================= */
function getCentroProtecao(loc, dimension) {
    const r = AREA_RADIUS;
    for (let x = -r; x <= r; x++) {
        for (let y = -10; y <= 10; y++) {
            for (let z = -r; z <= r; z++) {
                const pos = {
                    x: Math.floor(loc.x + x),
                    y: Math.floor(loc.y + y),
                    z: Math.floor(loc.z + z)
                };
                const block = dimension.getBlock(pos);
                if (!block) continue;
                if (
                    block.typeId === BLOCO_PROTECAO &&
                    distancia(block.location, loc) <= AREA_RADIUS
                ) {
                    return block.location;
                }
            }
        }
    }
    return null;
}

/* ================= EFEITOS + CAMERA ================= */
function efeitos(player, center) {
    const dim = player.dimension;
    for (let ang = 0; ang < 360; ang += PASSO_CIRCULO) {
        const rad = ang * Math.PI / 180;
        dim.spawnParticle(PARTICULA_AREA, {
            x: center.x + Math.cos(rad) * AREA_RADIUS + 0.5,
            y: center.y + 1,
            z: center.z + Math.sin(rad) * AREA_RADIUS + 0.5
        });
    }
    player.runCommand(`camera @s set well:free ease 1 linear pos ~ ~35 ~ rot 85 0`);
    player.runCommand(`titleraw @s actionbar {"rawtext":[{"text":"§c🚫 ÁREA PROTEGIDA"}]}`);
    player.runCommand(`playsound note.pling @s ~ ~ ~ 1 1`);
    system.runTimeout(() => {
        player.runCommand(`camera @s clear`);
    }, TEMPO_LIMPAR_CAMERA);
}

/* ================= REGISTRAR BASE ================= */
world.afterEvents.playerPlaceBlock.subscribe(ev => {
    const player = ev.player;
    const block = ev.block;
    if (!block || block.typeId !== BLOCO_PROTECAO) return;
    const key = baseKey(block.location, player.dimension);
    if (BASES.has(key)) {
        player.sendMessage("§c❌ Já existe uma base aqui.");
        return;
    }
    BASES.set(key, {
        dono: player.name,
        membros: [player.name],
        solicitacoes: []
    });
    saveBases(); // Salva após criar
    player.sendMessage("§a✔ Base criada. Você é o dono.");
});

/* ================= REMOVER BASE AO QUEBRAR BLOCO CENTRAL ================= */
world.afterEvents.playerBreakBlock.subscribe(ev => {
    const block = ev.brokenBlockPermutation;
    if (block.type.id !== BLOCO_PROTECAO) return;
    const key = baseKey(ev.block.location, ev.dimension);
    if (BASES.has(key)) {
        BASES.delete(key);
        saveBases(); // Salva após remover
        ev.player.sendMessage("§c❌ Base removida.");
    }
});

/* ================= MENU PRINCIPAL PARA DONO ================= */
async function abrirMenuDono(player, center) {
    if (MODAL_ABERTA.has(player.id)) return;
    MODAL_ABERTA.add(player.id);
    const base = BASES.get(baseKey(center, player.dimension));
    if (!base || base.dono !== player.name) {
        MODAL_ABERTA.delete(player.id);
        return;
    }
    let body = "Escolha uma opção:";
    if (base.solicitacoes.length > 0) {
        body += `\n\nSolicitações pendentes: ${base.solicitacoes.join(", ")}`;
    } else {
        body += "\n\nNenhuma solicitação pendente.";
    }
    const form = new ActionFormData()
        .title("§8Menu da Base")
        .body(body)
        .button("Listar Membros")
        .button("Gerenciar Membros")
        .button("Gerenciar Solicitações");
    const res = await form.show(player);
    system.runTimeout(() => {
        MODAL_ABERTA.delete(player.id);
    }, MODAL_COOLDOWN);
    if (res.canceled) return;
    if (res.selection === 0) {
        await listarMembros(player, center);
    } else if (res.selection === 1) {
        await abrirModalRemoverMembros(player, center);
    } else if (res.selection === 2) {
        await abrirMenuSolicitacoes(player, center);
    }
}

/* ================= LISTAR MEMBROS ================= */
async function listarMembros(player, center) {
    const base = BASES.get(baseKey(center, player.dimension));
    if (!base) return;
    let body = "Membros com acesso:";
    if (base.membros.length > 0) {
        body += `\n\n${base.membros.join("\n")}`;
    } else {
        body += "\n\nApenas o dono tem acesso.";
    }
    const form = new ActionFormData()
        .title("§8Lista de Membros")
        .body(body)
        .button("Voltar");
    const res = await form.show(player);
    if (res.canceled) return;
    // Voltar ao menu principal
    await abrirMenuDono(player, center);
}

/* ================= MODAL GERENCIAR MEMBROS ================= */
async function abrirModalMembros(player, center) {
    const base = BASES.get(baseKey(center, player.dimension));
    if (!base) return;
    const jogadores = world.getPlayers();
    const dropdown = [
        "Selecionar jogador",
        ...jogadores.map(p => p.name)
    ];
    const form = new ModalFormData()
        .title({ rawtext: [{ text: "§8Acesso da Base" }] })
        .dropdown(
            { rawtext: [{ text: "Jogadores online" }] },
            dropdown
        )
        .toggle(
            { rawtext: [{ text: "Permitir acesso ao jogador selecionado" }] },
            { defaultValue: true }
        );
    const res = await form.show(player);
    if (res.canceled) return;
    const index = res.formValues[0];
    const permitir = res.formValues[1];
    if (index === 0) {
        player.sendMessage("§cNenhum jogador selecionado.");
        return;
    }
    const alvo = jogadores[index - 1].name;
    if (permitir) {
        if (!base.membros.includes(alvo)) {
            base.membros.push(alvo);
            player.sendMessage(`§a✔ ${alvo} AGORA tem acesso.`);
        } else {
            player.sendMessage(`§e⚠ ${alvo} já tinha acesso.`);
        }
    } else {
        if (base.membros.includes(alvo) && alvo !== base.dono) {
            base.membros = base.membros.filter(n => n !== alvo);
            player.sendMessage(`§c✖ ${alvo} teve o acesso REMOVIDO.`);
        } else {
            player.sendMessage(`§e⚠ ${alvo} já não tinha acesso ou é o dono.`);
        }
    }
    saveBases();
    efeitos(player, center);
}

/* ================= MENU GERENCIAR SOLICITAÇÕES ================= */
async function abrirMenuSolicitacoes(player, center) {
    const base = BASES.get(baseKey(center, player.dimension));
    if (!base) return;
    if (base.solicitacoes.length === 0) {
        player.sendMessage("§e⚠ Não há solicitações pendentes.");
        return;
    }
    const form = new ActionFormData()
        .title("§8Solicitações de Acesso")
        .body("Selecione um jogador para aprovar ou negar:");
    base.solicitacoes.forEach(nome => {
        form.button(nome);
    });
    form.button("Voltar");
    const res = await form.show(player);
    if (res.canceled) return;
    const index = res.selection;
    const numSolic = base.solicitacoes.length;
    if (index === numSolic) {
        // Voltar
        await abrirMenuDono(player, center);
        return;
    }
    const nome = base.solicitacoes[index];
    await confirmarAcaoSolicitacao(player, center, nome);
}

/* ================= CONFIRMAR AÇÃO PARA SOLICITAÇÃO ================= */
async function confirmarAcaoSolicitacao(player, center, nome) {
    const base = BASES.get(baseKey(center, player.dimension));
    if (!base || !base.solicitacoes.includes(nome)) return;
    const form = new MessageFormData()
        .title(`Acesso para ${nome}`)
        .body(`Deseja aprovar o acesso de ${nome} à base?`)
        .button1("Sim (Aprovar)")
        .button2("Não (Negar)");
    const res = await form.show(player);
    if (res.canceled) {
        await abrirMenuSolicitacoes(player, center);
        return;
    }
    const index = base.solicitacoes.indexOf(nome);
    if (index !== -1) {
        base.solicitacoes.splice(index, 1);
    }
    if (res.selection === 0) { // Sim
        if (!base.membros.includes(nome)) {
            base.membros.push(nome);
            player.sendMessage(`§a✔ ${nome} aprovado e adicionado aos membros.`);
        } else {
            player.sendMessage(`§e⚠ ${nome} já era membro.`);
        }
    } else { // Não
        player.sendMessage(`§c✖ ${nome} negado.`);
    }
    saveBases();
    efeitos(player, center);
    // Reabrir o menu para mais ações
    await abrirMenuSolicitacoes(player, center);
}

/* ================= SOLICITAR ACESSO ================= */
async function solicitarAcesso(player, center) {
    if (MODAL_ABERTA.has(player.id)) return;
    MODAL_ABERTA.add(player.id);
    const base = BASES.get(baseKey(center, player.dimension));
    if (!base) {
        MODAL_ABERTA.delete(player.id);
        return;
    }
    if (base.membros.includes(player.name)) {
        player.sendMessage("§e⚠ Você já tem acesso.");
        MODAL_ABERTA.delete(player.id);
        return;
    }
    if (base.solicitacoes.includes(player.name)) {
        player.sendMessage("§e⚠ Você já solicitou acesso.");
        MODAL_ABERTA.delete(player.id);
        return;
    }
    const form = new MessageFormData()
        .title("Solicitação de Acesso")
        .body("Deseja solicitar acesso a esta base?")
        .button1("Sim")
        .button2("Não");
    const res = await form.show(player);
    system.runTimeout(() => {
        MODAL_ABERTA.delete(player.id);
    }, MODAL_COOLDOWN);
    if (res.canceled || res.selection === 1) return; // Não ou cancelado
    base.solicitacoes.push(player.name);
    saveBases();
    player.sendMessage("§a✔ Solicitação de acesso enviada ao dono.");
    efeitos(player, center);
}

/* ================= INTRUSÃO ================= */
function tratarIntrusao(player, loc) {
    const center = getCentroProtecao(loc, player.dimension);
    if (!center) return false;
    if (podeMexer(player, center)) return false;
    avisar(player);
    system.run(() => efeitos(player, center));
    return true;
}

/* ================= EVENTOS ================= */
world.beforeEvents.playerBreakBlock.subscribe(ev => {
    if (tratarIntrusao(ev.player, ev.block.location)) ev.cancel = true;
});

world.beforeEvents.playerPlaceBlock.subscribe(ev => {
    if (tratarIntrusao(ev.player, ev.block.location)) ev.cancel = true;
});

world.beforeEvents.playerInteractWithBlock.subscribe(ev => {
    const block = ev.block;
    if (!block) return;
    if (block.typeId === BLOCO_PROTECAO) {
        ev.cancel = true;
        const center = block.location;
        const base = BASES.get(baseKey(center, ev.player.dimension));
        if (base) {
            if (base.dono === ev.player.name) {
                system.run(() => abrirMenuDono(ev.player, center));
            } else {
                system.run(() => solicitarAcesso(ev.player, center));
            }
        }
        return;
    }
    if (tratarIntrusao(ev.player, block.location)) ev.cancel = true;
});

/* ================= MODAL REMOVER MEMBROS (INCLUINDO OFFLINE) ================= */
async function abrirModalRemoverMembros(player, center) {
    const base = BASES.get(baseKey(center, player.dimension));
    if (!base) return;

    // Remove o dono da lista para não aparecer na remoção
    const membrosRemoviveis = base.membros.filter(n => n !== base.dono);
    if (membrosRemoviveis.length === 0) {
        player.sendMessage("§e⚠ Não há membros para remover.");
        return;
    }

    const form = new ActionFormData()
        .title("§8Remover Membros da Base")
        .body("Selecione um membro para remover:");

    membrosRemoviveis.forEach(nome => form.button(nome));
    form.button("Voltar");

    const res = await form.show(player);
    if (res.canceled) return;

    const index = res.selection;
    if (index === membrosRemoviveis.length) {
        // Voltar
        await abrirMenuDono(player, center);
        return;
    }

    const alvo = membrosRemoviveis[index];
    base.membros = base.membros.filter(n => n !== alvo);
    saveBases();
    player.sendMessage(`§c✖ ${alvo} teve o acesso REMOVIDO.`);
    efeitos(player, center);

    // Reabrir o menu para mais ações
    await abrirModalRemoverMembros(player, center);
}



/* ================= WEAKNESS PARA SEM PERMISSÃO ================= */

const WEAKNESS_TICKS = 5;
const WEAKNESS_LEVEL = 60;

function aplicarWeakness(player) {
    try {
        player.runCommand(
            `effect @s weakness ${WEAKNESS_TICKS} ${WEAKNESS_LEVEL} true`
        );
    } catch {}
}

function removerWeakness(player) {
    try {
        player.runCommand(`effect @s clear weakness`);
    } catch {}
}

/* ================= LOOP DE VERIFICAÇÃO ================= */
system.runInterval(() => {
    for (const player of world.getPlayers()) {

        let dentroDeArea = false;
        let temPermissao = false;

        // verifica TODAS as bases
        for (const [key, base] of BASES.entries()) {
            const [x, y, z, dimId] = key.split("_");
            if (player.dimension.id !== dimId) continue;

            const center = {
                x: Number(x),
                y: Number(y),
                z: Number(z)
            };

            if (distancia(player.location, center) <= AREA_RADIUS) {
                dentroDeArea = true;

                if (base.membros.includes(player.name)) {
                    temPermissao = true;
                }
                break;
            }
        }

        // lógica final
        if (dentroDeArea && !temPermissao) {
            aplicarWeakness(player);
        } else {
            removerWeakness(player);
        }
    }
}, 40); // a cada 2 segundos (leve)

