<template>
    <OverlayScrollbarsComponent class="dev-view" :options="scrollbarOptions" element="div" v-if="isLoggedIn">
      <div class="page">
        <div class="dev-header">
            <h2>/dev</h2>
            <div class="dev-actions">
                <RouterLink to="/agents" class="dev-disco-btn"><HomeIcon class="w-4 h-4 inline" /> Home</RouterLink>
                <button class="dev-disco-btn" @click="disco" :disabled="discoing"><BoltIcon class="w-4 h-4 inline" /> Disconnect Gateway</button>
                <button class="dev-disco-btn" @click="discoChat" :disabled="discoChatting"><SignalSlashIcon class="w-4 h-4 inline" /> Disconnect Chat</button>
            </div>
        </div>

        <div class="content">
        <!-- Theme -->
        <div class="dev-section">
            <h3>Theme</h3>
            <div class="dev-actions">
                <button
                    class="dev-theme-btn"
                    :class="{ active: theme === 'loop42' }"
                    @click="setTheme('loop42')"
                ><component :is="THEME_ICONS.loop42" class="w-4 h-4 inline" /> loop42</button>
                <button
                    class="dev-theme-btn"
                    :class="{ active: theme === 'titan' }"
                    @click="setTheme('titan')"
                ><component :is="THEME_ICONS.titan" class="w-4 h-4 inline" /> Titan</button>
                <button
                    class="dev-theme-btn"
                    :class="{ active: theme === 'eras' }"
                    @click="setTheme('eras')"
                ><component :is="THEME_ICONS.eras" class="w-4 h-4 inline" /> ERAS</button>
            </div>
        </div>

        <!-- Dev Flags -->
        <div class="dev-section">
            <h3>Dev Flags</h3>
            <div class="dev-flags">
                <label class="dev-flag">
                    <input type="checkbox" v-model="devFlags.showGrid" />
                    <span>showGrid</span>
                </label>
                <label class="dev-flag">
                    <input type="checkbox" v-model="devFlags.showDebugInfo" />
                    <span>showDebugInfo</span>
                </label>
                <label class="dev-flag">
                    <input type="checkbox" v-model="devFlags.showHud" />
                    <span>showHud</span>
                </label>
            </div>
        </div>

        <!-- Takeover -->
        <div class="dev-section">
            <h3>Takeover</h3>
            <div class="dev-actions" v-if="!takeoverToken">
                <button class="dev-theme-btn" @click="handleInitTakeover"><LinkIcon class="w-4 h-4 inline" /> Enable Takeover</button>
            </div>
            <div v-else class="dev-actions" style="gap: var(--space-page); align-items: center; flex-wrap: wrap;">
                <code class="takeover-token">{{ takeoverToken }}</code>
                <button class="dev-theme-btn active" @click="handleRevoke"><XMarkIcon class="w-4 h-4 inline" /> Revoke</button>
                <button class="dev-theme-btn" :class="{ active: captureActive }" @click="handleToggleCapture">
                    <CameraIcon class="w-4 h-4 inline" /> {{ captureActive ? 'Capture ON' : 'Enable Capture' }}
                </button>
            </div>
        </div>

        <!-- System Access -->
        <div class="dev-section" v-if="systemRequests.length > 0 || systemGranted">
            <h3>System Access</h3>
            <div v-if="systemGranted" class="dev-system-granted">
                Access granted to {{ systemGranted.user }} — active until session end.
            </div>
            <div v-for="req in systemRequests" :key="req.requestId" class="dev-system-request">
                <div class="dev-system-code">{{ req.userCode }}</div>
                <div class="dev-system-desc">{{ req.description }}</div>
                <div class="dev-system-expiry">expires in {{ Math.max(0, Math.ceil((req.expiresAt - Date.now()) / 1000)) }}s</div>
                <div class="dev-actions" style="margin-top: 8px;">
                    <button class="dev-theme-btn" @click="denySystemRequest(req.requestId)">Deny</button>
                    <button class="dev-theme-btn active" @click="approveSystemRequest(req.requestId)">Approve</button>
                </div>
            </div>
        </div>

        <!-- MCP Counter -->
        <div class="dev-section">
            <h3>MCP Counter</h3>
            <div class="counter-widget" :class="{ muted: counterMuted }">
                <div class="counter-controls">
                    <button class="counter-btn" @click="counterAction('decrement')" :disabled="counterMuted || counterBusy">−</button>
                    <span class="counter-value" id="mcp-counter-value">{{ counterValue }}</span>
                    <button class="counter-btn" @click="counterAction('increment')" :disabled="counterMuted || counterBusy">+</button>
                </div>
                <div v-if="challengeMessage" class="counter-challenge">
                    <span class="counter-message">{{ challengeMessage }}</span>
                    <span v-if="challengeTimer > 0" class="counter-timer">{{ challengeTimer }}s</span>
                </div>
                <div v-else class="counter-hint">Waiting for Claude...</div>
            </div>
        </div>

        <!-- Action Picker -->
        <div class="dev-section" v-if="actionPicker.title">
            <h3>{{ actionPicker.title }}</h3>
            <div class="action-picker">
                <button
                    v-for="(opt, i) in actionPicker.options"
                    :key="i"
                    class="action-pick-btn"
                    :disabled="actionPickerBusy"
                    @click="pickAction(opt.id)"
                >{{ opt.label }}</button>
            </div>
        </div>

        <!-- Credits -->
        <div class="dev-section">
            <h3>OpenRouter Credits</h3>
            <div v-if="loading && !stats" class="dev-loading">Loading…</div>
            <div v-else-if="statsError" class="dev-error">{{ statsError }}</div>
            <div v-else-if="stats" class="credits-widget">
                <div class="credits-bar-track">
                    <div class="credits-bar-fill" :style="{ width: usedPct + '%' }"></div>
                </div>
                <div class="credits-row">
                    <div class="credits-stat">
                        <span class="credits-label">Used</span>
                        <span class="credits-amount credits-used">${{ fmt(stats.credits.used) }}</span>
                    </div>
                    <div class="credits-stat">
                        <span class="credits-label">Remaining</span>
                        <span class="credits-amount credits-remaining">${{ fmt(stats.credits.remaining) }}</span>
                    </div>
                    <div class="credits-stat">
                        <span class="credits-label">Total</span>
                        <span class="credits-amount">${{ fmt(stats.credits.total) }}</span>
                    </div>
                </div>
            </div>
        </div>

        <!-- Agents table -->
        <div class="dev-section" v-if="stats">
            <h3>Agents</h3>
            <div class="dev-table-wrap">
            <table class="dev-table">
                <thead>
                    <tr>
                        <th>Agent</th>
                        <th>Model</th>
                        <th>Context</th>
                        <th>Prompt / 1M</th>
                        <th>Completion / 1M</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="a in stats.agents" :key="a.id">
                        <td class="agent-id">{{ a.id }}</td>
                        <td><code>{{ a.modelId || a.model }}</code></td>
                        <td>{{ a.contextLength ? (a.contextLength / 1000).toFixed(0) + 'k' : '—' }}</td>
                        <td>{{ a.promptPrice !== null ? '$' + a.promptPrice.toFixed(3) : '—' }}</td>
                        <td>{{ a.completionPrice !== null ? '$' + a.completionPrice.toFixed(3) : '—' }}</td>
                    </tr>
                </tbody>
            </table>
            </div>
        </div>
        </div>

      </div>

      <!-- Breakout confirmation modal (inside v-if="isLoggedIn") -->
      <Teleport to="body">
        <div v-if="breakoutReq" class="breakout-modal-overlay" @click.self="denyBreakout">
          <div class="breakout-modal">
            <h3>Open Breakout</h3>
            <p>Name: <strong>{{ breakoutReq.name }}</strong></p>
            <p>Size: <strong>{{ breakoutReq.preset }}</strong></p>
            <p class="breakout-nonce">{{ breakoutReq.nonce }}</p>
            <div class="breakout-modal-actions">
              <button class="dev-theme-btn" @click="denyBreakout">Cancel</button>
              <button class="dev-theme-btn active" @click="confirmBreakout">Confirm</button>
            </div>
          </div>
        </div>
      </Teleport>
    </OverlayScrollbarsComponent>

    <div v-else class="not-logged-in">
        <p><LockClosedIcon class="w-5 h-5 inline" /> Not logged in</p>
        <RouterLink to="/login">Sign in &rarr;</RouterLink>
    </div>
