"""
Nexus Marketplace B2B — REST endpoints (Phase 1).

Routes:
  Bodegas
    GET  /pos/api/marketplace/bodegas              list verified bodegas
    GET  /pos/api/marketplace/bodegas/<id>         bodega detail

  Inventory
    POST /pos/api/marketplace/inventory/upload     bulk CSV upload (seller)
    GET  /pos/api/marketplace/inventory/search     browse (text/brand/city filters)
    GET  /pos/api/marketplace/inventory/part/<id>  bodegas stocking this part

  Purchase Orders
    POST /pos/api/marketplace/orders               create draft
    GET  /pos/api/marketplace/orders/mine          buyer's PO list
    GET  /pos/api/marketplace/orders/inbox         seller's incoming PO list
    GET  /pos/api/marketplace/orders/<id>          full detail
    POST /pos/api/marketplace/orders/<id>/transition   state change

NOTE: this replaces an earlier stub that referenced now-unused tables
(marketplace_orders, marketplace_order_items, tenants.is_seller flag).
The Phase 1 schema uses bodegas + purchase_orders + purchase_order_items.
"""

from functools import wraps
from flask import Blueprint, request, jsonify, g

from middleware import require_auth
from tenant_db import get_tenant_conn, get_master_conn
from services import marketplace_service as mkt


marketplace_bp = Blueprint('marketplace', __name__, url_prefix='/pos/api/marketplace')


# ─── Role loader + checker ────────────────────────────────────────────────

def _load_marketplace_profile():
    """Fetch the caller's marketplace_role + bodega_id from the tenant DB
    and attach to flask.g. Call AFTER @require_auth. Idempotent."""
    if hasattr(g, 'marketplace_loaded'):
        return
    g.marketplace_role = 'buyer'
    g.marketplace_bodega_id = None
    try:
        conn = get_tenant_conn(g.tenant_id)
        cur = conn.cursor()
        cur.execute(
            "SELECT marketplace_role, bodega_id FROM employees WHERE id = %s",
            (g.employee_id,),
        )
        row = cur.fetchone()
        if row:
            g.marketplace_role = row[0] or 'buyer'
            g.marketplace_bodega_id = row[1]
        cur.close()
        conn.close()
    except Exception as e:
        print(f'[marketplace] failed to load role: {e}')
    g.marketplace_loaded = True


def require_marketplace_role(*allowed_roles):
    """Decorator: only allow users whose marketplace_role is in the allowed list.
    Must be applied AFTER @require_auth()."""
    def decorator(f):
        @wraps(f)
        def wrapped(*args, **kwargs):
            _load_marketplace_profile()
            if g.marketplace_role not in allowed_roles:
                return jsonify({
                    'error': f'Marketplace role {g.marketplace_role} cannot access this endpoint',
                    'required': list(allowed_roles),
                }), 403
            return f(*args, **kwargs)
        return wrapped
    return decorator


def _with_master(f):
    """Open a master connection, run f(master_conn), always close."""
    conn = get_master_conn()
    try:
        return f(conn)
    finally:
        conn.close()


# ═══════════════════════════════════════════════════════════════════════════
# BODEGAS
# ═══════════════════════════════════════════════════════════════════════════

@marketplace_bp.route('/whoami', methods=['GET'])
@require_auth()
def whoami():
    """Return the current user's marketplace profile (role, bodega_id, etc.)."""
    _load_marketplace_profile()
    return jsonify({
        'employee_id': g.employee_id,
        'employee_name': g.employee_name,
        'tenant_id': g.tenant_id,
        'marketplace_role': g.marketplace_role,
        'bodega_id': g.marketplace_bodega_id,
    })


@marketplace_bp.route('/bodegas', methods=['GET'])
@require_auth()
def list_bodegas():
    verified_only = request.args.get('verified_only', 'true').lower() != 'false'
    city = request.args.get('city')
    def _do(master):
        return jsonify({'data': mkt.list_bodegas(master, verified_only=verified_only, city=city)})
    return _with_master(_do)


