"""Locations.itdb writer — iPod file path mapping database.

Maps track PIDs to their physical file locations on the iPod filesystem.

Schema:
    base_location: single row with root path "iPod_Control/Music"
    location: one row per track, mapping item_pid → "Fxx/ABCD.mp3"

Reference: libgpod itdb_sqlite.c mk_Locations()
"""

import time
import logging

from iTunesDB_Writer.mhit_writer import TrackInfo
from iTunesDB_Shared.constants import FILETYPE_CODES
from ._helpers import s64 as _s64, unix_to_coredata, open_db

logger = logging.getLogger(__name__)


# location_type = 0x46494C45 = "FILE" as big-endian int
LOCATION_TYPE_FILE = 0x46494C45

# Extension codes — same as FILETYPE_CODES (big-endian 4-byte ASCII)
_EXTENSION_CODES = FILETYPE_CODES

# kind_id mapping — matches location_kind_map in Library.itdb
# IDs from real iTunes-written databases on Nano 6G
_KIND_ID = {
    'mp3': 1,   # "MPEG audio file"
    'aac': 3,   # "AAC audio file"
    'm4a': 3,   # "AAC audio file" (or ALAC in M4A container)
    'm4p': 2,   # "Purchased AAC audio file"
    'm4b': 3,   # "AAC audio file" (audiobook)
    'm4v': 3,   #
    'mp4': 3,   #
    'wav': 1,   #
    'aif': 1,   #
    'aiff': 1,  #
    'alac': 3,  # ALAC is in M4A container
}


def _ipod_path_to_location(ipod_path: str) -> str:
    """Convert iPod colon-separated path to slash-based location.

    Input:  ":iPod_Control:Music:F04:ZEUN.mp3"
    Output: "F04/ZEUN.mp3"

    The location field stores the path relative to the base_location
    ("iPod_Control/Music"), using forward slashes.
    """
    # Strip leading colon and split
    parts = ipod_path.strip(':').split(':')
    # Skip "iPod_Control" and "Music" prefix
    # The path format is :iPod_Control:Music:Fxx:filename
    # We want: Fxx/filename
    if len(parts) >= 4 and parts[0] == 'iPod_Control' and parts[1] == 'Music':
        return '/'.join(parts[2:])
    elif len(parts) >= 2:
        # Fallback: just take the last two parts
        return '/'.join(parts[-2:])
    else:
        return ipod_path.strip(':').replace(':', '/')


_LOCATIONS_SCHEMA = """
CREATE TABLE IF NOT EXISTS base_location (
    id INTEGER NOT NULL,
    path TEXT,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS location (
    item_pid INTEGER NOT NULL,
    sub_id INTEGER NOT NULL DEFAULT 0,
    base_location_id INTEGER DEFAULT 0,
    location_type INTEGER,
    location TEXT,
    extension INTEGER,
    kind_id INTEGER DEFAULT 0,
    date_created INTEGER DEFAULT 0,
    file_size INTEGER DEFAULT 0,
    file_creator INTEGER,
    file_type INTEGER,
    num_dir_levels_file INTEGER,
    num_dir_levels_lib INTEGER,
    PRIMARY KEY (item_pid, sub_id)
);
"""


def write_locations_itdb(
    path: str,
    tracks: list[TrackInfo],
    tz_offset: int = 0,
) -> None:
    """Write Locations.itdb SQLite database.

    Args:
        path: Output file path.
        tracks: List of TrackInfo objects (with db_track_id and location set).
        tz_offset: Timezone offset in seconds (positive = east of UTC).
    """
    conn, cur = open_db(path)

    cur.executescript(_LOCATIONS_SCHEMA)

    # Single base_location entry
    cur.execute(
        "INSERT INTO base_location (id, path) VALUES (1, 'iPod_Control/Music')"
    )

    # One location per track
    now = int(time.time())

    for track in tracks:
        location = _ipod_path_to_location(track.location)
        ft = track.filetype.lower()
        extension = _EXTENSION_CODES.get(ft, _EXTENSION_CODES.get('mp3', 0x4D503320))
        kind_id = _KIND_ID.get(ft, 0)

        # date_created: Core Data timestamp of when the file was added
        date_added = track.date_added or now
        date_cd = unix_to_coredata(date_added, tz_offset)

        cur.execute(
            """INSERT INTO location (
                item_pid, sub_id, base_location_id, location_type,
                location, extension, kind_id, date_created, file_size,
                file_creator, file_type,
                num_dir_levels_file, num_dir_levels_lib
            ) VALUES (?, 0, 1, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL, NULL)""",
            (
                _s64(track.db_track_id), LOCATION_TYPE_FILE,
                location, extension, kind_id,
                date_cd, track.size,
            )
        )

    conn.commit()
    conn.close()

    logger.info("Wrote Locations.itdb: %d locations", len(tracks))
