import json

from flask import Blueprint, Response, current_app, jsonify, request, stream_with_context
from flask_login import login_required

from app import db as database
from app.services import sync as sync_svc
from app.services import eracuni as eracuni_svc
from app.labels import product_label as product_label_svc
from app.services import printer as printer_svc

products_bp = Blueprint('products', __name__)


@products_bp.route('/products/list')
@login_required
def products_list():
    db_path = current_app.config['DATABASE_PATH']
    rows = database.get_all_products(db_path)
    return jsonify(products=rows)


@products_bp.route('/products/<code>/detail')
@login_required
def product_detail(code):
    """Return DB record + raw e-računi API response for a single product."""
    db_path = current_app.config['DATABASE_PATH']
    db_row = database.get_product(code, db_path) or {}
    try:
        raw = eracuni_svc.get_product_raw(code)
    except Exception as exc:
        raw = {'error': str(exc)}
    return jsonify(db=db_row, raw=raw)


@products_bp.route('/products/<code>/print-label', methods=['POST'])
@login_required
def product_print_label(code):
    """Print a product label. JSON body: {label_type, language, sealed_amount, count}."""
    db_path = current_app.config['DATABASE_PATH']
    product = database.get_product(code, db_path)
    if not product:
        return jsonify(ok=False, error=f'Product {code} not found.')

    data = request.get_json(silent=True) or {}
    label_type   = data.get('label_type', 'product')
    language     = data.get('language', 'hr')
    sealed_amount = data.get('sealed_amount') or None
    count        = max(1, int(data.get('count', 1)))

    kwargs = dict(
        sku=product.get('productCode', code),
        name_hr=product.get('name', ''),
        name_en=product.get('englishName', ''),
        name_de=product.get('germanName', ''),
        location=product.get('defaultWarehouseLocation', ''),
        language=language,
    )

    try:
        for _ in range(count):
            if label_type == 'product':
                img = product_label_svc.generate_product(
                    barcode=product.get('barcode', ''), **kwargs)
            elif label_type == 'product_sealed':
                if not sealed_amount:
                    return jsonify(ok=False, error='Sealed amount is required.')
                img = product_label_svc.generate_product_sealed(
                    sealed_amount=int(sealed_amount), **kwargs)
            elif label_type == 'digikey':
                img = product_label_svc.generate_digikey(
                    barcode=product.get('barcode', ''), **kwargs)
            else:
                return jsonify(ok=False, error=f'Unknown label type: {label_type}')
            printer_svc.print_label(
                img, printer='small',
                meta={'order': code, 'label_type': label_type})
        return jsonify(ok=True)
    except ValueError as e:
        return jsonify(ok=False, error=str(e))
    except Exception as e:
        return jsonify(ok=False, error=str(e))


@products_bp.route('/products/sync')
@login_required
def products_sync():
    """SSE stream: sync products from e-računi."""
    db_path = current_app.config['DATABASE_PATH']
    app = current_app._get_current_object()

    def generate():
        with app.app_context():
            try:
                for msg in sync_svc.sync_products(db_path):
                    yield f"data: {json.dumps({'message': msg})}\n\n"
            except Exception as exc:
                yield f"data: {json.dumps({'message': f'Error: {exc}', 'error': True})}\n\n"
            yield f"data: {json.dumps({'done': True})}\n\n"

    return Response(
        stream_with_context(generate()),
        mimetype='text/event-stream',
        headers={'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no'},
    )