</template>

<script setup lang="ts">
defineOptions({ name: 'DevView' });
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue';
import { useRoute } from 'vue-router';
import { ws, auth, takeover } from '../store';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-vue';
import { scrollbarOptions } from '../composables/useScrollbar';
import { BoltIcon, SignalSlashIcon, LockClosedIcon, LinkIcon, XMarkIcon, CameraIcon, HomeIcon } from '@heroicons/vue/20/solid';
import { THEME_ICONS } from '../composables/useTheme';
import { useTheme } from '../composables/useTheme';
import { useDevFlags } from '../composables/useDevFlags';
import { getApiBase } from '../utils/apiBase';

const route = useRoute();
const { isLoggedIn } = auth;
const { connected, send: wsSend, onMessage } = ws;
const { theme, setTheme } = useTheme();
const devFlags = useDevFlags();

// ── Takeover (delegates to composables) ──
const takeoverToken = takeover.token;
const captureActive = takeover.capture.isActive;
const breakoutReq = takeover.breakout.pendingRequest;

function handleInitTakeover() { takeover.init(); }
function handleRevoke() { takeover.revoke(); }

// Breakout modal confirm/deny (for CLI-initiated openBreakout)
function confirmBreakout() { breakoutReq.value?.resolve(true); }
function denyBreakout() { breakoutReq.value?.resolve(false); }

