"""
Flask Web Interface for Image Restyling
Single-file application with login and restyling form
"""

from flask import Flask, render_template_string, request, redirect, url_for, session, flash, jsonify, send_file
from datetime import timedelta, datetime
from functools import wraps
from werkzeug.middleware.proxy_fix import ProxyFix
from werkzeug.utils import secure_filename
import os
import zipfile
import csv
import subprocess
import json
import shutil
from io import BytesIO

app = Flask(__name__)
app.secret_key = 'darveys-image-restyling-secret-key-2024'
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)

# Middleware to handle URL prefix
class PrefixMiddleware(object):
    def __init__(self, app, prefix=''):
        self.app = app
        self.prefix = prefix

    def __call__(self, environ, start_response):
        if environ['PATH_INFO'].startswith(self.prefix):
            environ['PATH_INFO'] = environ['PATH_INFO'][len(self.prefix):]
            environ['SCRIPT_NAME'] = self.prefix
            return self.app(environ, start_response)
        else:
            start_response('404', [('Content-Type', 'text/plain')])
            return [b"Not Found"]

app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix='/image-restyling')

# File upload configuration
UPLOAD_FOLDER = '/var/www/html/Open-AI/images_in'
ALLOWED_EXTENSIONS = {'zip'}
MAX_FILE_SIZE = 20 * 1024 * 1024  # 20 MB
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = MAX_FILE_SIZE

# Hardcoded credentials
USERNAME = 'darveys'
PASSWORD = 'darveys@openai9876'

# Helper function to check allowed file
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

# Login required decorator
def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if 'logged_in' not in session:
            flash('Please login to access this page.', 'warning')
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    return decorated_function

# HTML Templates
LOGIN_TEMPLATE = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login - Image Restyling</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .login-container {
            background: white;
            padding: 40px;
            border-radius: 10px;
            box-shadow: 0 10px 40px rgba(0,0,0,0.2);
            width: 100%;
            max-width: 400px;
        }
        h1 {
            color: #333;
            margin-bottom: 10px;
            text-align: center;
        }
        .subtitle {
            color: #666;
            text-align: center;
            margin-bottom: 30px;
            font-size: 14px;
        }
        .form-group {
            margin-bottom: 20px;
        }
        label {
            display: block;
            margin-bottom: 5px;
            color: #333;
            font-weight: 500;
        }
        input[type="text"],
        input[type="password"] {
            width: 100%;
            padding: 12px;
            border: 2px solid #ddd;
            border-radius: 5px;
            font-size: 14px;
            transition: border-color 0.3s;
        }
        input[type="text"]:focus,
        input[type="password"]:focus {
            outline: none;
            border-color: #667eea;
        }
        .btn {
            width: 100%;
            padding: 12px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 16px;
            font-weight: 600;
            cursor: pointer;
            transition: transform 0.2s;
        }
        .btn:hover {
            transform: translateY(-2px);
        }
        .btn:active {
            transform: translateY(0);
        }
        .alert {
            padding: 12px;
            border-radius: 5px;
            margin-bottom: 20px;
            font-size: 14px;
        }
        .alert-danger {
            background: #fee;
            color: #c33;
            border: 1px solid #fcc;
        }
        .alert-success {
            background: #efe;
            color: #3c3;
            border: 1px solid #cfc;
        }
        .error {
            color: #c33;
            font-size: 12px;
            margin-top: 5px;
            display: none;
        }
    </style>
