"""Device integration API routes — Samsung Health (Android companion app) only."""
from datetime import UTC, datetime

from bson import ObjectId
from flask import Blueprint, g, jsonify, request

from app.models.device_connection import DeviceConnection
from app.models.device_reading import VALID_METRICS
from app.repositories import device_repository
from app.routes.access import ensure_can_access_patient_data
from app.routes.auth import auth_required
from app.functionalities.devices import samsung_health_provider
from app.functionalities.devices.sync_service import get_dashboard_summary

devices_bp = Blueprint('devices', __name__, url_prefix='/devices')


# ─── Public info ─────────────────────────────────────────────────────

@devices_bp.route('/providers', methods=['GET'])
def list_providers():
    """List supported device providers and their capabilities."""
    return jsonify({
        'providers': [{
            'id': samsung_health_provider.PROVIDER_NAME,
            'displayName': samsung_health_provider.DISPLAY_NAME,
            'description': 'Galaxy Watch and Samsung Health app data via the Hipograf companion app',
            'metrics': samsung_health_provider.SUPPORTED_METRICS,
            'authType': 'companion_app',
            'requiresCompanionApp': True,
            'companionAppInstructions': (
                'Install the Hipograf Companion app on your Android phone, log in with your '
                'Hipograf account, and grant Health Connect permissions. Make sure Samsung '
                'Health → Settings → Health Connect is enabled for the categories you want to sync.'
            ),
            'status': 'available',
        }]
    })


# ─── Connections ─────────────────────────────────────────────────────

@devices_bp.route('/connections', methods=['GET'])
@auth_required
def list_connections():
    """List all device connections for the authenticated user."""
    user_id = g.auth_user['sub']
    connections = device_repository.find_connections_by_user(user_id)
    return jsonify([
        c.model_dump(by_alias=True, mode='json') for c in connections
    ])


# ─── Samsung Health push endpoint ────────────────────────────────────

@devices_bp.route('/sync/samsung_health', methods=['POST'])
@auth_required
def samsung_sync():
    """Receive data from the Android companion app."""
    user_id = g.auth_user['sub']
    payload = request.get_json(silent=True) or {}
    raw_readings = payload.get('readings', [])

    if not raw_readings:
        return jsonify({'error': 'NoReadings'}), 400

    # Get or create Samsung Health connection
    conn = device_repository.find_connection_by_provider(user_id, 'samsung_health')
    if not conn:
        conn = device_repository.create_connection(DeviceConnection(
            userId=ObjectId(user_id),
            provider='samsung_health',
            status='active',
            metadata=payload.get('deviceInfo', {}),
        ))

    readings = samsung_health_provider.normalize_incoming_payload(
        user_id, str(conn.id), raw_readings
    )
    count = device_repository.bulk_upsert_readings(readings)

    device_repository.update_connection(str(conn.id), {
        'lastSyncAt': datetime.now(UTC),
        'status': 'active',
        # Refresh device info on every sync — phone could change
        'metadata': payload.get('deviceInfo', conn.metadata),
    })

    return jsonify({
        'accepted': count,
        'serverTime': datetime.now(UTC).isoformat(),
    })


# ─── Disconnect / sharing ───────────────────────────────────────────

@devices_bp.route('/connections/<connection_id>', methods=['DELETE'])
@auth_required
def disconnect(connection_id: str):
    """Revoke a device connection. Keeps reading history."""
    user_id = g.auth_user['sub']
    conn = device_repository.find_connection_by_id(connection_id)
    if not conn:
        return jsonify({'error': 'NotFound'}), 404
    if str(conn.userId) != user_id:
        return jsonify({'error': 'Forbidden'}), 403

    device_repository.update_connection(connection_id, {'status': 'revoked'})
    return jsonify({'message': 'Disconnected'})


@devices_bp.route('/connections/<connection_id>/sharing', methods=['PATCH'])
@auth_required
def toggle_sharing(connection_id: str):
    """Toggle sharedWithPractitioners on a connection."""
    user_id = g.auth_user['sub']
    conn = device_repository.find_connection_by_id(connection_id)
    if not conn:
        return jsonify({'error': 'NotFound'}), 404
    if str(conn.userId) != user_id:
        return jsonify({'error': 'Forbidden'}), 403

    payload = request.get_json(silent=True) or {}
    shared = payload.get('sharedWithPractitioners')
    if shared is None:
        return jsonify({'error': 'MissingField', 'field': 'sharedWithPractitioners'}), 400

    updated = device_repository.update_connection(connection_id, {
        'sharedWithPractitioners': bool(shared),
    })
    return jsonify(updated.model_dump(by_alias=True, mode='json'))


# ─── Data queries ────────────────────────────────────────────────────

@devices_bp.route('/data', methods=['DELETE'])
@auth_required
def purge_data():
    """Wipe all (or selected) reading rows for the authenticated user.

    Useful when the schema of valid metrics has changed and stale rows
    need to be cleared. Optional JSON body: {"metrics": ["foo", "bar"]}
    to limit the purge to specific metric names.
    """
    user_id = g.auth_user['sub']
    payload = request.get_json(silent=True) or {}
    metrics = payload.get('metrics')
    deleted = device_repository.delete_readings_for_user(user_id, metrics)
    return jsonify({'deleted': deleted})


@devices_bp.route('/data', methods=['GET'])
@auth_required
def get_data():
    """Query reading history for the authenticated user."""
    user_id = g.auth_user['sub']
    metric = request.args.get('metric', '')
    start_date = request.args.get('start_date', '')
    end_date = request.args.get('end_date', '')

    if not metric or not start_date or not end_date:
        return jsonify({'error': 'MissingParams', 'required': ['metric', 'start_date', 'end_date']}), 400

    readings = device_repository.get_readings(user_id, metric, start_date, end_date)
    return jsonify([r.model_dump(by_alias=True, mode='json') for r in readings])


@devices_bp.route('/summary', methods=['GET'])
@auth_required
def get_summary():
    """Latest values for all metrics. Used by dashboard widgets."""
    user_id = g.auth_user['sub']
    return jsonify(get_dashboard_summary(user_id))


@devices_bp.route('/patients/<patient_id>/summary', methods=['GET'])
@auth_required
def get_patient_summary(patient_id: str):
    """Practitioner view: device summary for a specific patient."""
    _, err = ensure_can_access_patient_data(patient_id)
    if err:
        return err

    # Also check that patient has at least one connection with sharing on
    connections = device_repository.find_connections_by_user(patient_id)
    shared = [c for c in connections if c.sharedWithPractitioners and c.status == 'active']
    if not shared:
        return jsonify({
            'summary': {},
            'connectedProviders': [],
            'lastSync': None,
            'message': 'Patient has not shared device data or has no connected devices.',
        })

    return jsonify(get_dashboard_summary(patient_id))
