"""Service Order Blueprint: workshop Kanban management.

Prefix: /pos/api/service-orders
"""

from flask import Blueprint, g, jsonify, request
from middleware import require_auth
from services.service_order_engine import (
    add_item,
    add_labor,
    assign_mechanic,
    convert_to_sale,
    create_service_catalog_item,
    create_service_order,
    delete_service_catalog_item,
    get_kanban_summary,
    get_service_order,
    list_service_catalog,
    list_service_orders,
    release_item,
    remove_item,
    remove_labor,
    reserve_item,
    update_item,
    update_labor,
    update_service_catalog_item,
    update_service_order,
    update_status,
)
from tenant_db import get_tenant_conn

service_order_bp = Blueprint('service_orders', __name__, url_prefix='/pos/api/service-orders')


@service_order_bp.route('', methods=['GET'])
@require_auth('workshop.view')
def list_orders():
    status = request.args.get('status')
    priority = request.args.get('priority')
    customer_id = request.args.get('customer_id', type=int)
    employee_id = request.args.get('employee_id', type=int)
    delivery_method = request.args.get('delivery_method')
    is_direct = request.args.get('is_direct', type=lambda v: v.lower() == 'true') if 'is_direct' in request.args else None
    q = request.args.get('q')
    page = int(request.args.get('page', 1))
    per_page = min(int(request.args.get('per_page', 50)), 200)

    conn = get_tenant_conn(g.tenant_id)
    try:
        result = list_service_orders(
            conn, status=status, branch_id=g.branch_id,
            customer_id=customer_id, priority=priority,
            employee_id=employee_id, delivery_method=delivery_method,
            is_direct=is_direct, q=q, page=page, per_page=per_page
        )
        return jsonify(result)
    finally:
        conn.close()


@service_order_bp.route('/from-pos', methods=['POST'])
@require_auth('pos.sell')
def create_order_from_pos():
    """Create a service order directly from the POS cart (quotation)."""
    data = request.get_json() or {}
    items = data.get('items', [])
    estimated_cost = sum(
        (it.get('unit_price') or 0) * (it.get('quantity') or 1)
        for it in items
    )
    conn = get_tenant_conn(g.tenant_id)
    try:
        result = create_service_order(conn, {
            'tenant_id': g.tenant_id,
            'branch_id': data.get('branch_id', g.branch_id),
            'customer_id': data.get('customer_id'),
            'vehicle_id': data.get('vehicle_id'),
            'priority': data.get('priority', 'normal'),
            'reception_notes': data.get('reception_notes'),
            'estimated_cost': estimated_cost or None,
            'estimated_completion': data.get('estimated_completion'),
            'employee_id': data.get('employee_id'),
            'mileage_in': data.get('mileage_in'),
            'created_by': getattr(g, 'employee_id', None),
            'delivery_method': data.get('delivery_method'),
            'courier_id': data.get('courier_id'),
            'is_direct': data.get('is_direct', False),
        })
        so_id = result['service_order_id']
        for item in items:
            add_item(conn, so_id, item)
        order = get_service_order(conn, so_id)
        return jsonify(order), 201
    finally:
        conn.close()


@service_order_bp.route('', methods=['POST'])
@require_auth('workshop.edit')
def create_order():
    data = request.get_json() or {}
    conn = get_tenant_conn(g.tenant_id)
    try:
        result = create_service_order(conn, {
            'tenant_id': g.tenant_id,
            'branch_id': data.get('branch_id', g.branch_id),
            'customer_id': data.get('customer_id'),
            'vehicle_id': data.get('vehicle_id'),
            'priority': data.get('priority', 'normal'),
            'reception_notes': data.get('reception_notes'),
            'estimated_cost': data.get('estimated_cost'),
            'estimated_completion': data.get('estimated_completion'),
            'employee_id': data.get('employee_id'),
            'mileage_in': data.get('mileage_in'),
            'fuel_level': data.get('fuel_level'),
            'created_by': getattr(g, 'employee_id', None),
            'delivery_method': data.get('delivery_method'),
            'courier_id': data.get('courier_id'),
            'is_direct': data.get('is_direct', False),
        })
        return jsonify(result), 201
    finally:
        conn.close()


@service_order_bp.route('/<int:so_id>', methods=['GET'])
@require_auth('workshop.view')
def get_order(so_id):
    conn = get_tenant_conn(g.tenant_id)
    try:
        order = get_service_order(conn, so_id)
        if not order:
            return jsonify({'error': 'Service order not found'}), 404
        return jsonify(order)
    finally:
        conn.close()


@service_order_bp.route('/<int:so_id>', methods=['PUT'])
@require_auth('workshop.edit')
def update_order(so_id):
    data = request.get_json() or {}
    conn = get_tenant_conn(g.tenant_id)
    try:
        ok = update_service_order(conn, so_id, data)
        if not ok:
            return jsonify({'error': 'No fields to update'}), 400
        return jsonify({'message': 'Service order updated'})
    finally:
        conn.close()


