/**
 * SC2 Stream Widget - Configurable overlay for OBS
 *
 * URL Parameters:
 *   ?width=800    - widget width in px (default: 500)
 *   ?height=400   - widget height in px (default: 400)
 *   ?games=5      - number of recent games (default: 5)
 *   ?layout=vertical|horizontal  - stack direction (default: vertical)
 *   ?showChart=true|false  - show MMR chart (default: true)
 *   ?chartHeight=150  - chart height in px (default: 150)
 */

const REFRESH_INTERVAL_MS = 2000;
const MMR_MIN_VALID = 2000;
const MMR_MAX_VALID = 8000;
const ADAPTIVE_PADDING_PERCENT = 0.18;
const MIN_Y_RANGE = 200;

let chart = null;

// Default widget columns
const DEFAULT_WIDGET_COLUMNS = ["matchup", "result", "mmr_diff", "map", "time"];

// Parse URL params
function getParams() {
    const p = new URLSearchParams(window.location.search);
    const columnsParam = p.get("columns");
    return {
        width: parseInt(p.get("width")) || 1200,
        height: parseInt(p.get("height")) || 800,
        games: parseInt(p.get("games")) || 5,
        layout: p.get("layout") || "vertical",
        showChart: p.get("showChart") !== "false",
        chartHeight: parseInt(p.get("chartHeight")) || 150,
        columns: columnsParam ? columnsParam.split(",") : DEFAULT_WIDGET_COLUMNS,
    };
}

function formatDate(isoDate) {
    if (!isoDate) return "";
    try {
        const d = new Date(isoDate);
        return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
    } catch { return ""; }
}

// Auto-detected defaults (populated on init)
let defaultFilters = {};

async function loadDefaults() {
    try {
        const [racesRes, regionsRes] = await Promise.all([
            fetch('/api/v1/races').then(r => r.json()),
            fetch('/api/v1/regions').then(r => r.json()),
        ]);
        if (racesRes.default) defaultFilters.player_race = racesRes.default;
        if (regionsRes.default) defaultFilters.region = regionsRes.default;
    } catch {}
}

function buildFilterParams(extra = {}) {
    return new URLSearchParams({ ...defaultFilters, ...extra });
}

async function fetchReplays(count) {
    const params = buildFilterParams({ limit: count });
    const res = await fetch(`/api/v1/replays?${params}`);
    return res.json();
}

async function fetchMmrHistory() {
    const params = buildFilterParams();
    const res = await fetch(`/api/v1/mmr/history?${params}`);
    return res.json();
}

function formatDuration(seconds) {
    if (seconds == null) return "-";
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;
    return `${mins}:${String(secs).padStart(2, "0")}`;
}

function getWidgetCell(col, r) {
    const isWin = (r.result || "").toLowerCase() === "win";
    switch (col) {
        case "matchup":
            return `<span class="game-matchup">${r.matchup || "?"}</span>`;
        case "result": {
            const color = isWin ? "#00ff88" : "#ff4444";
            return `<span class="game-result" style="color: ${color}">${isWin ? "W" : "L"}</span>`;
        }
        case "mmr_diff": {
            const change = r.mmr_change;
            if (change == null) return `<span class="game-mmr-diff" style="color: rgba(255,255,255,0.3)">-</span>`;
            const str = change > 0 ? `+${change}` : `${change}`;
            const color = change > 0 ? "#00ff88" : change < 0 ? "#ff4444" : "rgba(255,255,255,0.4)";
            return `<span class="game-mmr-diff" style="color: ${color}">${str}</span>`;
        }
        case "mmr": {
            const mmr = r.post_mmr != null ? r.post_mmr : r.player_mmr;
            return `<span class="game-mmr-diff" style="color: rgba(255,255,255,0.7)">${mmr || "-"}</span>`;
        }
        case "opponent_mmr":
            return `<span class="game-mmr-diff" style="color: rgba(255,255,255,0.5)">${r.opponent_mmr || "-"}</span>`;
        case "map":
            return `<span class="game-map">${r.map_name || ""}</span>`;
        case "opponent":
            return `<span class="game-map">${r.opponent_name || ""}</span>`;
        case "apm":
            return `<span class="game-mmr-diff" style="color: rgba(255,255,255,0.5)">${r.player_apm || "-"}</span>`;
        case "length":
            return `<span class="game-time">${formatDuration(r.game_length_sec)}</span>`;
        case "time":
            return `<span class="game-time">${formatDate(r.played_at)}</span>`;
        case "workers_8m":
            return `<span class="game-mmr-diff" style="color: rgba(255,255,255,0.5)">${r.workers_8m || "-"}</span>`;
        default:
            return `<span class="game-map">${r[col] || "-"}</span>`;
    }
}

