"""MHLI Writer — Write artist list chunks for iTunesDB.

MHSD type 8 contains an artist list using 'mhli' as the list header and
'mhii' as individual artist items.  Despite sharing the 'mhii' magic with
ArtworkDB image items, these are structurally different chunks.

MHLI header layout (MHLI_HEADER_SIZE = 92 bytes):
    +0x00: 'mhli' magic (4B)
    +0x04: header_length (4B)
    +0x08: artist_count (4B)

MHII header layout (MHII_HEADER_SIZE = 80 bytes, per libgpod mk_mhii):
    +0x00: 'mhii' magic (4B)
    +0x04: header_length (4B)
    +0x08: total_length (4B) — header + child MHODs
    +0x0C: child_count (4B) — always 1 (the artist-name MHOD)
    +0x10: artist_id (4B) — links to MHIT.artist_id
    +0x14: sql_id (8B) — internal iPod DB id (must be non-zero)
    +0x1C: platform_flag (4B) — always 2

    Children: MHOD type 300 (artist name / album-artist name)

Cross-referenced against:
  - libgpod itdb_itunesdb.c: mk_mhii() (artist variant)
  - docs/iTunesCDB-internals.md §Type 8
"""

import random
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .mhit_writer import TrackInfo

from iTunesDB_Shared.field_base import (
    MHLI_HEADER_SIZE,
    write_fields,
    write_generic_header,
)
from iTunesDB_Shared.mhii_defs import MHII_HEADER_SIZE
from iTunesDB_Shared.constants import MHOD_TYPE_ARTIST_NAME
from .mhod_writer import write_mhod_string


def write_mhii_artist(artist_id: int, artist_name: str) -> bytes:
    """
    Write an MHII (artist item) chunk for the artist list.

    Args:
        artist_id: Unique artist ID (used to link tracks to artists)
        artist_name: Artist name string

    Returns:
        Complete MHII chunk with MHOD type 300
    """
    # Build child MHOD (always exactly 1: the artist name)
    children = bytearray()
    child_count = 0

    if artist_name:
        children.extend(write_mhod_string(MHOD_TYPE_ARTIST_NAME, artist_name))
        child_count += 1

    # Total chunk length
    total_length = MHII_HEADER_SIZE + len(children)

    # Build header
    header = bytearray(MHII_HEADER_SIZE)
    write_generic_header(header, 0, b'mhii', MHII_HEADER_SIZE, total_length)

    # CRITICAL: sql_id must be non-zero! Clean iTunes DBs have random u64 values here.
    sql_id = random.getrandbits(64)
    write_fields(header, 0, 'mhii', {
        'child_count': child_count,
        'artist_id': artist_id,
        'sql_id': sql_id,
        'platform_flag': 2,
    }, MHII_HEADER_SIZE)

    return bytes(header) + bytes(children)


def write_mhli(tracks: list["TrackInfo"], starting_index_for_artist_id: int) -> tuple[bytes, dict[str, int], int]:
    """
    Write an MHLI (artist list) chunk with artists derived from tracks.

    Deduplicates artists using case-insensitive matching (same as album
    deduplication in mhla_writer.py).

    Args:
        tracks: List of TrackInfo objects

    Returns:
        Tuple of (MHLI chunk bytes, artist_map dict mapping artist_name_lower to artist_id)
    """
    # Collect unique artists: lowercase artist name → display name
    # Use the first occurrence's casing as the canonical display name
    artist_display: dict[str, str] = {}
    for track in tracks:
        artist_name = track.artist or ""
        if not artist_name:
            continue
        key = artist_name.lower()
        if key not in artist_display:
            artist_display[key] = artist_name

    # Build artist items
    artist_items = bytearray()
    artist_map: dict[str, int] = {}  # lowercase artist → artist_id

    artist_id = starting_index_for_artist_id
    for key in sorted(artist_display.keys()):
        display_name = artist_display[key]
        artist_map[key] = artist_id
        artist_items.extend(write_mhii_artist(artist_id, display_name))
        artist_id += 1

    artist_count = len(artist_map)

    # Build header
    header = bytearray(MHLI_HEADER_SIZE)
    write_generic_header(header, 0, b'mhli', MHLI_HEADER_SIZE, artist_count)

    return bytes(header) + bytes(artist_items), artist_map, artist_id


def write_mhli_empty() -> bytes:
    """
    Write an empty MHLI (artist list) chunk.

    Returns:
        MHLI header with 0 artists
    """
    header = bytearray(MHLI_HEADER_SIZE)
    write_generic_header(header, 0, b'mhli', MHLI_HEADER_SIZE, 0)

    return bytes(header)