@service_order_bp.route('/<int:so_id>/status', methods=['PUT'])
@require_auth('workshop.edit')
def change_status(so_id):
    data = request.get_json() or {}
    new_status = data.get('status')
    if not new_status:
        return jsonify({'error': 'status is required'}), 400
    conn = get_tenant_conn(g.tenant_id)
    try:
        result = update_status(
            conn, so_id, new_status,
            changed_by=getattr(g, 'employee_id', None),
            notes=data.get('notes'),
        )
        return jsonify(result)
    except ValueError as e:
        return jsonify({'error': str(e)}), 400
    finally:
        conn.close()


# ─── Items (Parts) ─────────────────────────────

@service_order_bp.route('/<int:so_id>/items', methods=['POST'])
@require_auth('workshop.edit')
def add_order_item(so_id):
    data = request.get_json() or {}
    conn = get_tenant_conn(g.tenant_id)
    try:
        item_id = add_item(conn, so_id, data)
        return jsonify({'id': item_id, 'message': 'Item added'}), 201
    finally:
        conn.close()


@service_order_bp.route('/items/<int:item_id>', methods=['PUT'])
@require_auth('workshop.edit')
def update_order_item(item_id):
    data = request.get_json() or {}
    conn = get_tenant_conn(g.tenant_id)
    try:
        ok = update_item(conn, item_id, data)
        if not ok:
            return jsonify({'error': 'No fields to update'}), 400
        return jsonify({'message': 'Item updated'})
    finally:
        conn.close()


@service_order_bp.route('/items/<int:item_id>', methods=['DELETE'])
@require_auth('workshop.edit')
def delete_order_item(item_id):
    conn = get_tenant_conn(g.tenant_id)
    try:
        remove_item(conn, item_id)
        return jsonify({'message': 'Item removed'})
    finally:
        conn.close()


# ─── Labor ─────────────────────────────

@service_order_bp.route('/<int:so_id>/labor', methods=['POST'])
@require_auth('workshop.edit')
def add_order_labor(so_id):
    data = request.get_json() or {}
    if not data.get('description'):
        return jsonify({'error': 'description is required'}), 400
    conn = get_tenant_conn(g.tenant_id)
    try:
        labor_id = add_labor(conn, so_id, data)
        return jsonify({'id': labor_id, 'message': 'Labor added'}), 201
    finally:
        conn.close()


@service_order_bp.route('/labor/<int:labor_id>', methods=['PUT'])
@require_auth('workshop.edit')
def update_order_labor(labor_id):
    data = request.get_json() or {}
    conn = get_tenant_conn(g.tenant_id)
    try:
        ok = update_labor(conn, labor_id, data)
        if not ok:
            return jsonify({'error': 'No fields to update'}), 400
        return jsonify({'message': 'Labor updated'})
    finally:
        conn.close()


@service_order_bp.route('/labor/<int:labor_id>', methods=['DELETE'])
@require_auth('workshop.edit')
def delete_order_labor(labor_id):
    conn = get_tenant_conn(g.tenant_id)
    try:
        remove_labor(conn, labor_id)
        return jsonify({'message': 'Labor removed'})
    finally:
        conn.close()


# ─── Kanban Summary ─────────────────────────────

@service_order_bp.route('/kanban/summary', methods=['GET'])
@require_auth('workshop.view')
def kanban_summary():
    conn = get_tenant_conn(g.tenant_id)
    try:
        summary = get_kanban_summary(conn, branch_id=g.branch_id)
        return jsonify(summary)
    finally:
        conn.close()


# ─── Inventory reservation ────────────────────────


@service_order_bp.route('/<int:so_id>/items/<int:item_id>/reserve', methods=['POST'])
@require_auth('workshop.edit')
def reserve_order_item(so_id, item_id):
    """Reserve inventory for a service order item."""
    conn = get_tenant_conn(g.tenant_id)
    try:
        result = reserve_item(conn, item_id, branch_id=g.branch_id, employee_id=g.employee_id)
        return jsonify(result)
    except ValueError as e:
        return jsonify({'error': str(e)}), 400
    finally:
        conn.close()


@service_order_bp.route('/<int:so_id>/items/<int:item_id>/release', methods=['POST'])
@require_auth('workshop.edit')
def release_order_item(so_id, item_id):
    """Release a previous inventory reservation."""
    conn = get_tenant_conn(g.tenant_id)
    try:
        result = release_item(conn, item_id, employee_id=g.employee_id)
        return jsonify(result)
    except ValueError as e:
        return jsonify({'error': str(e)}), 400
    finally:
        conn.close()


# ─── Convert to sale ──────────────────────────────


