{% extends "base.html" %}

{% block title %}Market - AISBF Dashboard{% endblock %}

{% block content %}
<h2 style="margin-bottom: 20px;"><i class="fas fa-store" style="color: var(--color-link);"></i> Market</h2>
<p style="color: var(--color-muted); margin-bottom: 20px;">Browse shared providers and models, review pricing and reputation, and import market resources into your account.</p>

<div style="background: var(--bg-panel); border: 1px solid var(--color-border); border-radius: 10px; padding: 16px; margin-bottom: 18px;">
    <datalist id="market-search-suggestions"></datalist>
    <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-bottom: 12px;">
        <input id="market-search" list="market-search-suggestions" placeholder="Search name, type, capability" autocomplete="off" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
        <select id="market-source-type" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
            <option value="">All resource types</option>
            <option value="provider">Provider</option>
            <option value="model">Model</option>
            <option value="rotation">Rotation</option>
            <option value="autoselect">Autoselect</option>
        </select>
        <input id="market-model-type" placeholder="Model type / family" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
        <input id="market-model-name" placeholder="Model name" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
        <input id="market-size" placeholder="Size / params" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
        <label style="display:flex; align-items:center; gap:8px; color:var(--color-text);"><input type="checkbox" id="market-online-only"> Online only</label>
        <select id="market-sort" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
            <option value="newest">Newest</option>
            <option value="price_asc">Price low to high</option>
            <option value="price_desc">Price high to low</option>
            <option value="upvotes">Best rated</option>
            <option value="performance">Best performance</option>
            <option value="requests">Most used</option>
            <option value="revenue">Top grossing</option>
        </select>
    </div>
    <div style="display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin-bottom:10px;">
        <div id="capabilities-filter" style="display:flex; flex-wrap:wrap; gap:8px; align-items:center; flex:1;">
            <span style="font-size:13px; color:var(--color-muted); margin-right:4px;">Capabilities:</span>
            <button type="button" onclick="setAllCaps(true)" style="padding:3px 10px; border-radius:999px; border:1px solid var(--color-border); background:var(--bg-page); color:var(--color-muted); font-size:12px; cursor:pointer;">all</button>
            <button type="button" onclick="setAllCaps(false)" style="padding:3px 10px; border-radius:999px; border:1px solid var(--color-border); background:var(--bg-page); color:var(--color-muted); font-size:12px; cursor:pointer;">none</button>
        </div>
        <button class="btn btn-secondary" onclick="reloadMarket()" style="white-space:nowrap;">Search</button>
    </div>
</div>

<div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 16px;" id="market-grid"></div>

<div style="margin-top: 30px; background: var(--bg-panel); border: 1px solid var(--color-border); border-radius: 10px; padding: 18px;">
    <h3 style="margin-top:0;">Publish one of your resources</h3>
    <div style="display:grid; grid-template-columns: 1fr 1fr; gap: 12px;">
        <select id="publish-source-type" onchange="onPublishTypeChange()" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
            <option value="provider">Provider</option>
            <option value="model">Model</option>
            <option value="rotation">Rotation</option>
            <option value="autoselect">Autoselect</option>
        </select>
        <select id="publish-source-select" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
        </select>
        <input id="publish-title" placeholder="Listing title" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
        <select id="publish-provider-select" onchange="onPublishProviderChange()" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text); display:none;">
        </select>
        <input id="publish-price-tokens" type="number" step="0.0001" min="0" placeholder="Price / 1M tokens" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
        <input id="publish-price-requests" type="number" step="0.0001" min="0" placeholder="Price / 1000 requests" style="padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);">
    </div>
    <textarea id="publish-description" placeholder="Description" style="margin-top:12px; width:100%; min-height:84px; padding:10px; border:1px solid var(--color-border); border-radius:6px; background:var(--bg-page); color:var(--color-text);"></textarea>
    <button class="btn" style="margin-top:12px;" onclick="publishListing()">Publish Listing</button>
</div>
{% endblock %}

{% block extra_js %}
<script>
const BASE_PATH = {{ (request.scope.get('root_path', '') or '') | tojson }};
const listings = {{ market_listings_json | safe }};
const currencySymbol = {{ currency_symbol | tojson }};
const marketSettings = {{ market_settings_json | safe }};
const userResources = {{ user_resources_json | safe }};
const allCapabilities = {{ all_capabilities_json | safe }};

