"""
Hoymiles WFBLE DTU BLE provisioning via MicroPython aioble
Runs on ESP32-S3, scans for DTU, connects, writes WiFi credentials.
"""
import bluetooth
import struct
import time

DTU_MAC = bytes([0x24, 0x19, 0x72, 0x61, 0x9D, 0x62])  # reversed for BLE
SSID = "AhoySmartHome"
PASSWORD = "106granada"

WRITE_CHAR_UUID  = bluetooth.UUID("53300001-0023-4bd4-bbd5-a6920e4c5653")
NOTIFY_CHAR1_UUID = bluetooth.UUID("53300004-0023-4bd4-bbd5-a6920e4c5653")
NOTIFY_CHAR2_UUID = bluetooth.UUID("53300005-0023-4bd4-bbd5-a6920e4c5653")
SERVICE_UUID = bluetooth.UUID("53300000-0023-4bd4-bbd5-a6920e4c5653")

import aioble
import asyncio

async def main():
    print("[*] Scanning for DTU...")
    target = None
    async with aioble.scan(5000, interval_us=30000, window_us=30000, active=True) as scanner:
        async for result in scanner:
            mac = bytes(result.device.addr)
            mac_str = ":".join(f"{b:02X}" for b in reversed(mac))
            if mac_str == "24:19:72:61:9D:62" or (result.name() and "I3000" in result.name()):
                print(f"[+] Found DTU: {mac_str} name={result.name()}")
                target = result.device
                break

    if not target:
        print("[!] DTU not found in scan")
        return

    print(f"[*] Connecting to {target}...")
    async with await target.connect(timeout_ms=10000) as connection:
        print("[+] Connected")

        try:
            service = await connection.service(SERVICE_UUID)
            write_char = await service.characteristic(WRITE_CHAR_UUID)
            print(f"[+] Found write characteristic")

            # Read current value
            val = await write_char.read(timeout_ms=3000)
            print(f"[*] Current value: {val} ({val.hex()})")

            # Subscribe to notifications
            try:
                notify_char1 = await service.characteristic(NOTIFY_CHAR1_UUID)
                await notify_char1.subscribe(notify=True)
                print("[*] Subscribed to notify char 1")
            except Exception as e:
                print(f"[!] notify1 sub failed: {e}")

            try:
                notify_char2 = await service.characteristic(NOTIFY_CHAR2_UUID)
                await notify_char2.subscribe(notify=True)
                print("[*] Subscribed to notify char 2")
            except Exception as e:
                print(f"[!] notify2 sub failed: {e}")

            # Build WiFi config payload
            ssid_b = SSID.encode()
            pw_b = PASSWORD.encode()
            payload = bytes([0x28, len(ssid_b)]) + ssid_b + bytes([len(pw_b)]) + pw_b
            print(f"[*] Writing payload: {payload.hex()}")
            await write_char.write(payload, response=True)
            print("[+] Written — waiting for response...")

            # Wait for notifications
            for _ in range(10):
                await asyncio.sleep_ms(500)
                try:
                    data = await notify_char1.notified(timeout_ms=500)
                    print(f"[NOTIFY1] {data.hex()} | {data}")
                except:
                    pass
                try:
                    data = await notify_char2.notified(timeout_ms=500)
                    print(f"[NOTIFY2] {data.hex()} | {data}")
                except:
                    pass

        except Exception as e:
            print(f"[!] Error: {e}")

asyncio.run(main())