@service_order_bp.route('/<int:so_id>/convert-to-sale', methods=['POST'])
@require_auth('pos.sell')
def convert_order_to_sale(so_id):
    """Convert a service order into a POS sale.

    Body: {
        payment_method: 'efectivo' | 'transferencia' | 'tarjeta' | 'mixto',
        sale_type: 'cash' | 'credit' | 'mixed',
        register_id: int (optional),
        amount_paid: float (optional),
        payment_details: [...] (optional),
        notes: str (optional)
    }
    """
    data = request.get_json() or {}
    sale_payload = {
        'payment_method': data.get('payment_method', 'efectivo'),
        'sale_type': data.get('sale_type', 'cash'),
        'register_id': data.get('register_id'),
        'amount_paid': data.get('amount_paid'),
        'payment_details': data.get('payment_details', []),
        'notes': data.get('notes'),
    }

    conn = get_tenant_conn(g.tenant_id)
    try:
        result = convert_to_sale(
            conn, so_id, sale_payload, employee_id=g.employee_id
        )
        return jsonify(result), 201
    except ValueError as e:
        return jsonify({'error': str(e)}), 400
    finally:
        conn.close()


# ─── Mechanic assignment ──────────────────────────


@service_order_bp.route('/<int:so_id>/assign-mechanic', methods=['PUT'])
@require_auth('workshop.edit')
def assign_mechanic_endpoint(so_id):
    """Assign a mechanic/technician to a service order."""
    data = request.get_json() or {}
    employee_id = data.get('employee_id')
    if not employee_id:
        return jsonify({'error': 'employee_id is required'}), 400

    conn = get_tenant_conn(g.tenant_id)
    try:
        result = assign_mechanic(conn, so_id, employee_id)
        return jsonify(result)
    except ValueError as e:
        return jsonify({'error': str(e)}), 400
    finally:
        conn.close()


# ─── Service catalog (reusable labor) ─────────────


@service_order_bp.route('/service-catalog', methods=['GET'])
@require_auth('workshop.view')
def list_catalog():
    """List reusable labor/service concepts."""
    active_only = request.args.get('active_only', 'true').lower() != 'false'
    conn = get_tenant_conn(g.tenant_id)
    try:
        items = list_service_catalog(conn, active_only=active_only)
        return jsonify({'data': items})
    finally:
        conn.close()


@service_order_bp.route('/service-catalog', methods=['POST'])
@require_auth('workshop.edit')
def create_catalog_item():
    """Create a reusable labor concept."""
    data = request.get_json() or {}
    if not data.get('name'):
        return jsonify({'error': 'name is required'}), 400

    conn = get_tenant_conn(g.tenant_id)
    try:
        result = create_service_catalog_item(conn, g.tenant_id, data)
        return jsonify(result), 201
    finally:
        conn.close()


@service_order_bp.route('/service-catalog/<int:item_id>', methods=['PUT'])
@require_auth('workshop.edit')
def update_catalog_item(item_id):
    """Update a reusable labor concept."""
    data = request.get_json() or {}
    conn = get_tenant_conn(g.tenant_id)
    try:
        ok = update_service_catalog_item(conn, item_id, data)
        if not ok:
            return jsonify({'error': 'No fields to update'}), 400
        return jsonify({'message': 'Catalog item updated'})
    finally:
        conn.close()


@service_order_bp.route('/service-catalog/<int:item_id>', methods=['DELETE'])
@require_auth('workshop.edit')
def delete_catalog_item(item_id):
    """Soft-delete a reusable labor concept."""
    conn = get_tenant_conn(g.tenant_id)
    try:
        delete_service_catalog_item(conn, item_id)
        return jsonify({'message': 'Catalog item deactivated'})
    finally:
        conn.close()


# ─── Thermal printing ─────────────────────────────


@service_order_bp.route('/<int:so_id>/print', methods=['POST'])
@require_auth('workshop.view')
def print_service_order_ticket(so_id):
    """Generate a printable ticket for a service order.

    Body (optional): {printer_type: 'escpos_raw' | 'browser', width: 58 | 80}
      - escpos_raw: returns raw ESC/POS bytes (application/octet-stream)
      - browser: returns the data dict as JSON for browser-side rendering
    """
    from flask import Response
    from services.thermal_printer import generate_service_order_ticket

    body = request.get_json(silent=True) or {}
    printer_type = body.get('printer_type', 'escpos_raw')
    width = int(body.get('width', 80))

    conn = get_tenant_conn(g.tenant_id)
    cur = conn.cursor()

    order = get_service_order(conn, so_id)
    if not order:
        cur.close()
        conn.close()
        return jsonify({'error': 'Service order not found'}), 404

    # Fetch business info from config
    business_info = {'name': 'NEXUS AUTOPARTS', 'rfc': '', 'address': ''}
    try:
        cur.execute(
            "SELECT key, value FROM config WHERE key IN ('business_name','rfc','address')"
        )
        for rw in cur.fetchall():
            if rw[0] == 'business_name':
                business_info['name'] = rw[1]
            else:
                business_info[rw[0]] = rw[1]
    except Exception:
        pass

    cur.close()
    conn.close()

    if printer_type == 'browser':
        return jsonify(order)

    raw = generate_service_order_ticket(order, business_info, width=width)
    return Response(
        raw,
        mimetype='application/octet-stream',
        headers={
            'Content-Disposition': f'attachment; filename=orden_{order.get("order_number", so_id)}.bin'
        },
    )