function voteSummary(votes, target) {
    const item = (votes || {})[target] || {upvotes:0, downvotes:0, score:0};
    return `+${item.upvotes} / -${item.downvotes} (score ${item.score})`;
}

function formatVramMb(value) {
    if (value == null || value === '') return '?';
    const mb = Number(value);
    if (!Number.isFinite(mb)) return '?';
    if (mb >= 1024) return `${(mb / 1024).toFixed(1)} GB`;
    return `${Math.round(mb)} MB`;
}

function renderListingHardware(hw) {
    if (!hw) return '';
    const gpus = Array.isArray(hw.gpus) ? hw.gpus : [];
    const gpuName = gpus[0]?.name || null;
    const total = hw.total_vram_mb;
    const free = hw.available_vram_mb;
    if (!gpuName && total == null) return '';
    const parts = [];
    if (gpuName) {
        const short = gpuName.replace(/^NVIDIA\s+(GeForce\s+)?/i, '').replace(/^AMD\s+(Radeon\s+RX\s+)?/i, '');
        parts.push(short);
    }
    if (total != null) parts.push(`${formatVramMb(free)} / ${formatVramMb(total)} VRAM`);
    return `<div style="font-size:12px;margin-bottom:8px;display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:999px;background:rgba(99,102,241,0.1);border:1px solid rgba(99,102,241,0.3);color:#a5b4fc;">${parts.join(' · ')}</div>`;
}

function renderMarket() {
    const root = document.getElementById('market-grid');
    root.innerHTML = '';
    listings.forEach(listing => {
        const el = document.createElement('div');
        el.style.cssText = 'background: var(--bg-panel); border: 1px solid var(--color-border); border-radius: 12px; padding: 16px; box-shadow: 0 10px 30px rgba(0,0,0,0.08);';
        el.innerHTML = `
            <div style="display:flex; justify-content:space-between; gap:10px; align-items:flex-start;">
                <div>
                    <h3 style="margin:0 0 6px 0;">${listing.title}</h3>
                    <div style="color: var(--color-muted); font-size: 13px;">by ${listing.owner_display_name || listing.owner_username}</div>
                </div>
                <div style="text-align:right; font-size:13px; color: var(--color-link);">
                    <div>${currencySymbol}${Number(listing.price_per_million_tokens || 0).toFixed(4)} / 1M tok</div>
                    <div>${currencySymbol}${Number(listing.price_per_1000_requests || 0).toFixed(4)} / 1k req</div>
                </div>
            </div>
            <p style="color: var(--color-text); margin: 12px 0;">${listing.description || ''}</p>
            <div style="font-size:12px; color: var(--color-muted); margin-bottom: 10px;">Provider: ${listing.provider_id || '-'} ${listing.model_id ? ` | Model: ${listing.model_id}` : ''} ${listing.model_type_label ? ` | Type: ${listing.model_type_label}` : ''} ${listing.size_label ? ` | Size: ${listing.size_label}` : ''}</div>
            <div style="font-size:12px; color: var(--color-muted); margin-bottom: 10px;">Status: ${listing.online ? 'online' : 'offline'}${(listing.capabilities || []).length ? ` | Capabilities: ${(listing.capabilities || []).join(', ')}` : ''}</div>
            ${renderListingHardware(listing.hardware)}
            <div style="display:grid; grid-template-columns:1fr 1fr; gap:6px; font-size:12px; margin-bottom:12px;">
                <div>Listing votes: ${voteSummary(listing.votes, 'listing')}</div>
                <div>User votes: ${voteSummary(listing.votes, 'user')}</div>
                <div>Provider votes: ${voteSummary(listing.votes, 'provider')}</div>
                <div>Model votes: ${voteSummary(listing.votes, 'model')}</div>
            </div>
            <div style="display:grid; grid-template-columns:1fr 1fr; gap:6px; font-size:12px; margin-bottom:12px; color: var(--color-muted);">
                <div>Usage events: ${(listing.stats || {}).usage_events || 0}</div>
                <div>Total requests: ${(listing.stats || {}).total_requests || 0}</div>
                <div>Total tokens: ${(listing.stats || {}).total_tokens || 0}</div>
                <div>Avg tokens/req: ${Number((listing.stats || {}).avg_tokens_per_request || 0).toFixed(1)}</div>
                <div>Gross: ${currencySymbol}${Number((listing.stats || {}).gross_revenue || 0).toFixed(2)}</div>
                <div>Seller rev: ${currencySymbol}${Number((listing.stats || {}).provider_revenue || 0).toFixed(2)}</div>
                <div>Analytics req: ${(listing.analytics || {}).request_count || 0}</div>
                <div>Avg latency: ${Number((listing.analytics || {}).avg_latency_ms || 0).toFixed(1)} ms</div>
                <div>Error rate: ${(Number((listing.analytics || {}).error_rate || 0) * 100).toFixed(1)}%</div>
                <div>Analytics tokens: ${(listing.analytics || {}).total_tokens || 0}</div>
            </div>
            <div style="display:flex; flex-wrap:wrap; gap:8px;">
                <button class="btn btn-secondary" onclick="importListing(${listing.id})">Import</button>
                <button class="btn btn-secondary" onclick="voteListing(${listing.id}, 'listing', 1)">Upvote</button>
                <button class="btn btn-secondary" onclick="voteListing(${listing.id}, 'listing', -1)">Downvote</button>
            </div>
        `;
        root.appendChild(el);
    });
}

