"""Hospital API routes."""
from flask import Blueprint, jsonify, request
from pydantic import ValidationError

from app.models.hospital import Hospital
from app.repositories import hospital_repository
from app.routes.auth import auth_required, require_roles

hospitals_bp = Blueprint('hospitals_api', __name__)


@hospitals_bp.route('/hospitals', methods=['POST'])
@auth_required
@require_roles('admin')
def create_hospital_endpoint():
    """Create a hospital.
    ---
    tags:
        - Hospitals
    security:
        - BearerAuth: []
    requestBody:
        required: true
        content:
            application/json:
                schema:
                    $ref: '#/components/schemas/HospitalCreateRequest'
    responses:
        201:
            description: Hospital created
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/HospitalResponse'
        400:
            description: Validation error
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
        401:
            description: Unauthorized
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
        403:
            description: Forbidden
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
    """
    payload = request.get_json(silent=True) or {}
    try:
        hospital = Hospital.model_validate(payload)
    except ValidationError as exc:
        return jsonify({'error': 'ValidationError', 'detail': str(exc)}), 400

    created = hospital_repository.create(hospital)
    return jsonify(created.model_dump(by_alias=True, mode='json')), 201


@hospitals_bp.route('/hospitals/<hospital_id>', methods=['GET'])
@auth_required
def get_hospital_by_id_endpoint(hospital_id: str):
    """Get a hospital by ID.
    ---
    tags:
        - Hospitals
    security:
        - BearerAuth: []
    parameters:
        - in: path
          name: hospital_id
          required: true
          schema:
            type: string
    responses:
        200:
            description: Hospital found
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/HospitalResponse'
        401:
            description: Unauthorized
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
        404:
            description: Hospital not found
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
    """
    hospital = hospital_repository.find_by_id(hospital_id)
    if not hospital:
        return jsonify({'error': 'NotFound'}), 404
    return jsonify(hospital.model_dump(by_alias=True, mode='json'))


@hospitals_bp.route('/hospitals/by-tracking-id/<tracking_id>', methods=['GET'])
@auth_required
def get_hospital_by_tracking_id_endpoint(tracking_id: str):
    """Get a hospital by tracking ID.
    ---
    tags:
        - Hospitals
    security:
        - BearerAuth: []
    parameters:
        - in: path
          name: tracking_id
          required: true
          schema:
            type: string
    responses:
        200:
            description: Hospital found
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/HospitalResponse'
        401:
            description: Unauthorized
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
        404:
            description: Hospital not found
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
    """
    hospital = hospital_repository.find_by_tracking_id(tracking_id)
    if not hospital:
        return jsonify({'error': 'NotFound'}), 404
    return jsonify(hospital.model_dump(by_alias=True, mode='json'))


@hospitals_bp.route('/hospitals/<hospital_id>', methods=['PATCH'])
@auth_required
@require_roles('admin')
def update_hospital_endpoint(hospital_id: str):
    """Update a hospital record.
    ---
    tags:
        - Hospitals
    security:
        - BearerAuth: []
    parameters:
        - in: path
          name: hospital_id
          required: true
          schema:
            type: string
    requestBody:
        required: true
        content:
            application/json:
                schema:
                    $ref: '#/components/schemas/HospitalUpdateRequest'
    responses:
        200:
            description: Hospital updated
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/HospitalResponse'
        400:
            description: No updatable fields
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
        401:
            description: Unauthorized
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
        403:
            description: Forbidden
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
        404:
            description: Hospital not found
            content:
                application/json:
                    schema:
                        $ref: '#/components/schemas/ErrorResponse'
    """
    updates = request.get_json(silent=True) or {}
    forbidden = {'_id', 'id', 'created_at', 'updated_at'}
    filtered_updates = {k: v for k, v in updates.items() if k not in forbidden}
    if not filtered_updates:
        return jsonify({'error': 'NoUpdatableFields'}), 400

    updated = hospital_repository.update(hospital_id, filtered_updates)
    if not updated:
        return jsonify({'error': 'NotFound'}), 404

    return jsonify(updated.model_dump(by_alias=True, mode='json'))
