import asyncio
import json

from microdot import Microdot, send_file

from models import wifi_ws_clients
from settings import Settings

controller = Microdot()
settings = Settings()

@controller.get('')
async def get_settings(request):
    """Get all settings."""
    # Settings is already a dict subclass; avoid dict() wrapper which can
    # trigger MicroPython's "dict update sequence has wrong length" quirk.
    return json.dumps(settings), 200, {'Content-Type': 'application/json'}

@controller.get('/wifi/ap')
async def get_ap_config(request):
    """Get saved AP configuration (Pi: no in-device AP)."""
    config = {
        'saved_ssid': settings.get('wifi_ap_ssid'),
        'saved_password': settings.get('wifi_ap_password'),
        'saved_channel': settings.get('wifi_ap_channel'),
        'active': False,
    }
    return json.dumps(config), 200, {'Content-Type': 'application/json'}

@controller.post('/wifi/ap')
async def configure_ap(request):
    """Save AP configuration to settings (Pi: no in-device AP)."""
    try:
        data = request.json
        ssid = data.get('ssid')
        password = data.get('password', '')
        channel = data.get('channel')
        
        if not ssid:
            return json.dumps({"error": "SSID is required"}), 400
        
        # Validate channel (1-11 for 2.4GHz)
        if channel is not None:
            channel = int(channel)
            if channel < 1 or channel > 11:
                return json.dumps({"error": "Channel must be between 1 and 11"}), 400
        
        settings['wifi_ap_ssid'] = ssid
        settings['wifi_ap_password'] = password
        if channel is not None:
            settings['wifi_ap_channel'] = channel
        settings.save()
        
        return json.dumps({
            "message": "AP settings saved",
            "ssid": ssid,
            "channel": channel
        }), 200, {'Content-Type': 'application/json'}
    except Exception as e:
        return json.dumps({"error": str(e)}), 500

def _validate_wifi_channel(value):
    """Return int 1–11 or raise ValueError."""
    ch = int(value)
    if ch < 1 or ch > 11:
        raise ValueError("wifi_channel must be between 1 and 11")
    return ch


def _validate_global_brightness(value):
    """Return int 0–255 or raise ValueError."""
    v = int(value)
    if v < 0 or v > 255:
        raise ValueError("global_brightness must be between 0 and 255")
    return v


@controller.put('/settings')
async def update_settings(request):
    """Update general settings."""
    try:
        data = request.json
        global_brightness_changed = False
        for key, value in data.items():
            if key == 'wifi_channel' and value is not None:
                settings[key] = _validate_wifi_channel(value)
            elif key == 'global_brightness' and value is not None:
                settings[key] = _validate_global_brightness(value)
                global_brightness_changed = True
            else:
                settings[key] = value
        settings.save()
        if global_brightness_changed:
            try:
                asyncio.get_running_loop().create_task(
                    wifi_ws_clients.broadcast_global_brightness_to_tcp_drivers()
                )
            except RuntimeError:
                pass
        return json.dumps({"message": "Settings updated successfully"}), 200, {'Content-Type': 'application/json'}
    except ValueError as e:
        return json.dumps({"error": str(e)}), 400
    except Exception as e:
        return json.dumps({"error": str(e)}), 500

@controller.get('/page')
async def settings_page(request):
    """Serve the settings page."""
    return send_file('templates/settings.html')

