"""Legacy POG422 0x0A wire packet decode (82-byte hex CSV).

Production display code uses progressives.csv via EthergoldReader only.
These helpers remain for bench decode / EtherGold_Progs.csv reference captures.
"""

from __future__ import annotations

import csv
import os
from dataclasses import dataclass
from typing import Dict, List

from ethergold_reader import PROGRESSIVE_GAME_IDS

_EXPECTED_PACKET_BYTES = 82


def default_packet_path() -> str:
    base = os.path.dirname(os.path.abspath(__file__))
    return os.path.join(os.path.dirname(base), "EtherGold", "EtherGold_Progs.csv")


def _is_hex_byte(token: str) -> bool:
    text = token.strip().upper()
    if len(text) != 2:
        return False
    return all(ch in "0123456789ABCDEF" for ch in text)


def _uint_le(tokens: List[str]) -> int:
    value = 0
    for index, token in enumerate(tokens):
        value |= int(token, 16) << (8 * index)
    return value


def _load_packet_tokens(path: str) -> List[str]:
    with open(path, encoding="utf-8") as handle:
        rows = list(csv.reader(handle))

    tokens: List[str] = []
    for row in rows:
        if not row:
            continue
        cleaned = [cell.strip() for cell in row if cell.strip()]
        if not cleaned:
            continue
        if _is_hex_byte(cleaned[0]):
            payload = cleaned
        else:
            payload = cleaned[1:]
        for token in payload:
            if not _is_hex_byte(token):
                raise ValueError(f"Invalid EtherGold byte token {token!r} in {path}")
            tokens.append(token.upper())
    return tokens


@dataclass(frozen=True)
class EtherGoldPacket:
    soh: int
    message_type: int
    bank_number: int
    unknown_block: bytes
    terminal_id: int
    max_display_value: int
    game_pennies: Dict[int, int]
    crc16: int
    eop: int


def decode_ethergold_packet(tokens: List[str]) -> EtherGoldPacket:
    if len(tokens) != _EXPECTED_PACKET_BYTES:
        raise ValueError(
            f"Expected {_EXPECTED_PACKET_BYTES} EtherGold bytes, found {len(tokens)}"
        )
    cursor = 0

    def take(count: int) -> List[str]:
        nonlocal cursor
        chunk = tokens[cursor : cursor + count]
        cursor += count
        return chunk

    soh = int(take(1)[0], 16)
    message_type = int(take(1)[0], 16)
    bank_number = int(take(1)[0], 16)
    unknown_block = bytes(int(token, 16) for token in take(6))
    terminal_id = _uint_le(take(2))
    max_display_value = _uint_le(take(4))
    game_pennies = {game_id: _uint_le(take(4)) for game_id in range(1, 17)}
    crc16 = _uint_le(take(2))
    eop = int(take(1)[0], 16)

    return EtherGoldPacket(
        soh=soh,
        message_type=message_type,
        bank_number=bank_number,
        unknown_block=unknown_block,
        terminal_id=terminal_id,
        max_display_value=max_display_value,
        game_pennies=game_pennies,
        crc16=crc16,
        eop=eop,
    )


def packet_progressive_targets(packet: EtherGoldPacket) -> Dict[int, int]:
    """Map decoded 0x0A packet to progressives.csv game_id → pennies."""
    targets = dict(packet.game_pennies)
    targets[15] = 0
    return {
        game_id: pennies
        for game_id, pennies in targets.items()
        if game_id in PROGRESSIVE_GAME_IDS or game_id == 15
    }