@marketplace_bp.route('/bodegas/<int:bodega_id>', methods=['GET'])
@require_auth()
def get_bodega(bodega_id):
    def _do(master):
        b = mkt.get_bodega(master, bodega_id)
        if not b:
            return jsonify({'error': 'Bodega not found'}), 404
        return jsonify(b)
    return _with_master(_do)


# ═══════════════════════════════════════════════════════════════════════════
# INVENTORY
# ═══════════════════════════════════════════════════════════════════════════

@marketplace_bp.route('/inventory/upload', methods=['POST'])
@require_auth()
@require_marketplace_role('seller', 'admin')
def upload_inventory():
    """CSV bulk upload for a bodega's warehouse inventory.

    Body options:
      multipart/form-data with file field 'file'
      OR
      application/json with {bodega_id, csv}  (admin override)
    """
    # Sellers upload to THEIR bodega; admin can upload to any.
    if g.marketplace_role == 'seller':
        bodega_id = g.marketplace_bodega_id
        if not bodega_id:
            return jsonify({'error': 'Seller has no bodega_id assigned'}), 400
    else:
        body = request.get_json(silent=True) or {}
        bodega_id = int(body.get('bodega_id') or 0)
        if not bodega_id:
            return jsonify({'error': 'bodega_id required for admin upload'}), 400

    # Read CSV from either multipart file or JSON body
    csv_text = None
    if 'file' in request.files:
        csv_text = request.files['file'].read().decode('utf-8', errors='ignore')
    else:
        body = request.get_json(silent=True) or {}
        csv_text = body.get('csv')
    if not csv_text:
        return jsonify({'error': 'CSV payload required (file upload or JSON csv field)'}), 400

    def _do(master):
        result = mkt.upload_inventory_csv(master, bodega_id, csv_text)
        return jsonify(result)
    return _with_master(_do)


@marketplace_bp.route('/inventory/search', methods=['GET'])
@require_auth()
def search_inventory():
    q = request.args.get('q')
    brand = request.args.get('brand')
    city = request.args.get('city')
    limit = min(request.args.get('limit', 50, type=int), 200)
    def _do(master):
        data = mkt.search_inventory(master, query=q, brand=brand, city=city, limit=limit)
        return jsonify({'data': data, 'count': len(data)})
    return _with_master(_do)


@marketplace_bp.route('/inventory/part/<int:part_id>', methods=['GET'])
@require_auth()
def bodegas_with_part(part_id):
    def _do(master):
        data = mkt.get_bodegas_with_part(master, part_id)
        return jsonify({'data': data, 'count': len(data)})
    return _with_master(_do)


@marketplace_bp.route('/inventory/listing/<int:wi_id>', methods=['GET'])
@require_auth()
def bodegas_with_listing(wi_id):
    """Return bodegas stocking a specific seller listing (wi_id)."""
    def _do(master):
        data = mkt.get_bodegas_with_listing(master, wi_id)
        return jsonify({'data': data, 'count': len(data)})
    return _with_master(_do)


# ═══════════════════════════════════════════════════════════════════════════
# PURCHASE ORDERS
# ═══════════════════════════════════════════════════════════════════════════

@marketplace_bp.route('/orders', methods=['POST'])
@require_auth()
@require_marketplace_role('buyer', 'admin')
def create_order():
    """Create a new PO in draft status.

    Body:
      {
        "bodega_id": 1,
        "items": [{"part_id": 123, "quantity": 2, "unit_price": 150}, ...],
        "delivery_method": "pickup",
        "delivery_address": "...",
        "buyer_notes": "..."
      }
    """
    body = request.get_json() or {}
    bodega_id = int(body.get('bodega_id') or 0)
    items = body.get('items') or []

    if not bodega_id:
        return jsonify({'error': 'bodega_id required'}), 400
    if not items:
        return jsonify({'error': 'At least one item required'}), 400

    def _do(master):
        try:
            po_id = mkt.create_po_draft(
                master,
                buyer_tenant_id=g.tenant_id,
                buyer_user_id=g.employee_id,
                buyer_display_name=g.employee_name,
                buyer_phone=body.get('buyer_phone'),
                buyer_email=body.get('buyer_email'),
                bodega_id=bodega_id,
                items=items,
                delivery_method=body.get('delivery_method', 'pickup'),
                delivery_address=body.get('delivery_address'),
                buyer_notes=body.get('buyer_notes'),
            )
            return jsonify({'ok': True, 'po_id': po_id}), 201
        except ValueError as e:
            return jsonify({'error': str(e)}), 400
    return _with_master(_do)