</head>
<body>
    <div class="login-container">
        <h1>Image Restyling</h1>
        <p class="subtitle">Login to access the restyling interface</p>

        {% with messages = get_flashed_messages(with_categories=true) %}
            {% if messages %}
                {% for category, message in messages %}
                    <div class="alert alert-{{ category }}">{{ message }}</div>
                {% endfor %}
            {% endif %}
        {% endwith %}

        <form method="POST" onsubmit="return validateLogin()">
            <div class="form-group">
                <label for="username">Username</label>
                <input type="text" id="username" name="username" required>
                <div class="error" id="username-error">Username is required</div>
            </div>
            <div class="form-group">
                <label for="password">Password</label>
                <input type="password" id="password" name="password" required>
                <div class="error" id="password-error">Password is required</div>
            </div>
            <button type="submit" class="btn">Login</button>
        </form>
    </div>

    <script>
        function validateLogin() {
            let isValid = true;

            const username = document.getElementById('username').value.trim();
            const password = document.getElementById('password').value;

            // Reset errors
            document.getElementById('username-error').style.display = 'none';
            document.getElementById('password-error').style.display = 'none';

            // Validate username
            if (username === '') {
                document.getElementById('username-error').style.display = 'block';
                isValid = false;
            }

            // Validate password
            if (password === '') {
                document.getElementById('password-error').style.display = 'block';
                isValid = false;
            }

            return isValid;
        }
    </script>
