{% extends "base.html" %}

{% block title %}Upload Algorithm - MHA Flow{% endblock %}

{% block content %}
<div class="row justify-content-center">
    <div class="col-md-10">
        <div class="card shadow">
            <div class="card-header bg-warning">
                <h5><i class="fas fa-upload"></i> Upload Custom Algorithm</h5>
            </div>
            <div class="card-body">
                <div class="alert alert-info">
                    <h6><i class="fas fa-info-circle"></i> How it works:</h6>
                    <ol class="mb-0">
                        <li><strong>Upload</strong> your algorithm file (.py)</li>
                        <li><strong>Auto-mapping</strong> — your custom variable names are automatically mapped to standard parameters</li>
                        <li><strong>Use locally</strong> — algorithm is available on your system immediately</li>
                        <li><strong>Review</strong> — submitted to GitHub for admin review</li>
                        <li><strong>Credit</strong> — when approved for release, you get full credit as contributor</li>
                    </ol>
                </div>
                
                <div class="alert alert-light border">
                    <h6><i class="fas fa-code"></i> Requirements:</h6>
                    <ul class="mb-0">
                        <li>Python file (.py) with a class (preferably inheriting from <code>BaseOptimizer</code>)</li>
                        <li>Must implement <code>optimize()</code> or <code>_optimize()</code> method</li>
                        <li>Variables can use <strong>any names</strong> — the system auto-maps them (e.g., <code>N</code> → <code>population_size</code>)</li>
                    </ul>
                </div>
                
                <form id="uploadForm" enctype="multipart/form-data">
                    <div class="mb-3">
                        <label class="form-label fw-bold">Algorithm File <span class="text-danger">*</span></label>
                        <input type="file" class="form-control" id="algorithmFile" accept=".py" required>
                        <small class="form-text text-muted">Upload a Python file containing your algorithm</small>
                    </div>
                    
                    <div class="row">
                        <div class="col-md-6 mb-3">
                            <label class="form-label fw-bold">Category</label>
                            <select class="form-select" id="category">
                                <option value="Custom">Custom</option>
                                <option value="Swarm Intelligence">Swarm Intelligence</option>
                                <option value="Evolutionary">Evolutionary</option>
                                <option value="Bio-Inspired">Bio-Inspired</option>
                                <option value="Physics-Based">Physics-Based</option>
                                <option value="Hybrid">Hybrid</option>
                                <option value="Math-Based">Math-Based</option>
                                <option value="Human-Based">Human-Based</option>
                            </select>
                        </div>
                        <div class="col-md-6 mb-3">
                            <label class="form-label fw-bold">Description</label>
                            <textarea class="form-control" id="description" rows="3" 
                                placeholder="Describe your algorithm (inspiration, how it works, best for...)"></textarea>
                        </div>
                    </div>
                    
                    <!-- Parameter Mapping Section (shown after validation) -->
                    <div id="paramMappingSection" class="d-none">
                        <div class="card bg-light mb-3">
                            <div class="card-header">
                                <h6 class="mb-0"><i class="fas fa-exchange-alt"></i> Parameter Mapping</h6>
                                <small class="text-muted">Your variables have been auto-mapped. Adjust if needed.</small>
                            </div>
                            <div class="card-body">
                                <div id="paramMappingRows"></div>
                                <div id="unmappedParams" class="mt-2"></div>
                            </div>
                        </div>
                    </div>
                    
                    <button type="submit" class="btn btn-warning w-100" id="uploadBtn">
                        <i class="fas fa-upload"></i> Upload & Integrate Algorithm
                    </button>
                </form>
                
                <div id="uploadResult" class="mt-3 d-none"></div>
            </div>
        </div>
        
        <!-- My Custom Algorithms -->
        <div class="card shadow mt-4">
            <div class="card-header bg-primary text-white">
                <h5><i class="fas fa-list"></i> My Custom Algorithms</h5>
            </div>
            <div class="card-body">
                <div id="myAlgorithms">
                    <p class="text-muted">Loading your algorithms...</p>
                </div>
            </div>
        </div>
        
        <!-- Contributor Credits -->
        <div class="card shadow mt-4">
            <div class="card-header bg-success text-white">
                <h5><i class="fas fa-trophy"></i> Contributor Credits</h5>
            </div>
            <div class="card-body">
                <div id="contributorCredits">
                    <p class="text-muted">Loading contributor credits...</p>
                </div>
            </div>
        </div>
        
        <div class="card shadow mt-4">
            <div class="card-header bg-secondary text-white">
                <h5><i class="fas fa-code"></i> Example Template</h5>
            </div>
            <div class="card-body">
                <pre class="bg-light p-3 rounded"><code>from mha_toolbox.base import BaseOptimizer
