"""ISO 14443-A commands: hf.14a.*"""
import struct
from .protocol import Cmd
from .transport import PM3Transport, PM3Error

# ISO14A command flags (from pm3_cmd.h)
ISO14A_CONNECT = 0x0001
ISO14A_NO_DISCONNECT = 0x0002
ISO14A_RAW = 0x0008
ISO14A_TOPAZMODE = 0x0100
ISO14A_NO_RATS = 0x0200


class HF14ACommands:
    """ISO 14443-A commands."""

    def __init__(self, transport: PM3Transport):
        self._t = transport

    async def scan(self) -> dict:
        """Scan for ISO14443A card. Returns UID, ATQA, SAK, ATS."""
        resp = await self._t.send_mix(
            Cmd.HF_ISO14443A_READER,
            arg0=ISO14A_CONNECT | ISO14A_NO_DISCONNECT,
            timeout=5.0,
        )

        select_status = resp.oldarg[0] if resp.oldarg else 0
        if select_status == 0:
            return {"found": False, "uid": None}

        # Parse iso14a_card_select_t from response data
        data = resp.data
        if len(data) < 13:  # uid(10) + uidlen(1) + atqa(2)
            return {"found": False, "uid": None}

        uid_raw = data[0:10]
        uid_len = data[10]
        atqa = data[11:13]
        sak = data[13] if len(data) > 13 else 0
        ats_len = data[14] if len(data) > 14 else 0
        ats = data[15:15 + ats_len] if ats_len > 0 and len(data) > 15 else b""

        uid = uid_raw[:uid_len]

        return {
            "found": True,
            "uid": uid.hex(),
            "uid_len": uid_len,
            "atqa": atqa.hex(),
            "sak": sak,
            "ats": ats.hex() if ats else None,
            "select_status": select_status,  # 1=OK+ATS, 2=OK no ATS, 3=proprietary
        }

    async def raw(self, data: bytes, flags: int = 0, timeout_14a: int = 0) -> dict:
        """Send raw ISO14443A command."""
        resp = await self._t.send_mix(
            Cmd.HF_ISO14443A_READER,
            arg0=flags | ISO14A_RAW | ISO14A_NO_DISCONNECT,
            arg1=len(data),
            arg2=timeout_14a,
            payload=data,
            timeout=5.0,
        )
        return {
            "status": resp.status,
            "data": resp.data.hex() if resp.data else None,
            "raw": resp.data,
        }

    async def sniff(self, param: int = 0) -> dict:
        """Sniff ISO14443A traffic."""
        resp = await self._t.send_mix(
            Cmd.HF_ISO14443A_SNIFF, arg0=param, timeout=30.0,
        )
        return {"status": resp.status}

    async def sim(self, uid: bytes, sak: int = 0x08, atqa: bytes = b"\x04\x00",
                  flags: int = 0) -> dict:
        """Simulate ISO14443A card."""
        if len(uid) == 4:
            uid_flag = 0x0010
        elif len(uid) == 7:
            uid_flag = 0x0020
        elif len(uid) == 10:
            uid_flag = 0x0030
        else:
            raise ValueError("UID must be 4, 7, or 10 bytes")

        flag_val = flags | uid_flag | 0x0001  # FLAG_INTERACTIVE
        payload = atqa + bytes([sak]) + uid
        resp = await self._t.send_mix(
            Cmd.HF_ISO14443A_SIMULATE, arg0=flag_val, timeout=60.0, payload=payload,
        )
        return {"status": resp.status}
