"""Business Units API endpoints - Full CRUD."""

from flask import Blueprint, request
from flask_jwt_extended import jwt_required

from shopdb.extensions import db
from shopdb.core.models import BusinessUnit
from shopdb.utils.responses import (
    success_response,
    error_response,
    paginated_response,
    ErrorCodes
)
from shopdb.utils.pagination import get_pagination_params, paginate_query

from shopdb.utils.authz import require_role
from shopdb.utils.import_mode import apply_import_timestamps

businessunits_bp = Blueprint('businessunits', __name__)


@businessunits_bp.route('', methods=['GET'])
@jwt_required(optional=True)
def list_businessunits():
    """List all business units."""
    page, per_page = get_pagination_params(request)

    query = BusinessUnit.query

    if request.args.get('active', 'true').lower() != 'false':
        query = query.filter(BusinessUnit.isactive == True)

    # Exact-match natural-key lookup for idempotent import (unit name).
    if exactunit := request.args.get('businessunit'):
        query = query.filter(BusinessUnit.businessunit == exactunit)

    if search := request.args.get('search'):
        query = query.filter(
            db.or_(
                BusinessUnit.businessunit.ilike(f'%{search}%'),
                BusinessUnit.code.ilike(f'%{search}%')
            )
        )

    query = query.order_by(BusinessUnit.businessunit)

    items, total = paginate_query(query, page, per_page)
    data = [bu.to_dict() for bu in items]

    return paginated_response(data, page, per_page, total)


@businessunits_bp.route('/<int:bu_id>', methods=['GET'])
@jwt_required(optional=True)
def get_businessunit(bu_id: int):
    """Get a single business unit."""
    bu = db.session.get(BusinessUnit, bu_id)

    if not bu:
        return error_response(
            ErrorCodes.NOT_FOUND,
            f'Business unit with ID {bu_id} not found',
            http_code=404
        )

    data = bu.to_dict()
    data['parent'] = bu.parent.to_dict() if bu.parent else None
    data['children'] = [c.to_dict() for c in bu.children]

    return success_response(data)


@businessunits_bp.route('', methods=['POST'])
@jwt_required()
@require_role('admin')
def create_businessunit():
    """Create a new business unit."""
    data = request.get_json()

    if not data or not data.get('businessunit'):
        return error_response(ErrorCodes.VALIDATION_ERROR, 'businessunit is required')

    if BusinessUnit.query.filter_by(businessunit=data['businessunit']).first():
        return error_response(
            ErrorCodes.CONFLICT,
            f"Business unit '{data['businessunit']}' already exists",
            http_code=409
        )

    bu = BusinessUnit(
        businessunit=data['businessunit'],
        code=data.get('code'),
        description=data.get('description'),
        parentid=data.get('parentid')
    )

    db.session.add(bu)
    apply_import_timestamps(bu, data)
    db.session.commit()

    return success_response(bu.to_dict(), message='Business unit created', http_code=201)


@businessunits_bp.route('/<int:bu_id>', methods=['PUT'])
@jwt_required()
@require_role('admin')
def update_businessunit(bu_id: int):
    """Update a business unit."""
    bu = db.session.get(BusinessUnit, bu_id)

    if not bu:
        return error_response(
            ErrorCodes.NOT_FOUND,
            f'Business unit with ID {bu_id} not found',
            http_code=404
        )

    data = request.get_json()
    if not data:
        return error_response(ErrorCodes.VALIDATION_ERROR, 'No data provided')

    if 'businessunit' in data and data['businessunit'] != bu.businessunit:
        if BusinessUnit.query.filter_by(businessunit=data['businessunit']).first():
            return error_response(
                ErrorCodes.CONFLICT,
                f"Business unit '{data['businessunit']}' already exists",
                http_code=409
            )

    for key in ['businessunit', 'code', 'description', 'parentid', 'isactive']:
        if key in data:
            setattr(bu, key, data[key])

    apply_import_timestamps(bu, data)
    db.session.commit()
    return success_response(bu.to_dict(), message='Business unit updated')


@businessunits_bp.route('/<int:bu_id>', methods=['DELETE'])
@jwt_required()
@require_role('admin')
def delete_businessunit(bu_id: int):
    """Delete (deactivate) a business unit."""
    bu = db.session.get(BusinessUnit, bu_id)

    if not bu:
        return error_response(
            ErrorCodes.NOT_FOUND,
            f'Business unit with ID {bu_id} not found',
            http_code=404
        )

    bu.isactive = False
    db.session.commit()

    return success_response(message='Business unit deleted')