</body>
</html>
"""

DASHBOARD_TEMPLATE = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Restyling Dashboard</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #f5f5f5;
            min-height: 100vh;
        }
        .navbar {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 15px 30px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        .navbar h1 {
            font-size: 24px;
        }
        .logout-btn {
            padding: 8px 20px;
            background: rgba(255,255,255,0.2);
            color: white;
            border: 2px solid white;
            border-radius: 5px;
            cursor: pointer;
            text-decoration: none;
            font-weight: 600;
            transition: background 0.3s;
        }
        .logout-btn:hover {
            background: rgba(255,255,255,0.3);
        }
        .container {
            max-width: 800px;
            margin: 40px auto;
            padding: 0 20px;
        }
        .card {
            background: white;
            padding: 40px;
            border-radius: 10px;
            box-shadow: 0 5px 20px rgba(0,0,0,0.1);
        }
        h2 {
            color: #333;
            margin-bottom: 10px;
        }
        .subtitle {
            color: #666;
            margin-bottom: 30px;
            font-size: 14px;
        }
        .form-group {
            margin-bottom: 25px;
        }
        label {
            display: block;
            margin-bottom: 8px;
            color: #333;
            font-weight: 600;
            font-size: 14px;
        }
        textarea {
            width: 100%;
            padding: 12px;
            border: 2px solid #ddd;
            border-radius: 5px;
            font-size: 14px;
            font-family: inherit;
            resize: vertical;
            min-height: 120px;
            transition: border-color 0.3s;
        }
        textarea:focus {
            outline: none;
            border-color: #667eea;
        }
        select {
            width: 100%;
            padding: 12px;
            border: 2px solid #ddd;
            border-radius: 5px;
            font-size: 14px;
            cursor: pointer;
            background: white;
            transition: border-color 0.3s;
        }
        select:focus {
            outline: none;
            border-color: #667eea;
        }
        .button-group {
            display: flex;
            gap: 15px;
            margin-top: 30px;
        }
        .btn {
            flex: 1;
            padding: 12px;
            border: none;
            border-radius: 5px;
            font-size: 16px;
            font-weight: 600;
            cursor: pointer;
            transition: transform 0.2s;
        }
        .btn-primary {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }
        .btn-secondary {
            background: #6c757d;
            color: white;
        }
        .btn:hover {
            transform: translateY(-2px);
        }
        .btn:active {
            transform: translateY(0);
        }
        .error {
            color: #c33;
            font-size: 12px;
            margin-top: 5px;
            display: none;
        }
        .alert {
            padding: 12px;
            border-radius: 5px;
            margin-bottom: 20px;
            font-size: 14px;
        }
        .alert-success {
            background: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }
        .alert-danger {
            background: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }
        .alert-warning {
            background: #fff3cd;
            color: #856404;
            border: 1px solid #ffeaa7;
        }
        .char-count {
            font-size: 12px;
            color: #666;
            text-align: right;
            margin-top: 5px;
        }
        .file-upload-wrapper {
            position: relative;
            overflow: hidden;
            display: inline-block;
            width: 100%;
        }
        .file-upload-input {
            display: none;
        }
        .file-upload-label {
            display: block;
            padding: 12px;
            background: #f8f9fa;
            border: 2px dashed #ddd;
            border-radius: 5px;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s;
        }
        .file-upload-label:hover {
            border-color: #667eea;
            background: #f0f4ff;
        }
        .file-name-display {
            margin-top: 10px;
            font-size: 14px;
            color: #666;
        }
        .upload-progress {
            margin-top: 10px;
            display: none;
        }
        .progress-bar {
            width: 100%;
            height: 25px;
            background: #f0f0f0;
            border-radius: 5px;
            overflow: hidden;
        }
        .progress-bar-fill {
            height: 100%;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            transition: width 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-size: 12px;
            font-weight: 600;
        }
        .upload-info {
            margin-top: 10px;
            padding: 10px;
            background: #e8f5e9;
            border-radius: 5px;
            font-size: 13px;
            color: #2e7d32;
            display: none;
        }
        .btn-primary:disabled {
            background: #ccc;
            cursor: not-allowed;
            transform: none;
        }
    </style>
</head>
<body>
    <div class="navbar">
        <h1>Image Restyling Dashboard</h1>
        <a href="{{ url_for('logout') }}" class="logout-btn">Logout</a>
    </div>

    <div class="container">
        <div class="card">
            <h2>Restyle Images</h2>
            <p class="subtitle">Configure your image restyling parameters</p>

            {% with messages = get_flashed_messages(with_categories=true) %}
                {% if messages %}
                    {% for category, message in messages %}
                        <div class="alert alert-{{ category }}">{{ message }}</div>
                    {% endfor %}
                {% endif %}
            {% endwith %}

            <form method="POST" onsubmit="return validateForm()">
                <div class="form-group">
                    <label for="zipfile">Upload Images (ZIP file) *</label>
                    <div class="file-upload-wrapper">
                        <input type="file" id="zipfile" name="zipfile" class="file-upload-input" accept=".zip" onchange="handleFileSelect(event)">
                        <label for="zipfile" class="file-upload-label">
                            <span>📁 Click to select ZIP file (Max 20 MB)</span>
                        </label>
                    </div>
                    <div class="file-name-display" id="file-name-display"></div>
                    <div class="upload-progress" id="upload-progress">
                        <div class="progress-bar">
                            <div class="progress-bar-fill" id="progress-bar-fill" style="width: 0%">0%</div>
                        </div>
                    </div>
                    <div class="upload-info" id="upload-info"></div>
                    <div class="error" id="file-error"></div>
                </div>

                <div class="form-group">
                    <label for="prompt">Restyling Prompt *</label>
                    <textarea id="prompt" name="prompt" placeholder="Enter your restyling instructions here..." maxlength="1000" oninput="updateCharCount()"></textarea>
                    <div class="char-count"><span id="char-count">0</span>/1000 characters</div>
                    <div class="error" id="prompt-error">Prompt is required (minimum 10 characters)</div>
                </div>

                <div class="form-group">
                    <label for="quality">Quality *</label>
                    <select id="quality" name="quality">
                        <option value="">-- Select Quality --</option>
                        <option value="high">High</option>
                        <option value="medium">Medium</option>
                    </select>
                    <div class="error" id="quality-error">Please select a quality option</div>
                </div>

                <div class="button-group">
                    <button type="submit" id="submit-btn" class="btn btn-primary" disabled>Submit</button>
                    <button type="button" class="btn btn-secondary" onclick="resetForm()">Cancel</button>
                </div>
            </form>
        </div>

        <!-- Status Monitoring Section -->
        <div class="card" style="margin-top: 30px;">
            <h2>Job Status Monitor</h2>
            <p class="subtitle">Check the processing status of your recent jobs</p>

            <!-- Recent Jobs List -->
            <div id="jobs-list" style="margin-bottom: 20px;">
                <button type="button" class="btn btn-secondary" onclick="loadRecentJobs()" style="width: auto;">
                    🔄 Load Recent Jobs
                </button>
            </div>

            <!-- Selected Job Status -->
            <div id="status-container" style="display: none;">
                <div style="background: #f8f9fa; padding: 20px; border-radius: 5px; margin-top: 20px;">
                    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
                        <div>
                            <h3 style="margin: 0; color: #333;">Job: <span id="job-timestamp"></span></h3>
                            <p style="margin: 5px 0 0 0; color: #666; font-size: 14px;">Status: <span id="job-status" style="font-weight: 600;"></span></p>
                        </div>
                        <button type="button" class="btn btn-secondary" onclick="refreshStatus()" style="width: auto; padding: 8px 16px;">
                            🔄 Refresh
                        </button>
                    </div>

                    <!-- Progress Info -->
                    <div style="margin-bottom: 15px;">
                        <p style="margin: 0 0 10px 0; font-size: 16px; font-weight: 600; color: #333;">
                            Processed: <span id="progress-text">0 / 0</span> images
                        </p>
                        <div class="progress-bar">
                            <div class="progress-bar-fill" id="status-progress-bar" style="width: 0%">0%</div>
                        </div>
                    </div>

                    <!-- Status Message -->
                    <div style="padding: 10px; background: white; border-radius: 5px; margin-bottom: 15px;">
                        <p style="margin: 0; font-size: 13px; color: #666;" id="status-message">No message</p>
                        <p style="margin: 5px 0 0 0; font-size: 12px; color: #999;">Last updated: <span id="status-updated"></span></p>
                    </div>

                    <!-- Download Button -->
                    <div id="download-container" style="display: none;">
                        <a id="download-link" href="#" class="btn btn-primary" style="display: inline-block; text-decoration: none; width: auto;">
                            📥 Download Restyled Images
                        </a>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        let uploadedTimestamp = null;

        function handleFileSelect(event) {
            const file = event.target.files[0];
            const fileError = document.getElementById('file-error');
            const fileNameDisplay = document.getElementById('file-name-display');

            // Reset error
            fileError.style.display = 'none';
            fileError.textContent = '';

            if (!file) {
                return;
            }

            // Validate file type
            if (!file.name.toLowerCase().endsWith('.zip')) {
                fileError.textContent = 'Only ZIP files are allowed';
                fileError.style.display = 'block';
                event.target.value = '';
                return;
            }

            // Validate file size (20 MB)
            const maxSize = 20 * 1024 * 1024;
            if (file.size > maxSize) {
                fileError.textContent = 'File size must not exceed 20 MB';
                fileError.style.display = 'block';
                event.target.value = '';
                return;
            }

            // Display file name
            fileNameDisplay.textContent = `Selected: ${file.name} (${(file.size / 1024 / 1024).toFixed(2)} MB)`;

            // Upload file via AJAX
            uploadFile(file);
        }

        function uploadFile(file) {
            const formData = new FormData();
            formData.append('zipfile', file);

            const uploadProgress = document.getElementById('upload-progress');
            const progressBarFill = document.getElementById('progress-bar-fill');
            const uploadInfo = document.getElementById('upload-info');
            const fileError = document.getElementById('file-error');

            // Show progress bar
            uploadProgress.style.display = 'block';
            uploadInfo.style.display = 'none';

            const xhr = new XMLHttpRequest();

            // Upload progress
            xhr.upload.addEventListener('progress', function(e) {
                if (e.lengthComputable) {
                    const percentComplete = Math.round((e.loaded / e.total) * 100);
                    progressBarFill.style.width = percentComplete + '%';
                    progressBarFill.textContent = percentComplete + '%';
                }
            });

            // Upload complete
            xhr.addEventListener('load', function() {
                if (xhr.status === 200) {
                    const response = JSON.parse(xhr.responseText);
                    if (response.success) {
                        uploadedTimestamp = response.timestamp;
                        uploadInfo.innerHTML = `✓ ${response.message}<br>Extracted ${response.file_count} images`;
                        uploadInfo.style.display = 'block';

                        // Enable submit button
                        document.getElementById('submit-btn').disabled = false;
                    } else {
                        fileError.textContent = response.message;
                        fileError.style.display = 'block';
                        uploadProgress.style.display = 'none';
                    }
                } else {
                    const response = JSON.parse(xhr.responseText);
                    fileError.textContent = response.message || 'Upload failed';
                    fileError.style.display = 'block';
                    uploadProgress.style.display = 'none';
                }
            });

            // Upload error
            xhr.addEventListener('error', function() {
                fileError.textContent = 'Upload failed. Please try again.';
                fileError.style.display = 'block';
                uploadProgress.style.display = 'none';
            });

            // Send request
            xhr.open('POST', '{{ url_for("upload_images") }}', true);
            xhr.send(formData);
        }

        function updateCharCount() {
            const prompt = document.getElementById('prompt').value;
            document.getElementById('char-count').textContent = prompt.length;
        }

        function validateForm() {
            let isValid = true;

            const prompt = document.getElementById('prompt').value.trim();
            const quality = document.getElementById('quality').value;

            // Reset errors
            document.getElementById('prompt-error').style.display = 'none';
            document.getElementById('quality-error').style.display = 'none';

            // Validate prompt
            if (prompt === '' || prompt.length < 10) {
                document.getElementById('prompt-error').style.display = 'block';
                isValid = false;
            }

            // Validate quality
            if (quality === '') {
                document.getElementById('quality-error').style.display = 'block';
                isValid = false;
            }

            return isValid;
        }

        function resetForm() {
            if (confirm('Are you sure you want to clear the form?')) {
                // Reset file upload
                document.getElementById('zipfile').value = '';
                document.getElementById('file-name-display').textContent = '';
                document.getElementById('upload-progress').style.display = 'none';
                document.getElementById('upload-info').style.display = 'none';
                document.getElementById('file-error').style.display = 'none';
                uploadedTimestamp = null;

                // Reset form fields
                document.getElementById('prompt').value = '';
                document.getElementById('quality').value = '';
                updateCharCount();

                // Disable submit button
                document.getElementById('submit-btn').disabled = true;

                // Hide any error messages
                document.getElementById('prompt-error').style.display = 'none';
                document.getElementById('quality-error').style.display = 'none';
            }
        }

        // Status monitoring variables
        let currentJobTimestamp = null;
        let statusCheckInterval = null;

        // Load recent jobs
        function loadRecentJobs() {
            fetch('{{ url_for("get_recent_jobs") }}')
                .then(response => response.json())
                .then(data => {
                    if (data.success && data.jobs.length > 0) {
                        const jobsList = document.getElementById('jobs-list');
                        let html = '<div style="margin-bottom: 15px;"><strong>Recent Jobs:</strong></div>';
                        html += '<div style="display: grid; gap: 10px;">';

                        data.jobs.forEach(job => {
                            const statusColor = job.status === 'completed' ? '#2e7d32' :
                                              job.status === 'processing' ? '#1976d2' :
                                              job.status === 'failed' ? '#d32f2f' : '#666';

                            html += `
                                <div style="padding: 12px; background: #f8f9fa; border-radius: 5px; cursor: pointer; border-left: 4px solid ${statusColor};"
                                     onclick="checkJobStatus('${job.timestamp}')">
                                    <strong>Job: ${job.timestamp}</strong><br>
                                    <span style="color: ${statusColor}; font-weight: 600;">Status: ${job.status.toUpperCase()}</span><br>
                                    <small style="color: #666;">Submitted: ${job.submitted_at}</small>
                                </div>
                            `;
                        });

                        html += '</div>';
                        jobsList.innerHTML = html;
                    } else {
                        document.getElementById('jobs-list').innerHTML = '<p style="color: #666;">No jobs found. Submit a job first!</p>';
                    }
                })
                .catch(error => {
                    console.error('Error loading jobs:', error);
                    alert('Error loading jobs');
                });
        }

        // Check specific job status
        function checkJobStatus(timestamp) {
            currentJobTimestamp = timestamp;

            fetch(`{{ url_for("check_status", timestamp="TIMESTAMP") }}`.replace('TIMESTAMP', timestamp))
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        displayStatus(data, timestamp);

                        // Auto-refresh if processing
                        if (data.status === 'processing') {
                            if (!statusCheckInterval) {
                                statusCheckInterval = setInterval(() => refreshStatus(), 5000);
                            }
                        } else {
                            clearInterval(statusCheckInterval);
                            statusCheckInterval = null;
                        }
                    } else {
                        alert('Job not found: ' + data.message);
                    }
                })
                .catch(error => {
                    console.error('Error checking status:', error);
                    alert('Error checking status');
                });
        }

        // Display status information
        function displayStatus(data, timestamp) {
            document.getElementById('status-container').style.display = 'block';
            document.getElementById('job-timestamp').textContent = timestamp;

            // Status text with color
            const statusSpan = document.getElementById('job-status');
            statusSpan.textContent = data.status.toUpperCase();

            if (data.status === 'completed') {
                statusSpan.style.color = '#2e7d32';
            } else if (data.status === 'processing') {
                statusSpan.style.color = '#1976d2';
            } else if (data.status === 'failed') {
                statusSpan.style.color = '#d32f2f';
            } else {
                statusSpan.style.color = '#666';
            }

            // Progress
            document.getElementById('progress-text').textContent = `${data.processed} / ${data.total}`;
            document.getElementById('status-progress-bar').style.width = data.progress + '%';
            document.getElementById('status-progress-bar').textContent = data.progress + '%';

            // Message
            document.getElementById('status-message').textContent = data.message || 'No message';
            document.getElementById('status-updated').textContent = data.updated_at || 'N/A';

            // Download button
            if (data.status === 'completed') {
                const downloadContainer = document.getElementById('download-container');
                const downloadLink = document.getElementById('download-link');
                downloadLink.href = `{{ url_for("download_images", timestamp="TIMESTAMP") }}`.replace('TIMESTAMP', timestamp);
                downloadContainer.style.display = 'block';
            } else {
                document.getElementById('download-container').style.display = 'none';
            }
        }

        // Refresh current job status
        function refreshStatus() {
            if (currentJobTimestamp) {
                checkJobStatus(currentJobTimestamp);
            }
        }

        // Auto-load jobs on page load
        window.addEventListener('load', function() {
            // Load jobs after a short delay
            setTimeout(loadRecentJobs, 500);
        });
    </script>
</body>
</html>
"""