// Capture toggle
async function handleToggleCapture() {
    if (captureActive.value) {
        takeover.capture.disable();
    } else {
        await takeover.capture.enable();
    }
}

// ── System Access ──
const SESSION_KEY = 'nyx_session';
const SESSION_TOKEN = () => localStorage.getItem(SESSION_KEY) ?? '';

interface SystemRequest { requestId: string; userCode: string; description: string; expiresAt: number; }
const systemRequests = ref<SystemRequest[]>([]);
const systemGranted  = ref<{ user: string } | null>(null);

async function fetchPendingSystemRequests() {
    try {
        const res = await fetch(`${getApiBase()}/api/system/pending`, {
            headers: { Authorization: `Bearer ${SESSION_TOKEN()}` },
        });
        if (res.ok) {
            const { pending } = await res.json();
            systemRequests.value = pending ?? [];
        }
    } catch { /* silent */ }
}

async function approveSystemRequest(requestId: string) {
    const res = await fetch(`${getApiBase()}/api/system/approve`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ sessionToken: SESSION_TOKEN(), requestId }),
    });
    if (res.ok) systemRequests.value = systemRequests.value.filter(r => r.requestId !== requestId);
}

async function denySystemRequest(requestId: string) {
    await fetch(`${getApiBase()}/api/system/deny`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ sessionToken: SESSION_TOKEN(), requestId }),
    });
    systemRequests.value = systemRequests.value.filter(r => r.requestId !== requestId);
}

// ── MCP Counter ──
const counterValue = ref(Math.floor(Math.random() * 11)); // 0..10
const counterBusy = ref(false);
const counterMuted = ref(true);
const challengeMessage = ref('');
const challengeTimer = ref(0);
let challengeInterval: ReturnType<typeof setInterval> | null = null;
let challengeGen = 0;

// ── Action Picker ──
const actionPicker = ref<{ title: string; options: { id: string; label: string }[] }>({ title: '', options: [] });
const actionPickerBusy = ref(false);
async function pickAction(id: string) {
    actionPickerBusy.value = true;
    actionPicker.value = { title: '', options: [] };
    try {
        await fetch(`${getApiBase()}/api/dev/counter`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${SESSION_TOKEN()}` },
            body: JSON.stringify({ action: 'pick', pick: id }),
        });
    } catch { /* silent */ }
    actionPickerBusy.value = false;
}

async function counterAction(action: 'increment' | 'decrement') {
    counterMuted.value = true;
    challengeGen++;
    if (challengeInterval) { clearInterval(challengeInterval); challengeInterval = null; }
    challengeMessage.value = '';
    challengeTimer.value = 0;
    counterBusy.value = true;
    try {
        await fetch(`${getApiBase()}/api/dev/counter`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${SESSION_TOKEN()}` },
            body: JSON.stringify({ action }),
        });
    } catch { /* silent */ }
    counterBusy.value = false;
}

// ── Stats ──
const loading = ref(false);
const statsError = ref('');
const stats = ref<any>(null);

function fmt(v: number | null) {
    if (v === null || v === undefined) return '—';
    return v.toFixed(2);
}

const usedPct = computed(() => {
    const t = stats.value?.credits?.total;
    const u = stats.value?.credits?.used;
    if (!t) return 0;
    return Math.min(100, (u / t) * 100);
});

function load() {
    if (!connected.value) return;
    loading.value = true;
    statsError.value = '';
    wsSend({ type: 'stats_request' });
}

const discoing = ref(false);
const discoChatting = ref(false);

function disco() {
    if (!connected.value) return;
    discoing.value = true;
    wsSend({ type: 'disco_request' });
    setTimeout(() => { discoing.value = false; }, 2000);
}

function discoChat() {
    if (!connected.value) return;
    discoChatting.value = true;
    wsSend({ type: 'disco_chat_request' });
    setTimeout(() => { discoChatting.value = false; }, 3000);
}

// ── Polling lifecycle ──
let unsubscribeWs: (() => void) | null = null;
let refreshInterval: number | undefined;

