"""Vendors 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 Vendor
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

vendors_bp = Blueprint('vendors', __name__)


@vendors_bp.route('', methods=['GET'])
@jwt_required(optional=True)
def list_vendors():
    """List all vendors."""
    page, per_page = get_pagination_params(request)

    query = Vendor.query

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

    # Exact-match natural-key lookup for idempotent import (vendor name).
    if exactvendor := request.args.get('vendor'):
        query = query.filter(Vendor.vendor == exactvendor)

    if search := request.args.get('search'):
        query = query.filter(Vendor.vendor.ilike(f'%{search}%'))

    query = query.order_by(Vendor.vendor)

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

    return paginated_response(data, page, per_page, total)


@vendors_bp.route('/<int:vendor_id>', methods=['GET'])
@jwt_required(optional=True)
def get_vendor(vendor_id: int):
    """Get a single vendor."""
    v = db.session.get(Vendor, vendor_id)

    if not v:
        return error_response(
            ErrorCodes.NOT_FOUND,
            f'Vendor with ID {vendor_id} not found',
            http_code=404
        )

    return success_response(v.to_dict())


@vendors_bp.route('', methods=['POST'])
@jwt_required()
@require_role('admin')
def create_vendor():
    """Create a new vendor."""
    data = request.get_json()

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

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

    v = Vendor(
        vendor=data['vendor'],
        description=data.get('description'),
        website=data.get('website'),
        supportphone=data.get('supportphone'),
        supportemail=data.get('supportemail'),
        notes=data.get('notes')
    )

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

    return success_response(v.to_dict(), message='Vendor created', http_code=201)


@vendors_bp.route('/<int:vendor_id>', methods=['PUT'])
@jwt_required()
@require_role('admin')
def update_vendor(vendor_id: int):
    """Update a vendor."""
    v = db.session.get(Vendor, vendor_id)

    if not v:
        return error_response(
            ErrorCodes.NOT_FOUND,
            f'Vendor with ID {vendor_id} not found',
            http_code=404
        )

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

    if 'vendor' in data and data['vendor'] != v.vendor:
        if Vendor.query.filter_by(vendor=data['vendor']).first():
            return error_response(
                ErrorCodes.CONFLICT,
                f"Vendor '{data['vendor']}' already exists",
                http_code=409
            )

    for key in ['vendor', 'description', 'website', 'supportphone', 'supportemail', 'notes', 'isactive']:
        if key in data:
            setattr(v, key, data[key])

    apply_import_timestamps(v, data)
    db.session.commit()
    return success_response(v.to_dict(), message='Vendor updated')


@vendors_bp.route('/<int:vendor_id>', methods=['DELETE'])
@jwt_required()
@require_role('admin')
def delete_vendor(vendor_id: int):
    """Delete (deactivate) a vendor."""
    v = db.session.get(Vendor, vendor_id)

    if not v:
        return error_response(
            ErrorCodes.NOT_FOUND,
            f'Vendor with ID {vendor_id} not found',
            http_code=404
        )

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

    return success_response(message='Vendor deleted')