@marketplace_bp.route('/orders/mine', methods=['GET'])
@require_auth()
def my_orders():
    """Buyer view: POs this tenant (or user) created."""
    only_mine = request.args.get('only_mine', 'true').lower() != 'false'
    def _do(master):
        data = mkt.list_pos_for_buyer(
            master,
            buyer_tenant_id=g.tenant_id,
            buyer_user_id=g.employee_id if only_mine else None,
        )
        return jsonify({'data': data, 'count': len(data)})
    return _with_master(_do)


@marketplace_bp.route('/orders/inbox', methods=['GET'])
@require_auth()
@require_marketplace_role('seller', 'admin')
def seller_inbox():
    """Seller view: incoming POs for this bodega."""
    if g.marketplace_role == 'seller':
        bodega_id = g.marketplace_bodega_id
    else:
        bodega_id = int(request.args.get('bodega_id') or 0)
    if not bodega_id:
        return jsonify({'error': 'bodega_id required'}), 400
    def _do(master):
        data = mkt.list_pos_for_seller(master, bodega_id)
        return jsonify({'data': data, 'count': len(data)})
    return _with_master(_do)


@marketplace_bp.route('/orders/<int:po_id>', methods=['GET'])
@require_auth()
def get_order(po_id):
    """PO detail — buyer sees their tenant's POs, seller sees their bodega's."""
    _load_marketplace_profile()
    def _do(master):
        po = mkt.get_po_detail(master, po_id)
        if not po:
            return jsonify({'error': 'PO not found'}), 404

        # Authorization
        if g.marketplace_role == 'seller':
            if po['bodega_id'] != g.marketplace_bodega_id:
                return jsonify({'error': 'Not authorized'}), 403
        elif g.marketplace_role == 'buyer':
            if po['buyer_tenant_id'] != g.tenant_id:
                return jsonify({'error': 'Not authorized'}), 403
        # admin sees all

        return jsonify(po)
    return _with_master(_do)


@marketplace_bp.route('/orders/<int:po_id>/transition', methods=['POST'])
@require_auth()
def transition_order(po_id):
    """Change a PO's status. Role determines which transitions are allowed.

    Body: {"new_status": "confirmed", "note": "optional note"}
    """
    _load_marketplace_profile()
    body = request.get_json() or {}
    new_status = body.get('new_status')
    note = body.get('note')
    if not new_status:
        return jsonify({'error': 'new_status required'}), 400

    # Map marketplace_role to actor_kind for the state machine.
    actor_kind = g.marketplace_role
    if actor_kind == 'admin':
        actor_kind = 'seller'  # admin defaults to seller path in Phase 1

    def _do(master):
        po = mkt.get_po_detail(master, po_id)
        if not po:
            return jsonify({'error': 'PO not found'}), 404
        if g.marketplace_role == 'seller' and po['bodega_id'] != g.marketplace_bodega_id:
            return jsonify({'error': 'Not authorized'}), 403
        if g.marketplace_role == 'buyer' and po['buyer_tenant_id'] != g.tenant_id:
            return jsonify({'error': 'Not authorized'}), 403

        result = mkt.transition_po(
            master,
            po_id=po_id,
            new_status=new_status,
            actor_user_id=g.employee_id,
            actor_kind=actor_kind,
            note=note,
        )
        if not result.get('ok'):
            return jsonify(result), 400
        return jsonify(result)
    return _with_master(_do)