@app.route('/')
def index():
    if 'logged_in' in session:
        return redirect(url_for('dashboard'))
    return redirect(url_for('login'))

@app.route('/login', methods=['GET', 'POST'])
def login():
    if 'logged_in' in session:
        return redirect(url_for('dashboard'))

    if request.method == 'POST':
        username = request.form.get('username', '').strip()
        password = request.form.get('password', '')

        # Server-side validation
        if not username or not password:
            flash('Username and password are required.', 'danger')
            return render_template_string(LOGIN_TEMPLATE)

        # Check credentials
        if username == USERNAME and password == PASSWORD:
            session.permanent = True
            session['logged_in'] = True
            session['username'] = username
            flash('Login successful! Welcome back.', 'success')
            return redirect(url_for('dashboard'))
        else:
            flash('Invalid username or password. Please try again.', 'danger')
            return render_template_string(LOGIN_TEMPLATE)

    return render_template_string(LOGIN_TEMPLATE)

@app.route('/dashboard', methods=['GET', 'POST'])
@login_required
def dashboard():
    if request.method == 'POST':
        prompt = request.form.get('prompt', '').strip()
        quality = request.form.get('quality', '').strip()

        # Server-side validation
        errors = []

        # Check if images were uploaded
        if 'upload_timestamp' not in session:
            errors.append('Please upload images first before submitting.')

        if not prompt or len(prompt) < 10:
            errors.append('Prompt must be at least 10 characters long.')

        if len(prompt) > 1000:
            errors.append('Prompt must not exceed 1000 characters.')

        if quality not in ['high', 'medium']:
            errors.append('Please select a valid quality option.')

        if errors:
            for error in errors:
                flash(error, 'danger')
            return render_template_string(DASHBOARD_TEMPLATE)

        # Get timestamp from session
        timestamp = session['upload_timestamp']

        # Setup paths
        csv_path = os.path.join(app.config['UPLOAD_FOLDER'], timestamp, f'catalog-{timestamp}.csv')
        jobs_dir = '/var/www/html/Open-AI/jobs'
        os.makedirs(jobs_dir, exist_ok=True)

        # Save job data
        job_data = {
            'timestamp': timestamp,
            'prompt': prompt,
            'quality': quality,
            'csv_path': csv_path,
            'status': 'pending',
            'submitted_at': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }

        job_file = os.path.join(jobs_dir, f'job_{timestamp}.json')
        with open(job_file, 'w') as f:
            json.dump(job_data, f, indent=2)

        # Trigger background processing
        try:
            script_path = '/var/www/html/Open-AI/restyle_batch_prod.py'
            subprocess.Popen([
                'python3',
                script_path,
                '--prompt', prompt,
                '--quality', quality,
                '--csv', csv_path,
                '--timestamp', timestamp
            ], cwd='/var/www/html/Open-AI')

            flash('Your request has been submitted and processing will begin shortly.', 'success')

            # Clear upload timestamp from session
            session.pop('upload_timestamp', None)

        except Exception as e:
            flash(f'Error starting background job: {str(e)}', 'danger')

        return redirect(url_for('dashboard'))

    return render_template_string(DASHBOARD_TEMPLATE)

