package ru.serega6531.packmate.security;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.nio.charset.StandardCharsets;

@Slf4j
@Component
public class FakeAdminResponder {

    private final ObjectMapper mapper = new ObjectMapper();
    private final List<String> encodedImages;

    public FakeAdminResponder() {
        this.encodedImages = loadImages();
    }

    private List<String> loadImages() {
        try {
            Resource[] resources = new PathMatchingResourcePatternResolver()
                    .getResources("classpath:/static/fake/images/*");

            List<String> images = Arrays.stream(resources)
                    .map(resource -> {
                        try {
                            String contentType = URLConnection.guessContentTypeFromName(resource.getFilename());
                            if (contentType == null) {
                                contentType = "image/jpeg";
                            }
                            byte[] raw = StreamUtils.copyToByteArray(resource.getInputStream());
                            return "data:%s;base64,%s".formatted(
                                    contentType,
                                    Base64.getEncoder().encodeToString(raw));
                        } catch (IOException e) {
                            log.warn("Failed to load fake admin image {}", resource.getFilename(), e);
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .toList();

            if (images.isEmpty()) {
                log.warn("No images found for fake admin fun mode");
            }

            return images;
        } catch (IOException e) {
            log.warn("Failed to load fake admin images", e);
            return Collections.emptyList();
        }
    }

    public String funPageHtml() {
        String phrasesJson = toJson(getFunPhrases());
        String imagesJson = toJson(encodedImages);
        String phrasesB64 = Base64.getEncoder().encodeToString(phrasesJson.getBytes(StandardCharsets.UTF_8));
        String imagesB64 = Base64.getEncoder().encodeToString(imagesJson.getBytes(StandardCharsets.UTF_8));
        String template = """
                <!doctype html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <title>0xb00b5 team Packmate // fake funwall</title>
                    <style>
                        @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=JetBrains+Mono:wght@500&display=swap');
                        :root {
                            --bg: #050512;
                            --accent: #59f3ff;
                            --accent-2: #ff5fd2;
                            --glass: rgba(9, 19, 45, 0.75);
                            --grid: rgba(89, 243, 255, 0.25);
                        }
                        * { box-sizing: border-box; }
                        body {
                            margin: 0;
                            padding: 0;
                            min-height: 100vh;
                            background: radial-gradient(circle at 20% 20%, rgba(255, 95, 210, 0.18), transparent 25%), radial-gradient(circle at 80% 0%, rgba(89, 243, 255, 0.2), transparent 30%), linear-gradient(135deg, #04040d 0%, #0a1024 45%, #050512 100%);
                            color: #e9f7ff;
                            font-family: 'Press Start 2P', 'JetBrains Mono', monospace;
                            display: flex;
                            align-items: center;
                            justify-content: center;
                            padding: 40px 18px 60px;
                            overflow: hidden;
                        }
                        .grid-bg {
                            position: fixed;
                            inset: 0;
                            background-image: linear-gradient(var(--grid) 1px, transparent 1px), linear-gradient(90deg, var(--grid) 1px, transparent 1px);
                            background-size: 80px 80px;
                            mask-image: radial-gradient(circle at 50% 20%, rgba(0,0,0,.8), transparent 75%);
                            opacity: 0.5;
                            z-index: 0;
                        }
                        .shell {
                            position: relative;
                            z-index: 1;
                            width: min(90vw, 1180px);
                            background: var(--glass);
                            border: 1px solid rgba(89, 243, 255, 0.4);
                            box-shadow: 0 0 40px rgba(89, 243, 255, 0.25), 0 0 24px rgba(255, 95, 210, 0.2);
                            border-radius: 18px;
                            padding: 32px;
                            backdrop-filter: blur(10px);
                        }
                        .shell::after {
                            content: '';
                            position: absolute;
                            inset: 12px;
                            border: 1px dashed rgba(255, 95, 210, 0.25);
                            border-radius: 14px;
                            pointer-events: none;
                        }
                        h1 {
                            margin: 0 0 20px;
                            font-size: 18px;
                            letter-spacing: 1.5px;
                            text-shadow: 0 0 8px rgba(89, 243, 255, 0.8);
                        }
                        .badge {
                            display: inline-block;
                            padding: 8px 14px;
                            border-radius: 10px;
                            border: 1px solid rgba(255, 95, 210, 0.35);
                            color: #ffcdf4;
                            box-shadow: inset 0 0 10px rgba(255, 95, 210, 0.35), 0 0 10px rgba(255, 95, 210, 0.35);
                            margin-bottom: 18px;
                        }
                        canvas {
                            width: 100%;
                            height: 420px;
                            border-radius: 14px;
                            border: 1px solid rgba(89, 243, 255, 0.35);
                            background: radial-gradient(circle at 30% 30%, rgba(255, 95, 210, 0.08), transparent 40%), #0b122a;
                            box-shadow: inset 0 0 30px rgba(0,0,0,0.35), 0 0 18px rgba(89, 243, 255, 0.12);
                        }
                        .typed {
                            margin-top: 22px;
                            font-size: 14px;
                            min-height: 24px;
                            letter-spacing: 0.8px;
                            color: #aaf6ff;
                            display: flex;
                            align-items: center;
                            gap: 10px;
                        }
                        #typed-text {
                            overflow: hidden;
                            white-space: nowrap;
                        }
                        .cursor {
                            display: inline-block;
                            width: 12px;
                            background: #aaf6ff;
                            animation: blink 0.8s infinite;
                            height: 14px;
                        }
                        @keyframes blink {
                            0%, 50% { opacity: 1; }
                            51%, 100% { opacity: 0.2; }
                        }
                        .footer-note {
                            margin-top: 18px;
                            font-size: 11px;
                            color: rgba(233, 247, 255, 0.65);
                            letter-spacing: 1px;
                        }
                    </style>
                </head>
                <body>
                <div class="grid-bg"></div>
                    <div class="shell">
                    <h1>0xb00b5 team Packmate</h1>
                    <div class="badge">// @danosito</div>
                        <canvas id="snap-canvas"></canvas>
                        <div class="typed">
                            <span id="typed-text"></span><span class="cursor"></span>
                        </div>
                    <div class="footer-note">Hmmm where are the packets? IDK</div>
                    </div>
                    <script>
                    const phrases = JSON.parse(atob('__PHRASES_B64__'));
                    const images = JSON.parse(atob('__IMAGES_B64__'));
                    const canvas = document.getElementById('snap-canvas');
                    const ctx = canvas.getContext('2d');
                    const textEl = document.getElementById('typed-text');

                    const pick = (list) => list[Math.floor(Math.random() * list.length)];
                    const specialLink = {
                        text: 'Your special guide to get flag!',
                        href: 'https://youtu.be/rrw-Pv3rc0E?si=-ZQmhZVxh4HF6luD'
                    };

                    function renderImage() {
                        const chosen = (images && images.length) ? pick(images) : '';
                        if (!chosen) {
                            ctx.fillStyle = '#0b122a';
                            ctx.fillRect(0, 0, canvas.width, canvas.height);
                            return;
                        }
                        const img = new Image();
                        img.onload = () => {
                            const maxW = 960;
                            const scale = Math.min(maxW / img.width, 1);
                            const w = img.width * scale;
                            const h = img.height * scale;
                            canvas.width = w;
                            canvas.height = h;
                            ctx.clearRect(0, 0, w, h);
                            ctx.drawImage(img, 0, 0, w, h);
                            setTimeout(() => snapAway(), 5000);
                        };
                        img.src = chosen;
                    }

                    function snapAway() {
                        let ticks = 0;
                        const interval = setInterval(() => {
                            for (let i = 0; i < 48; i++) {
                                const x = Math.random() * canvas.width;
                                const y = Math.random() * canvas.height;
                                const size = 4 + Math.random() * 10;
                                ctx.clearRect(x, y, size, size);
                            }
                            ticks++;
                            if (ticks > 80) {
                                clearInterval(interval);
                                setTimeout(renderImage, 400);
                            }
                        }, 28);
                    }

                    function typewriter() {
                        const phrase = pick(phrases);
                        const isSpecial = phrase === specialLink.text;
                        textEl.textContent = '';
                        let linkEl = null;
                        if (isSpecial) {
                            linkEl = document.createElement('a');
                            linkEl.href = specialLink.href;
                            linkEl.target = '_blank';
                            linkEl.rel = 'noreferrer noopener';
                            linkEl.style.color = '#aaf6ff';
                            textEl.appendChild(linkEl);
                        }
                        let i = 0;
                        const typeDelay = phrase.length ? 5000 / phrase.length : 120;

                        const typeInterval = setInterval(() => {
                            const target = isSpecial ? linkEl : textEl;
                            target.textContent += phrase.charAt(i);
                            i++;
                            if (i >= phrase.length) {
                                clearInterval(typeInterval);
                                setTimeout(() => erase(phrase, isSpecial), 3000);
                            }
                        }, typeDelay);
                    }

                    function erase(phrase, isSpecial) {
                        const eraseDelay = phrase.length ? 2000 / phrase.length : 80;
                        const eraser = setInterval(() => {
                            const target = isSpecial ? textEl.querySelector('a') : textEl;
                            if (!target) {
                                clearInterval(eraser);
                                setTimeout(typewriter, 200);
                                return;
                            }
                            target.textContent = target.textContent.slice(0, -1);
                            if (!target.textContent.length) {
                                if (isSpecial) {
                                    target.remove();
                                }
                                clearInterval(eraser);
                                setTimeout(typewriter, 200);
                            }
                        }, eraseDelay);
                    }

                    renderImage();
                    typewriter();
                </script>
                </body>
                </html>
                """;
        return template
                .replace("__PHRASES_B64__", phrasesB64)
                .replace("__IMAGES_B64__", imagesB64);
    }

    public String fakePacketsHtml() {
        return """
                <!doctype html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <title>0xb00b5 PM // packets</title>
                    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/css/bootstrap.min.css">
                    <style>
                        @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=JetBrains+Mono:wght@400;600&display=swap');
                        :root {
                            --bg: #05030a;
                            --bg-2: #0a0a18;
                            --panel: rgba(9, 7, 18, 0.9);
                            --panel-strong: rgba(14, 10, 24, 0.95);
                            --accent: #c66bff;
                            --accent-2: #7a1dff;
                            --text: #e6e0ff;
                            --muted: #9b90c8;
                            --mono: 'JetBrains Mono', 'Ubuntu Mono', monospace;
                            --pixel: 'Press Start 2P', 'JetBrains Mono', monospace;
                        }
                        * { box-sizing: border-box; scrollbar-width: none; }
                        *::-webkit-scrollbar { width: 0; height: 0; }
                        body {
                            margin: 0;
                            min-height: 100vh;
                            background:
                                    radial-gradient(circle at 18% 24%, rgba(198, 107, 255, 0.18), transparent 25%),
                                    radial-gradient(circle at 82% 12%, rgba(122, 29, 255, 0.12), transparent 25%),
                                    linear-gradient(135deg, #020107 0%, #0a0820 50%, #03010b 100%);
                            color: var(--text);
                            font-family: var(--pixel);
                            letter-spacing: 0.6px;
                            overflow: hidden;
                        }
                        .bg-lines {
                            position: fixed; inset: 0; pointer-events: none; z-index: 0;
                            background-image: linear-gradient(rgba(122, 29, 255, 0.1) 1px, transparent 1px),
                            linear-gradient(90deg, rgba(198, 107, 255, 0.12) 1px, transparent 1px);
                            background-size: 120px 120px;
                        }
                        .app-shell {
                            position: relative;
                            z-index: 1;
                        }
                        .navbar {
                            background: var(--panel-strong);
                            border-bottom: 1px solid rgba(122, 29, 255, 0.45);
                            box-shadow: 0 10px 35px rgba(0, 0, 0, 0.55), 0 0 28px rgba(122, 29, 255, 0.35);
                            padding: 12px 18px;
                        }
                        .brand {
                            display: flex;
                            align-items: center;
                            gap: 10px;
                            color: var(--accent);
                        }
                        .brand .dot {
                            width: 12px;
                            height: 12px;
                            border-radius: 50%;
                            background: linear-gradient(135deg, var(--accent), var(--accent-2));
                            box-shadow: 0 0 10px rgba(122, 29, 255, 0.65);
                        }
                        .metrics {
                            display: flex;
                            gap: 10px;
                            align-items: center;
                            margin-left: 12px;
                            flex-wrap: wrap;
                        }
                        .chip {
                            background: rgba(122, 29, 255, 0.12);
                            border: 1px solid rgba(122, 29, 255, 0.28);
                            color: var(--text);
                            padding: 8px 10px;
                            border-radius: 10px;
                            display: grid;
                            grid-template-columns: auto auto;
                            column-gap: 8px;
                            align-items: center;
                            font-size: 11px;
                            box-shadow: 0 0 14px rgba(122, 29, 255, 0.24);
                        }
                        .chip .label { color: var(--muted); }
                        .chip .value { color: var(--accent); }
                        .patterns-dropdown {
                            display: inline-flex;
                            width: 128px;
                            min-width: 128px;
                            max-width: 128px;
                            flex: 0 0 128px;
                            flex-shrink: 0;
                            box-sizing: border-box;
                            margin-left: 14px;
                        }
                        .patterns-dropdown > button {
                            display: inline-flex;
                            justify-content: center;
                            align-items: center;
                            font-family: var(--pixel);
                            font-size: 9.6px;
                            letter-spacing: 0.05px;
                            width: 128px;
                            min-width: 128px;
                            max-width: 128px;
                            padding-left: 8px;
                            padding-right: 8px;
                            white-space: nowrap;
                        }
                        .services-nav {
                            display: flex;
                            align-items: center;
                            gap: 4px;
                            margin-left: 14px;
                            flex-wrap: wrap;
                        }
                        .services-nav .nav-link {
                            padding: 6px 10px;
                            border-radius: 10px;
                            margin: 2px 0;
                            background: rgba(122, 29, 255, 0.12);
                            border: 1px solid rgba(122, 29, 255, 0.28);
                            color: var(--text);
                            font-size: 10px;
                            letter-spacing: 0.3px;
                            white-space: nowrap;
                        }
                        .layout {
                            display: grid;
                            grid-template-columns: 320px 1fr;
                            gap: 0;
                            min-height: calc(100vh - 72px);
                        }
                        .sidebar {
                            background: var(--panel);
                            border-right: 1px solid rgba(122, 29, 255, 0.25);
                            box-shadow: inset -10px 0 24px rgba(0, 0, 0, 0.35);
                            padding: 16px 12px;
                            overflow-y: auto;
                        }
                        .sidebar-title {
                            font-size: 10px;
                            text-transform: uppercase;
                            color: var(--muted);
                            margin-bottom: 10px;
                        }
                        .content {
                            background: var(--panel);
                            border-left: 1px solid rgba(122, 29, 255, 0.15);
                            padding: 18px 22px 26px;
                            box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.45), 0 0 38px rgba(122, 29, 255, 0.18);
                            position: relative;
                            min-height: calc(100vh - 120px);
                        }
                        .content-header {
                            display: flex;
                            align-items: center;
                            justify-content: space-between;
                            margin-bottom: 14px;
                        }
                        .title {
                            font-size: 12px;
                            color: var(--text);
                        }
                        .packet-board {
                            background: rgba(9, 7, 18, 0.9);
                            border: 1px solid rgba(122, 29, 255, 0.35);
                            border-radius: 14px;
                            min-height: calc(100vh - 160px);
                            padding: 14px;
                            overflow: hidden;
                        }
                        .packet-feed {
                            font-family: var(--mono);
                            font-size: 11px;
                            max-height: calc(100vh - 200px);
                            overflow-y: auto;
                            padding-right: 6px;
                        }
                        .packet-line {
                            display: flex;
                            align-items: baseline;
                            gap: 10px;
                            padding: 6px 0;
                            border-bottom: 1px dashed rgba(122, 29, 255, 0.2);
                            color: var(--text);
                        }
                        .packet-line .pill {
                            display: inline-block;
                            padding: 2px 8px;
                            border-radius: 8px;
                            background: rgba(122, 29, 255, 0.2);
                            border: 1px solid rgba(122, 29, 255, 0.35);
                            font-size: 9px;
                            letter-spacing: 0.4px;
                            color: var(--accent);
                        }
                        .packet-line .meta {
                            color: var(--muted);
                            font-size: 10px;
                        }
                        .packet-line .bytes { color: #9ff8ff; }
                        .empty-slot { background: transparent; border: none; box-shadow: none; }
                    </style>
                </head>
                <body>
                    <div class="bg-lines"></div>
                    <div class="app-shell">
                        <nav class="navbar navbar-dark navbar-expand fixed-top">
                            <div class="d-flex align-items-center">
                                <span class="brand">
                                    <span class="dot"></span>
                                    0xb00b5 PM
                                </span>
                            </div>
                            <div class="metrics">
                                <span class="chip"><span class="label">SPM</span><span class="value" id="metric-spm">0</span></span>
                                <span class="chip"><span class="label">PPS</span><span class="value" id="metric-pps">0</span></span>
                            </div>
                            <div class="patterns-dropdown">
                                <button class="btn btn-dark btn-block" disabled>Patterns</button>
                            </div>
                            <div class="services-nav" id="nav-services"></div>
                            <span class="ml-auto text-monospace text-muted" style="font-size: 10px;">[Selected: none]</span>
                        </nav>
                        <div class="layout" style="margin-top: 64px;">
                            <aside class="sidebar">
                                <div class="sidebar-title">Packets</div>
                                <div class="packet-board">
                                    <div class="packet-feed" id="packet-feed"></div>
                                </div>
                            </aside>
                            <main class="content empty-slot"></main>
                        </div>
                    </div>
                <script>
                    const navServicesEl = document.getElementById('nav-services');
                    const feedEl = document.getElementById('packet-feed');
                    const spmEl = document.getElementById('metric-spm');
                    const ppsEl = document.getElementById('metric-pps');
                    let services = [];
                    let packetId = Math.floor(Math.random() * 5000) + 10;

                    fetch('/api/fake/services')
                        .then(r => r.json())
                        .then(data => {
                            services = data;
                            renderServices();
                            startFeed();
                        })
                        .catch(() => {
                            services = [{ name: 'ghost', port: 0, packetKind: 'tcp' }];
                            renderServices();
                            startFeed();
                        });

                    function renderServices() {
                        navServicesEl.innerHTML = '';
                        services.forEach((svc) => {
                            const link = document.createElement('a');
                            link.className = 'nav-link';
                            link.href = '#';
                            link.textContent = `${svc.name} #${svc.port}`;
                            navServicesEl.appendChild(link);
                        });
                    }

                    function spawnPacket() {
                        if (!services.length) return;
                        const svc = services[Math.floor(Math.random() * services.length)];
                        const proto = (svc.packetKind || 'tcp').toUpperCase();
                        const ts = new Date();
                        const clock = ts.toTimeString().slice(0, 8);
                        const bytes = Math.floor(Math.random() * 1800) + 40;

                        const line = document.createElement('div');
                        line.className = 'packet-line';
                        line.innerHTML = `
                            <span class="pill">${proto}</span>
                            <span class="meta">${clock}</span>
                            <span class="meta">:${svc.port} ${svc.name}</span>
                            <span class="bytes">${bytes} bytes</span>
                            <span class="meta">id #${packetId}</span>
                        `;
                        packetId++;
                        feedEl.prepend(line);
                        while (feedEl.children.length > 120) {
                            feedEl.removeChild(feedEl.lastChild);
                        }
                        updateMetrics();
                    }

                    function updateMetrics() {
                        const total = feedEl.children.length;
                        spmEl.textContent = Math.min(total, 999);
                        ppsEl.textContent = Math.floor(total / 2);
                    }

                    function startFeed() {
                        setInterval(spawnPacket, 55);
                    }
                </script>
                </body>
                </html>
                """;
    }

    private List<String> getFunPhrases() {
        return List.of(
                "Here's the flag. Are you ready? here it goes... Wait, no.",
                "Wanna see the flag? send yours to @danosito:)",
                "Hey, why are you here? go pentest our services",
                "Hmmm i think <script>alert(\"You're stupid\")</script> might work..",
                "Bip, boop, here was packet but codex ate it",
                "Our LLM tockens ran out. Maybe you could give us some:)?",
                ":(){ :|:& };:",
                "i think creds are admin:admin but i'm not sure...",
                "Try eternalBlue, i think it would work",
                "I think i defended this page well enough, here is flag: LLMDELETEDTHEFLAG=",
                "Go open ida pro and reverse this text",
                "I would give you our flags for free, but you are a bad person:(",
                "b00b5 is not a fresh meat:(",
                "marcus, send your packmate credits pls",
                "Marcus, fuck off",
                "Your special guide to get flag!"
        );
    }

    private String toJson(List<String> data) {
        try {
            return mapper.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            log.warn("Failed to convert data to json for fake admin", e);
            return "[]";
        }
    }
}