import numpy as np

class MyCustomAlgorithm(BaseOptimizer):
    """Custom Optimization Algorithm"""
    
    def __init__(self, population_size=30, max_iterations=100, **kwargs):
        super().__init__(population_size, max_iterations, **kwargs)
        self.algorithm_name = "My Custom Algorithm"
    
    def _optimize(self, objective_function, X=None, y=None, **kwargs):
        # Get dimensions and bounds
        if X is not None:
            dimension = X.shape[1]
            lb, ub = 0.0, 1.0
        else:
            dimension = kwargs.get('dimensions', 10)
            lb = kwargs.get('lower_bound', -100.0)
            ub = kwargs.get('upper_bound', 100.0)
        
        # Initialize population
        population = np.random.uniform(lb, ub, (self.population_size_, dimension))
        fitness = np.array([objective_function(ind) for ind in population])
        
        # Find best solution
        best_idx = np.argmin(fitness)
        best_position = population[best_idx].copy()
        best_fitness = fitness[best_idx]
        
        # Tracking
        global_fitness = [best_fitness]
        local_fitness = [fitness.copy()]
        local_positions = [population.copy()]
        
        # Main optimization loop
        for iteration in range(self.max_iterations_):
            for i in range(self.population_size_):
                # Your optimization logic here
                # Update population[i]
                population[i] = np.clip(population[i], lb, ub)
                fitness[i] = objective_function(population[i])
                
                if fitness[i] < best_fitness:
                    best_position = population[i].copy()
                    best_fitness = fitness[i]
            
            global_fitness.append(best_fitness)
            local_fitness.append(fitness.copy())
            local_positions.append(population.copy())
        
        return best_position, best_fitness, global_fitness, local_fitness, local_positions</code></pre>
                
                <h6 class="mt-3">Or with custom variable names (auto-mapped!):</h6>
                <pre class="bg-light p-3 rounded"><code>import numpy as np

class MySwarmOptimizer:
    """Custom algorithm with non-standard parameter names"""
    
    def __init__(self, N=30, T=100, D=10, lb=-100, ub=100):
        # N = population_size (auto-mapped)
        # T = max_iterations (auto-mapped)
        # D = dimensions (auto-mapped)
        self.N = N
        self.T = T
        self.D = D
        self.lb = lb
        self.ub = ub
    
    def optimize(self, fitness_func, **kwargs):
        population = np.random.uniform(self.lb, self.ub, (self.N, self.D))
        fitness = np.array([fitness_func(x) for x in population])
        
        best_idx = np.argmin(fitness)
        best_pos = population[best_idx].copy()
        best_fit = fitness[best_idx]
        history = [best_fit]
        
        for t in range(self.T):
            for i in range(self.N):
                # Your logic here
                new_pos = population[i] + np.random.randn(self.D) * 0.1
                new_pos = np.clip(new_pos, self.lb, self.ub)
                new_fit = fitness_func(new_pos)
                if new_fit < fitness[i]:
                    population[i] = new_pos
                    fitness[i] = new_fit
                    if new_fit < best_fit:
                        best_pos = new_pos.copy()
                        best_fit = new_fit
            history.append(best_fit)
        
        return best_pos, best_fit, history, None, None</code></pre>
                <button class="btn btn-sm btn-outline-secondary" onclick="copyTemplate()">
                    <i class="fas fa-copy"></i> Copy Template
                </button>
            </div>
        </div>
    </div>
</div>

<script>
// Load user's custom algorithms on page load
document.addEventListener('DOMContentLoaded', function() {
    loadMyAlgorithms();
    loadContributorCredits();
});