@app.route('/upload-images', methods=['POST'])
@login_required
def upload_images():
    """Handle ZIP file upload and processing"""
    try:
        # Check if file is present
        if 'zipfile' not in request.files:
            return jsonify({'success': False, 'message': 'No file uploaded'}), 400

        file = request.files['zipfile']

        # Check if file is selected
        if file.filename == '':
            return jsonify({'success': False, 'message': 'No file selected'}), 400

        # Validate file type
        if not allowed_file(file.filename):
            return jsonify({'success': False, 'message': 'Only ZIP files are allowed'}), 400

        # Generate timestamp for folder name
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        timestamp_folder = os.path.join(app.config['UPLOAD_FOLDER'], timestamp)

        # Create timestamp folder
        os.makedirs(timestamp_folder, exist_ok=True)

        # Save uploaded ZIP file temporarily
        filename = secure_filename(file.filename)
        temp_zip_path = os.path.join(timestamp_folder, filename)
        file.save(temp_zip_path)

        # Extract images from ZIP
        image_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp'}
        extracted_files = []

        with zipfile.ZipFile(temp_zip_path, 'r') as zip_ref:
            for file_info in zip_ref.filelist:
                # Skip directories
                if file_info.is_dir():
                    continue

                # Get file extension
                file_ext = os.path.splitext(file_info.filename)[1].lower()

                # Only extract image files
                if file_ext in image_extensions:
                    # Get just the filename (flatten structure)
                    base_filename = os.path.basename(file_info.filename)

                    # Extract directly to timestamp folder
                    with zip_ref.open(file_info) as source:
                        target_path = os.path.join(timestamp_folder, base_filename)
                        with open(target_path, 'wb') as target:
                            target.write(source.read())

                    extracted_files.append(base_filename)

        # Remove temporary ZIP file
        os.remove(temp_zip_path)

        # Generate CSV file
        csv_filename = f'catalog-{timestamp}.csv'
        csv_path = os.path.join(timestamp_folder, csv_filename)

        with open(csv_path, 'w', newline='') as csvfile:
            writer = csv.writer(csvfile)
            writer.writerow(['filename'])  # Header
            for filename in sorted(extracted_files):
                writer.writerow([filename])

        # Store timestamp in session for form submission
        session['upload_timestamp'] = timestamp

        return jsonify({
            'success': True,
            'message': 'Images uploaded successfully',
            'timestamp': timestamp,
            'file_count': len(extracted_files)
        }), 200

    except zipfile.BadZipFile:
        return jsonify({'success': False, 'message': 'Invalid ZIP file'}), 400
    except Exception as e:
        return jsonify({'success': False, 'message': f'Error processing file: {str(e)}'}), 500