async function importListing(id) {
    const response = await fetch(`${BASE_PATH}/api/market/listings/${id}/import`, {method:'POST', headers:{'Content-Type':'application/json'}});
    const result = await response.json();
    if (!response.ok) {
        alert(result.error || 'Import failed');
        return;
    }
    alert(`Imported as ${result.imported_config_type}: ${result.imported_config_id}`);
}

async function voteListing(id, targetType, vote) {
    const response = await fetch(`${BASE_PATH}/api/market/listings/${id}/vote`, {
        method:'POST',
        headers:{'Content-Type':'application/json'},
        body: JSON.stringify({target_type: targetType, vote})
    });
    const result = await response.json();
    if (!response.ok) {
        alert(result.error || 'Vote failed');
        return;
    }
    const listing = listings.find(item => item.id === id);
    if (listing) listing.votes = result.votes;
    renderMarket();
}

function _populateSelect(selectEl, items, valueFn, labelFn, placeholder) {
    selectEl.innerHTML = '';
    if (placeholder) {
        const opt = document.createElement('option');
        opt.value = '';
        opt.textContent = placeholder;
        selectEl.appendChild(opt);
    }
    for (const item of items) {
        const opt = document.createElement('option');
        opt.value = valueFn(item);
        opt.textContent = labelFn(item);
        selectEl.appendChild(opt);
    }
}

function onPublishTypeChange() {
    const type = document.getElementById('publish-source-type').value;
    const sourceSelect = document.getElementById('publish-source-select');
    const providerSelect = document.getElementById('publish-provider-select');

    providerSelect.style.display = 'none';

    if (type === 'provider') {
        _populateSelect(sourceSelect, userResources.providers, i => i.id, i => i.label, '— select provider —');
    } else if (type === 'rotation') {
        _populateSelect(sourceSelect, userResources.rotations, i => i.id, i => i.label, '— select rotation —');
    } else if (type === 'autoselect') {
        _populateSelect(sourceSelect, userResources.autoselects, i => i.id, i => i.label, '— select autoselect —');
    } else if (type === 'model') {
        _populateSelect(providerSelect, userResources.providers, i => i.id, i => i.label, '— select provider —');
        providerSelect.style.display = '';
        onPublishProviderChange();
    }
}

function onPublishProviderChange() {
    const pid = document.getElementById('publish-provider-select').value;
    const sourceSelect = document.getElementById('publish-source-select');
    const models = (userResources.models_by_provider[pid] || []);
    _populateSelect(sourceSelect, models, m => m.name, m => m.name, models.length ? '— select model —' : '(no models configured)');
}

async function publishListing() {
    const sourceType = document.getElementById('publish-source-type').value;
    const sourceId = document.getElementById('publish-source-select').value.trim();
    const providerId = document.getElementById('publish-provider-select').value.trim();
    const body = {
        source_type: sourceType,
        source_id: sourceId,
        provider_id: sourceType === 'model' ? providerId : undefined,
        model_id: sourceType === 'model' ? sourceId : undefined,
        title: document.getElementById('publish-title').value.trim(),
        description: document.getElementById('publish-description').value.trim(),
        price_per_million_tokens: parseFloat(document.getElementById('publish-price-tokens').value || '0'),
        price_per_1000_requests: parseFloat(document.getElementById('publish-price-requests').value || '0')
    };
    const response = await fetch(`${BASE_PATH}/api/market/listings`, {
        method:'POST',
        headers:{'Content-Type':'application/json'},
        body: JSON.stringify(body)
    });
    const result = await response.json();
    if (!response.ok) {
        alert(result.error || 'Publish failed');
        return;
    }
    window.location.reload();
}

