import logging
from functools import wraps
from flask import request, jsonify
from models import Preset, Settings
from services.generation import generate_from_preset
from services.job_queue import _job_queue_lock, _job_history

logger = logging.getLogger('gaze')


def register_routes(app):

    def require_api_key(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            api_key = request.headers.get('X-API-Key') or request.args.get('api_key')
            if not api_key:
                return jsonify({'error': 'Missing API key. Provide X-API-Key header or api_key query parameter.'}), 401
            settings = Settings.query.first()
            if not settings or not settings.api_key or api_key != settings.api_key:
                return jsonify({'error': 'Invalid API key.'}), 403
            return f(*args, **kwargs)
        return decorated

    @app.route('/api/v1/presets')
    @require_api_key
    def api_v1_presets():
        presets = Preset.query.order_by(Preset.name).all()
        return jsonify({
            'presets': [
                {
                    'preset_id': p.preset_id,
                    'slug': p.slug,
                    'name': p.name,
                    'has_cover': bool(p.image_path),
                }
                for p in presets
            ]
        })

    @app.route('/api/v1/generate/<path:preset_slug>', methods=['POST'])
    @require_api_key
    def api_v1_generate(preset_slug):
        preset = Preset.query.filter_by(slug=preset_slug).first()
        if not preset:
            return jsonify({'error': f'Preset not found: {preset_slug}'}), 404

        body = request.get_json(silent=True) or {}

        count = body.get('count', 1)
        try:
            count = int(count)
        except (TypeError, ValueError):
            return jsonify({'error': 'count must be an integer'}), 400
        if count < 1 or count > 20:
            return jsonify({'error': 'count must be between 1 and 20'}), 400

        seed = body.get('seed')
        if seed is not None:
            try:
                seed = int(seed)
            except (TypeError, ValueError):
                return jsonify({'error': 'seed must be an integer'}), 400

        width = body.get('width')
        height = body.get('height')
        if (width is None) != (height is None):
            return jsonify({'error': 'width and height must both be provided or both omitted'}), 400

        overrides = {
            'action': 'preview',
            'checkpoint': body.get('checkpoint', ''),
            'extra_positive': body.get('extra_positive', ''),
            'extra_negative': body.get('extra_negative', ''),
            'seed': seed,
            'width': int(width) if width else None,
            'height': int(height) if height else None,
        }

        try:
            jobs = []
            for _ in range(count):
                job = generate_from_preset(preset, overrides)
                jobs.append({'job_id': job['id'], 'status': 'queued'})
            return jsonify({'jobs': jobs}), 202
        except Exception as e:
            logger.exception("API generation error (preset %s): %s", preset_slug, e)
            return jsonify({'error': str(e)}), 500

    @app.route('/api/v1/job/<job_id>')
    @require_api_key
    def api_v1_job_status(job_id):
        with _job_queue_lock:
            job = _job_history.get(job_id)
            if not job:
                return jsonify({'error': 'Job not found'}), 404
            resp = {
                'id': job['id'],
                'label': job['label'],
                'status': job['status'],
                'error': job['error'],
            }
            if job.get('result'):
                resp['result'] = job['result']
            return jsonify(resp)