@app.route('/check-status/<timestamp>', methods=['GET'])
@login_required
def check_status(timestamp):
    """Check job processing status"""
    try:
        jobs_dir = '/var/www/html/Open-AI/jobs'
        job_file = os.path.join(jobs_dir, f'job_{timestamp}.json')

        if not os.path.exists(job_file):
            return jsonify({
                'success': False,
                'message': 'Job not found'
            }), 404

        # Read job status
        with open(job_file, 'r') as f:
            job_data = json.load(f)

        # Calculate progress percentage
        processed = job_data.get('processed', 0)
        total = job_data.get('total', 0)
        progress = int((processed / total * 100)) if total > 0 else 0

        return jsonify({
            'success': True,
            'status': job_data.get('status', 'unknown'),
            'processed': processed,
            'total': total,
            'progress': progress,
            'message': job_data.get('message', ''),
            'updated_at': job_data.get('updated_at', '')
        }), 200

    except Exception as e:
        return jsonify({
            'success': False,
            'message': f'Error checking status: {str(e)}'
        }), 500

@app.route('/download/<timestamp>', methods=['GET'])
@login_required
def download_images(timestamp):
    """Download processed images as ZIP"""
    try:
        output_dir = os.path.join('/var/www/html/Open-AI/images_out', timestamp)

        if not os.path.exists(output_dir):
            flash('No processed images found for this job.', 'danger')
            return redirect(url_for('dashboard'))

        # Check if directory has files
        files = [f for f in os.listdir(output_dir) if os.path.isfile(os.path.join(output_dir, f))]
        if not files:
            flash('No processed images found for this job.', 'danger')
            return redirect(url_for('dashboard'))

        # Create ZIP file in memory
        memory_file = BytesIO()
        with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for filename in files:
                file_path = os.path.join(output_dir, filename)
                zipf.write(file_path, filename)

        memory_file.seek(0)

        return send_file(
            memory_file,
            mimetype='application/zip',
            as_attachment=True,
            download_name=f'restyled-images-{timestamp}.zip'
        )

    except Exception as e:
        flash(f'Error creating download: {str(e)}', 'danger')
        return redirect(url_for('dashboard'))

@app.route('/get-recent-jobs', methods=['GET'])
@login_required
def get_recent_jobs():
    """Get list of recent jobs for status checking"""
    try:
        jobs_dir = '/var/www/html/Open-AI/jobs'
        if not os.path.exists(jobs_dir):
            return jsonify({'success': True, 'jobs': []}), 200

        job_files = [f for f in os.listdir(jobs_dir) if f.startswith('job_') and f.endswith('.json')]
        jobs = []

        for job_file in sorted(job_files, reverse=True)[:10]:  # Last 10 jobs
            try:
                with open(os.path.join(jobs_dir, job_file), 'r') as f:
                    job_data = json.load(f)
                    timestamp = job_file.replace('job_', '').replace('.json', '')
                    jobs.append({
                        'timestamp': timestamp,
                        'status': job_data.get('status', 'unknown'),
                        'submitted_at': job_data.get('submitted_at', '')
                    })
            except:
                continue

        return jsonify({'success': True, 'jobs': jobs}), 200

    except Exception as e:
        return jsonify({'success': False, 'message': str(e)}), 500

@app.route('/logout')
def logout():
    session.clear()
    flash('You have been logged out successfully.', 'success')
    return redirect(url_for('login'))

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