function updateSearchSuggestions() {
    const suggestions = new Set();
    for (const l of listings) {
        if (l.title) suggestions.add(l.title);
        const meta = l.metadata || {};
        const mn = l.model_id || meta.model_name;
        if (mn) suggestions.add(mn);
        const pt = meta.provider_type || meta.type;
        if (pt) suggestions.add(pt);
    }
    const dl = document.getElementById('market-search-suggestions');
    dl.innerHTML = '';
    for (const s of suggestions) {
        const opt = document.createElement('option');
        opt.value = s;
        dl.appendChild(opt);
    }
}

function _setPillActive(btn, active) {
    btn.dataset.active = active ? '1' : '0';
    btn.style.background = active ? 'var(--color-link)' : 'var(--bg-page)';
    btn.style.color = active ? '#fff' : 'var(--color-text)';
    btn.style.borderColor = active ? 'var(--color-link)' : 'var(--color-border)';
}

function setAllCaps(active) {
    document.querySelectorAll('#capabilities-filter button[data-cap]').forEach(btn => _setPillActive(btn, active));
    reloadMarket();
}

function initCapabilityPills() {
    const container = document.getElementById('capabilities-filter');
    while (container.children.length > 1) container.removeChild(container.lastChild);
    for (const cap of allCapabilities) {
        const btn = document.createElement('button');
        btn.type = 'button';
        btn.dataset.cap = cap;
        btn.textContent = cap.replace(/_/g, ' ');
        btn.style.cssText = 'padding:4px 12px; border-radius:999px; border:1px solid var(--color-border); background:var(--bg-page); color:var(--color-text); font-size:13px; cursor:pointer; transition: background 0.15s, color 0.15s;';
        _setPillActive(btn, true);
        btn.addEventListener('click', () => {
            _setPillActive(btn, btn.dataset.active !== '1');
            reloadMarket();
        });
        container.appendChild(btn);
    }
}

let _searchDebounce = null;
document.addEventListener('DOMContentLoaded', () => {
    const searchEl = document.getElementById('market-search');
    searchEl.addEventListener('input', () => {
        if (searchEl.value.length === 0 || searchEl.value.length >= 2) {
            clearTimeout(_searchDebounce);
            _searchDebounce = setTimeout(reloadMarket, 300);
        }
    });
    for (const id of ['market-source-type', 'market-sort', 'market-online-only', 'market-model-type', 'market-model-name', 'market-size']) {
        const el = document.getElementById(id);
        if (el) el.addEventListener('change', reloadMarket);
    }
    for (const id of ['market-model-type', 'market-model-name', 'market-size']) {
        const el = document.getElementById(id);
        if (el) el.addEventListener('input', () => {
            clearTimeout(_searchDebounce);
            _searchDebounce = setTimeout(reloadMarket, 300);
        });
    }
});

renderMarket();
updateSearchSuggestions();
initCapabilityPills();
onPublishTypeChange();

async function reloadMarket() {
    const params = new URLSearchParams();
    const q = document.getElementById('market-search').value.trim();
    const sourceType = document.getElementById('market-source-type').value;
    const activePills = [...document.querySelectorAll('#capabilities-filter button[data-active="1"]')];
    const selectedCaps = activePills.length === allCapabilities.length ? [] : activePills.map(b => b.dataset.cap);
    const modelType = document.getElementById('market-model-type').value.trim();
    const modelName = document.getElementById('market-model-name').value.trim();
    const size = document.getElementById('market-size').value.trim();
    const onlineOnly = document.getElementById('market-online-only').checked;
    const sortBy = document.getElementById('market-sort').value;
    if (q) params.set('q', q);
    if (sourceType) params.set('source_type', sourceType);
    if (selectedCaps.length) params.set('capabilities', selectedCaps.join(','));
    if (modelType) params.set('model_type', modelType);
    if (modelName) params.set('model_name', modelName);
    if (size) params.set('size', size);
    if (onlineOnly) params.set('online_only', '1');
    if (sortBy) params.set('sort_by', sortBy);
    const response = await fetch(`${BASE_PATH}/api/market/listings?${params.toString()}`);
    const result = await response.json();
    if (!response.ok) {
        alert(result.error || 'Failed to load market');
        return;
    }
    listings.length = 0;
    for (const listing of result.listings || []) listings.push(listing);
    renderMarket();
    updateSearchSuggestions();
}
</script>
{% endblock %}
