#!/usr/bin/env python3
from __future__ import annotations

import argparse
import json
import os
import re
import secrets
from pathlib import Path


def update_firmware_config(path: Path, token: str) -> None:
    key = "CONFIG_DEVICE_LAB_DEVICE_TOKEN"
    line = f'{key}="{token}"'
    content = path.read_text(encoding="utf-8") if path.exists() else ""
    pattern = re.compile(rf"^{key}=.*$", re.MULTILINE)
    if pattern.search(content):
        content = pattern.sub(line, content)
    else:
        content = content.rstrip() + "\n" + line + "\n"
    path.write_text(content, encoding="utf-8")
    os.chmod(path, 0o600)


def main() -> None:
    repo = Path(__file__).resolve().parents[1]
    parser = argparse.ArgumentParser(description="Provision the single Device Lab token")
    parser.add_argument("--device-id", default="", help="bind now, or leave empty to bind first device")
    parser.add_argument("--rotate", action="store_true", help="replace an existing token")
    parser.add_argument(
        "--server-state",
        type=Path,
        default=Path.home() / ".config/esp32-device-gateway/device.json",
    )
    parser.add_argument(
        "--firmware-config",
        type=Path,
        default=repo / "config/sdkconfig.defaults.local",
    )
    args = parser.parse_args()

    credential: dict[str, str] | None = None
    if args.server_state.exists() and not args.rotate:
        value = json.loads(args.server_state.read_text(encoding="utf-8"))
        if isinstance(value, dict) and isinstance(value.get("device_token"), str):
            credential = value
    if credential is None:
        credential = {
            "device_id": args.device_id,
            "device_token": secrets.token_urlsafe(32),
            "pi_token": secrets.token_urlsafe(32),
        }
    elif args.device_id:
        credential["device_id"] = args.device_id
    if not isinstance(credential.get("pi_token"), str) or not credential["pi_token"]:
        credential["pi_token"] = secrets.token_urlsafe(32)

    args.server_state.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
    args.server_state.write_text(json.dumps(credential, indent=2) + "\n", encoding="utf-8")
    os.chmod(args.server_state, 0o600)
    update_firmware_config(args.firmware_config, credential["device_token"])

    binding = credential.get("device_id") or "first authenticated device"
    print(f"Server credential: {args.server_state} (mode 0600)")
    print(f"Firmware config: {args.firmware_config} (mode 0600)")
    print(f"Device binding: {binding}")
    print("Token generated and synchronized without printing it.")


if __name__ == "__main__":
    main()