onMounted(() => {
    fetchPendingSystemRequests();

    unsubscribeWs = onMessage((data: any) => {
        if (data.type === 'system_access_request') {
            if (!systemRequests.value.find(r => r.requestId === data.requestId))
                systemRequests.value.push(data);
            return;
        }
        if (data.type === 'counter_update') {
            counterValue.value = data.value ?? counterValue.value;
            return;
        }
        if (data.type === 'counter_challenge') {
            challengeMessage.value = data.message || 'DECIDE NOW!';
            challengeTimer.value = data.timeout || 30;
            counterMuted.value = false;
            // Flash + scroll into view
            nextTick(() => {
                const el = document.querySelector('.counter-widget');
                if (el) {
                    el.classList.remove('flash');
                    void (el as HTMLElement).offsetWidth; // reflow
                    el.classList.add('flash');
                    el.scrollIntoView({ behavior: 'smooth', block: 'center' });
                }
            });
            if (challengeInterval) clearInterval(challengeInterval);
            const cid = ++challengeGen;
            challengeInterval = setInterval(() => {
                if (cid !== challengeGen) { clearInterval(challengeInterval!); return; }
                challengeTimer.value--;
                if (challengeTimer.value <= 0) {
                    if (challengeInterval) { clearInterval(challengeInterval); challengeInterval = null; }
                    counterMuted.value = true;
                    challengeMessage.value = '';
                    fetch(`${getApiBase()}/api/dev/counter`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${SESSION_TOKEN()}` },
                        body: JSON.stringify({ action: 'timeout' }),
                    });
                }
            }, 1000);
            return;
        }
        if (data.type === 'confetti') {
            const container = document.createElement('div');
            container.className = 'confetti-container';
            const colors = ['#ff6b6b','#ffd93d','#6bcb77','#4d96ff','#ff922b','#cc5de8'];
            for (let i = 0; i < 60; i++) {
                const piece = document.createElement('div');
                piece.className = 'confetti-piece';
                piece.style.left = Math.random() * 100 + '%';
                piece.style.background = colors[Math.floor(Math.random() * colors.length)];
                piece.style.animationDelay = Math.random() * 2 + 's';
                piece.style.borderRadius = Math.random() > 0.5 ? '50%' : '0';
                container.appendChild(piece);
            }
            document.body.appendChild(container);
            setTimeout(() => container.remove(), 5000);
            return;
        }
        if (data.type === 'action_picker') {
            actionPicker.value = { title: data.title || 'Next?', options: data.options || [] };
            actionPickerBusy.value = false;
            return;
        }
        if (data.type === 'counter_mute') {
            counterMuted.value = true;
            challengeMessage.value = data.message || '';
            if (challengeInterval) { clearInterval(challengeInterval); challengeInterval = null; }
            challengeTimer.value = 0;
            return;
        }
        if (data.type === 'stats') {
            loading.value = false;
            if (data.error) { statsError.value = data.error; }
            else { stats.value = data; }
        }
    });

    const startRefresh = () => {
        load();
        refreshInterval = setInterval(load, 15000) as unknown as number;
    };

    if (connected.value) {
        startRefresh();
    } else {
        const stop = watch(connected, (val) => {
            if (val) { stop(); startRefresh(); }
        });
    }
});

watch(() => route.name, (name, prev) => {
    if (name === 'dev' && !refreshInterval && connected.value) {
        load();
        refreshInterval = setInterval(load, 15000) as unknown as number;
    } else if (prev === 'dev' && name !== 'dev' && refreshInterval) {
        clearInterval(refreshInterval);
        refreshInterval = undefined;
    }
});

onUnmounted(() => {
    if (unsubscribeWs) unsubscribeWs();
    if (refreshInterval) clearInterval(refreshInterval);
});
</script>

<style scoped>
.dev-view {
    height: 100%;
}

.dev-system-request {
    background: color-mix(in srgb, var(--color-accent) 8%, var(--color-surface));
    border: 1px solid color-mix(in srgb, var(--color-accent) 30%, transparent);
    border-radius: 6px;
    padding: 12px 16px;
    margin-bottom: 8px;
}
.dev-system-code {
    font-family: monospace;
    font-size: 1.4em;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--color-accent);
    margin-bottom: 4px;
}
.dev-system-desc {
    font-size: 0.9em;
    color: var(--color-text);
    margin-bottom: 2px;
}
.dev-system-expiry {
    font-size: 0.8em;
    color: var(--color-text-dim);
    margin-bottom: 4px;
}
.dev-system-granted {
    font-size: 0.9em;
    color: var(--color-success-dim, #4ade80);
    padding: 6px 0;
}
</style>