function loadMyAlgorithms() {
    fetch('/api/my-custom-algorithms')
        .then(r => r.json())
        .then(data => {
            const container = document.getElementById('myAlgorithms');
            if (!data.algorithms || data.algorithms.length === 0) {
                container.innerHTML = '<p class="text-muted">No custom algorithms uploaded yet.</p>';
                return;
            }
            let html = '<div class="table-responsive"><table class="table table-sm">';
            html += '<thead><tr><th>Algorithm</th><th>Category</th><th>Status</th><th>Uses</th><th>Uploaded</th></tr></thead><tbody>';
            data.algorithms.forEach(algo => {
                const statusBadge = {
                    'pending': '<span class="badge bg-warning">Pending Review</span>',
                    'approved': '<span class="badge bg-success">Approved</span>',
                    'rejected': '<span class="badge bg-danger">Rejected</span>'
                }[algo.status] || '<span class="badge bg-secondary">Unknown</span>';
                
                const localBadge = algo.local_algo_id ? 
                    ' <span class="badge bg-info">Local</span>' : '';
                
                html += `<tr>
                    <td><strong>${algo.algorithm_name}</strong>${localBadge}</td>
                    <td>${algo.category || 'Custom'}</td>
                    <td>${statusBadge}</td>
                    <td>${algo.usage_count || 0}</td>
                    <td>${algo.upload_date ? new Date(algo.upload_date).toLocaleDateString() : '-'}</td>
                </tr>`;
            });
            html += '</tbody></table></div>';
            container.innerHTML = html;
        })
        .catch(() => {
            document.getElementById('myAlgorithms').innerHTML = 
                '<p class="text-muted">Could not load algorithms.</p>';
        });
}

function loadContributorCredits() {
    fetch('/api/contributors')
        .then(r => r.json())
        .then(data => {
            const container = document.getElementById('contributorCredits');
            if (!data.contributors || data.contributors.length === 0) {
                container.innerHTML = '<p class="text-muted">No approved contributions yet. Be the first!</p>';
                return;
            }
            let html = '<div class="table-responsive"><table class="table table-sm">';
            html += '<thead><tr><th>Algorithm</th><th>Contributor</th><th>Category</th><th>Version</th></tr></thead><tbody>';
            data.contributors.forEach(c => {
                html += `<tr>
                    <td><strong>${c.algorithm_name}</strong></td>
                    <td><i class="fas fa-user"></i> ${c.contributor}</td>
                    <td>${c.category || 'Custom'}</td>
                    <td>${c.version_included || 'Next release'}</td>
                </tr>`;
            });
            html += '</tbody></table></div>';
            container.innerHTML = html;
        })
        .catch(() => {
            document.getElementById('contributorCredits').innerHTML = 
                '<p class="text-muted">Could not load credits.</p>';
        });
}