function renderGamesList(replays) {
    const container = document.getElementById("gamesList");
    const columns = getParams().columns;

    if (!replays || replays.length === 0) {
        container.innerHTML = '<div class="game-row" style="opacity: 0.3">No recent games</div>';
        return;
    }

    container.innerHTML = replays.map(r =>
        `<div class="game-row">${columns.map(col => getWidgetCell(col, r)).join("")}</div>`
    ).join("");
}

function updateStatsDisplay(replays) {
    if (!replays || replays.length === 0) return;

    const latest = replays[0];
    const mmrEl = document.getElementById("currentMMR");
    if (latest.player_mmr) {
        mmrEl.textContent = latest.player_mmr.toLocaleString();
    }

    const wins = replays.filter(r => (r.result || "").toLowerCase() === "win").length;
    const total = replays.length;
    const wr = total > 0 ? Math.round((wins / total) * 100) : 0;
    document.getElementById("winRate").textContent = `${wr}%`;
}

function calculateAdaptiveYAxis(data) {
    if (!data || data.length === 0) return { min: 0, max: 5000 };
    const mmrValues = data.map(d => d.mmr);
    const minMMR = Math.min(...mmrValues);
    const maxMMR = Math.max(...mmrValues);
    const range = Math.max(maxMMR - minMMR, MIN_Y_RANGE);
    const padding = range * ADAPTIVE_PADDING_PERCENT;
    return {
        min: Math.floor((minMMR - padding) / 50) * 50,
        max: Math.ceil((maxMMR + padding) / 50) * 50,
    };
}

async function initChart() {
    const params = getParams();
    if (!params.showChart) {
        document.getElementById("chartArea").style.display = "none";
        return;
    }

    document.getElementById("chartArea").style.height = `${params.chartHeight}px`;

    const result = await fetchMmrHistory();
    const data = (result.data || []).filter(d => d.mmr >= MMR_MIN_VALID && d.mmr <= MMR_MAX_VALID);

    const yAxis = calculateAdaptiveYAxis(data);
    const ctx = document.getElementById("mmrChart").getContext("2d");

    chart = new Chart(ctx, {
        type: "line",
        data: {
            labels: data.map((_, i) => i + 1),
            datasets: [{
                data: data.map(d => d.mmr),
                borderColor: "#ff9d5c",
                borderWidth: 2,
                backgroundColor: "rgba(255, 120, 60, 0.08)",
                pointBackgroundColor: data.map(d => d.result === "Win" ? "#00ff88" : "#ff4444"),
                pointBorderColor: data.map(d => d.result === "Win" ? "#00ff88" : "#ff4444"),
                pointRadius: 3,
                pointHoverRadius: 4,
                tension: 0.3,
                fill: true,
            }],
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: { legend: { display: false }, tooltip: { enabled: false } },
            scales: {
                x: {
                    display: false,
                },
                y: {
                    min: yAxis.min, max: yAxis.max,
                    ticks: { color: "rgba(255,255,255,0.5)", font: { family: "Roboto Mono", size: 10 }, maxTicksLimit: 4, callback: v => v.toLocaleString() },
                    grid: { color: "rgba(255,255,255,0.06)" },
                    border: { display: false },
                },
            },
            animation: false,
        },
    });
}

async function updateChart() {
    if (!chart) return;

    const result = await fetchMmrHistory();
    const data = (result.data || []).filter(d => d.mmr >= MMR_MIN_VALID && d.mmr <= MMR_MAX_VALID);
    const yAxis = calculateAdaptiveYAxis(data);

    chart.data.labels = data.map((_, i) => i + 1);
    chart.data.datasets[0].data = data.map(d => d.mmr);
    chart.data.datasets[0].pointBackgroundColor = data.map(d => d.result === "Win" ? "#00ff88" : "#ff4444");
    chart.data.datasets[0].pointBorderColor = data.map(d => d.result === "Win" ? "#00ff88" : "#ff4444");
    chart.options.scales.y.min = yAxis.min;
    chart.options.scales.y.max = yAxis.max;
    chart.update("none");
}

async function refresh() {
    const params = getParams();
    const result = await fetchReplays(params.games);
    renderGamesList(result.replays);
    updateStatsDisplay(result.replays);
    updateChart();
}

function applyLayout() {
    const params = getParams();
    const container = document.getElementById("widgetContainer");
    container.style.width = `${params.width}px`;
    container.style.height = `${params.height}px`;

    if (params.layout === "horizontal") {
        container.classList.add("horizontal");
    }

    // Set title from config
    fetch("/api/v1/config").then(r => r.json()).then(config => {
        document.getElementById("widgetTitle").textContent =
            `${config.player_name || "SC2"} STATS`;
    });
}

// Initialize
applyLayout();

(async () => {
    await loadDefaults();
    const params = getParams();
    const result = await fetchReplays(params.games);
    renderGamesList(result.replays);
    updateStatsDisplay(result.replays);
    await initChart();
    setInterval(refresh, REFRESH_INTERVAL_MS);
})();