document.getElementById('uploadForm').addEventListener('submit', async function(e) {
    e.preventDefault();
    
    const fileInput = document.getElementById('algorithmFile');
    const description = document.getElementById('description').value;
    const category = document.getElementById('category').value;
    
    if (!fileInput.files.length) {
        alert('Please select a file');
        return;
    }
    
    const formData = new FormData();
    formData.append('file', fileInput.files[0]);
    formData.append('description', description);
    formData.append('category', category);
    
    // Include any user-adjusted parameter mappings
    const mappingInputs = document.querySelectorAll('.param-mapping-select');
    if (mappingInputs.length > 0) {
        const mappings = {};
        mappingInputs.forEach(input => {
            const param = input.dataset.param;
            const value = input.value;
            if (param && value) {
                mappings[param] = {'suggested': value, 'confirmed': true};
            }
        });
        formData.append('parameter_mapping', JSON.stringify(mappings));
    }
    
    document.getElementById('uploadBtn').disabled = true;
    document.getElementById('uploadBtn').innerHTML = '<i class="fas fa-spinner fa-spin"></i> Processing...';
    
    try {
        const response = await fetch('/api/upload-algorithm', {
            method: 'POST',
            body: formData
        });
        
        const result = await response.json();
        const resultDiv = document.getElementById('uploadResult');
        
        if (response.ok) {
            // Show parameter mapping if available
            if (result.parameter_mapping && result.parameter_mapping.mapped) {
                showParameterMapping(result.parameter_mapping);
            }
            
            let creditHtml = '';
            if (result.contributor_credit) {
                creditHtml = `<div class="alert alert-success mt-2">
                    <i class="fas fa-trophy"></i> <strong>Credit:</strong> ${result.contributor_credit.message}
                </div>`;
            }
            
            let usageHtml = '';
            if (result.usage_example) {
                usageHtml = `<div class="mt-2">
                    <strong>Use it now:</strong>
                    <pre class="bg-light p-2 rounded mt-1"><code>${result.usage_example}</code></pre>
                </div>`;
            }
            
            let githubHtml = '';
            if (result.github && result.github.pr_url) {
                githubHtml = `<p class="mb-1"><i class="fab fa-github"></i> 
                    <a href="${result.github.pr_url}" target="_blank">View Pull Request</a></p>`;
            }
            
            resultDiv.className = 'alert alert-success mt-3';
            resultDiv.innerHTML = `
                <h6><i class="fas fa-check-circle"></i> Upload Successful!</h6>
                <p class="mb-1"><strong>Algorithm:</strong> ${result.algorithm_name}</p>
                <p class="mb-1"><strong>Status:</strong> Available locally 
                    ${result.local_available ? '<span class="badge bg-success">Ready</span>' : ''} 
                    | Pending review for release</p>
                ${githubHtml}
                ${creditHtml}
                ${usageHtml}
            `;
            fileInput.value = '';
            document.getElementById('description').value = '';
            
            // Reload algorithms list
            loadMyAlgorithms();
        } else {
            resultDiv.className = 'alert alert-danger mt-3';
            resultDiv.innerHTML = `
                <h6><i class="fas fa-exclamation-triangle"></i> Upload Failed</h6>
                <p class="mb-0">${result.error}</p>
                ${result.details ? '<pre class="mt-2">' + JSON.stringify(result.details, null, 2) + '</pre>' : ''}
            `;
        }
        
        resultDiv.classList.remove('d-none');
        
    } catch (error) {
        alert('Upload failed: ' + error.message);
    } finally {
        document.getElementById('uploadBtn').disabled = false;
        document.getElementById('uploadBtn').innerHTML = '<i class="fas fa-upload"></i> Upload & Integrate Algorithm';
    }
});

function showParameterMapping(mapping) {
    const section = document.getElementById('paramMappingSection');
    const rowsDiv = document.getElementById('paramMappingRows');
    const unmappedDiv = document.getElementById('unmappedParams');
    
    let html = '';
    const standardParams = ['population_size', 'max_iterations', 'dimensions', 
                           'lower_bound', 'upper_bound', 'objective_function', 'algorithm_specific'];
    
    if (mapping.mapped) {
        for (const [param, info] of Object.entries(mapping.mapped)) {
            const suggested = typeof info === 'object' ? info.suggested : info;
            const confidence = typeof info === 'object' ? info.confidence : 'high';
            const badgeClass = confidence === 'high' ? 'bg-success' : 
                             confidence === 'medium' ? 'bg-warning' : 'bg-secondary';
            
            html += `<div class="row mb-2 align-items-center">
                <div class="col-4"><code>${param}</code> <span class="badge ${badgeClass}">${confidence}</span></div>
                <div class="col-1 text-center"><i class="fas fa-arrow-right"></i></div>
                <div class="col-5">
                    <select class="form-select form-select-sm param-mapping-select" data-param="${param}">
                        ${standardParams.map(sp => `<option value="${sp}" ${sp === suggested ? 'selected' : ''}>${sp}</option>`).join('')}
                    </select>
                </div>
            </div>`;
        }
    }
    
    rowsDiv.innerHTML = html;
    
    if (mapping.unmapped && mapping.unmapped.length > 0) {
        unmappedDiv.innerHTML = `<div class="alert alert-warning py-2">
            <small><i class="fas fa-info-circle"></i> Algorithm-specific parameters (kept as custom hyperparameters): 
            <strong>${mapping.unmapped.join(', ')}</strong></small>
        </div>`;
    }
    
    if (html || (mapping.unmapped && mapping.unmapped.length > 0)) {
        section.classList.remove('d-none');
    }
}

function copyTemplate() {
    const template = document.querySelector('pre code').textContent;
    navigator.clipboard.writeText(template).then(() => {
        alert('Template copied to clipboard!');
    });
}
</script>
{% endblock %}
