"""
HiFi API Client — Alternative lossless download source via public hifi-api instances.

Provides Tidal-sourced FLAC downloads (16-bit and 24-bit) through the open hifi-api
project. No authentication required from the client — the API instances handle
Tidal credentials internally.

Interface follows the same patterns as TidalDownloadClient for drop-in compatibility
with the existing download infrastructure (TrackResult, DownloadStatus, etc).

Supports:
- Track search by title, artist, album
- Album lookup by ID
- Artist lookup by ID
- HLS manifest-based downloads via /trackManifests/ endpoint
- Quality selection: HIRES_LOSSLESS, LOSSLESS, HIGH, LOW
- Multiple API instance failover
- FFmpeg demuxing for FLAC extraction from MP4 containers
"""

import os
import re
import uuid
import time
import shutil
import json
import base64
import subprocess
import threading
from typing import List, Optional, Dict, Any, Tuple
from pathlib import Path
from urllib.parse import urljoin

import requests as http_requests

from utils.logging_config import get_logger
from config.settings import config_manager
from core.download_plugins.types import TrackResult, AlbumResult, DownloadStatus

logger = get_logger("hifi_client")

# HLS quality presets mapping to /trackManifests/ format parameters
HLS_QUALITY_MAP = {
    'hires': {
        'formats': ['FLAC_HIRES'],
        'manifest_type': 'HLS',
        'extension': 'flac',
        'label': 'FLAC 24-bit/96kHz',
        'bitrate': 9216,
        'codec': 'flac',
    },
    'lossless': {
        'formats': ['FLAC'],
        'manifest_type': 'HLS',
        'extension': 'flac',
        'label': 'FLAC 16-bit/44.1kHz',
        'bitrate': 1411,
        'codec': 'flac',
    },
    'high': {
        'formats': ['AACLC'],
        'manifest_type': 'HLS',
        'extension': 'm4a',
        'label': 'AAC 320kbps',
        'bitrate': 320,
        'codec': 'aac',
    },
    'low': {
        'formats': ['HEAACV1'],
        'manifest_type': 'HLS',
        'extension': 'm4a',
        'label': 'AAC 96kbps',
        'bitrate': 96,
        'codec': 'aac',
    },
}

HLS_MAP_TAG_RE = re.compile(r'#EXT-X-MAP:.*URI="([^"]+)"')

TRACK_ENDPOINT_QUALITY_MAP = {
    'hires': 'HI_RES_LOSSLESS',
    'lossless': 'LOSSLESS',
    'high': 'HIGH',
    'low': 'LOW',
}

# Default public hifi-api instances (ordered by preference)
DEFAULT_INSTANCES = [
    'https://triton.squid.wtf',
    'https://hifi-one.spotisaver.net',
    'https://hifi-two.spotisaver.net',
    'https://hund.qqdl.site',
    'https://katze.qqdl.site',
    'https://arran.monochrome.tf',
]


from core.download_plugins.base import DownloadSourcePlugin


class HiFiClient(DownloadSourcePlugin):
    """
    HiFi API client for searching and downloading lossless music.
    Uses public hifi-api instances (Tidal backend) — no auth required.
    """

    def __init__(self, download_path: str = None, base_url: str = None):
        if download_path is None:
            download_path = config_manager.get('soulseek.download_path', './downloads')
        self.download_path = Path(download_path)
        self.download_path.mkdir(parents=True, exist_ok=True)

        self._instances = []
        self._instance_lock = threading.Lock()
        self._load_instances_from_db()

        self._current_instance = self._instances[0] if self._instances else None

        self.session = http_requests.Session()
        self.session.headers.update({
            'User-Agent': 'SoulSync/1.0',
            'Accept': 'application/json',
        })

        self._engine = None
        self.shutdown_check = None

        self._last_api_call = 0
        self._api_lock = threading.Lock()
        self._min_interval = 0.5

        logger.info(f"HiFi client initialized (instance: {self._current_instance}, "
                     f"download path: {self.download_path})")

    def set_shutdown_check(self, check_callable):
        self.shutdown_check = check_callable

    def set_engine(self, engine):
        self._engine = engine

    def _load_instances_from_db(self):
        try:
            from database.music_database import get_database
            db = get_database()
            db.seed_hifi_instances(DEFAULT_INSTANCES)
            rows = db.get_hifi_instances()
            urls = [r['url'] for r in rows if r['enabled']]
            if urls:
                self._instances = urls
            else:
                self._instances = list(DEFAULT_INSTANCES)
        except Exception as e:
            logger.warning(f"Failed to load HiFi instances from DB, using defaults: {e}")
            self._instances = list(DEFAULT_INSTANCES)

    def reload_instances(self):
        with self._instance_lock:
            old_current = self._current_instance
            self._load_instances_from_db()
            self._current_instance = self._instances[0] if self._instances else None
            if self._current_instance != old_current:
                logger.info(f"HiFi instances reloaded, active: {self._current_instance}")
            else:
                logger.info("HiFi instances reloaded")

    def _get_instance(self) -> Optional[str]:
        with self._instance_lock:
            return self._current_instance

    def _rotate_instance(self, failed_url: str):
        with self._instance_lock:
            if failed_url in self._instances:
                self._instances.remove(failed_url)
                self._instances.append(failed_url)
            if self._instances:
                self._current_instance = self._instances[0]
                logger.info(f"Rotated to HiFi instance: {self._current_instance}")
            else:
                self._current_instance = None

    def _rate_limit(self):
        with self._api_lock:
            now = time.time()
            elapsed = now - self._last_api_call
            if elapsed < self._min_interval:
                time.sleep(self._min_interval - elapsed)
            self._last_api_call = time.time()

    def _api_get(self, path: str, params: dict = None, timeout: int = 15) -> Optional[dict]:
        tried = set()

        while True:
            instance = self._get_instance()
            if not instance or instance in tried:
                logger.error("All HiFi API instances exhausted")
                return None

            tried.add(instance)
            url = f"{instance}{path}"
            self._rate_limit()

            try:
                response = self.session.get(url, params=params, timeout=timeout)
                response.raise_for_status()
                data = response.json()

                if isinstance(data, dict) and data.get('error'):
                    logger.warning(f"HiFi API error from {instance}: {data['error']}")
                    return None

                return data

            except http_requests.exceptions.Timeout:
                logger.warning(f"HiFi API timeout: {instance}")
                self._rotate_instance(instance)
            except http_requests.exceptions.ConnectionError:
                logger.warning(f"HiFi API connection error: {instance}")
                self._rotate_instance(instance)
            except http_requests.exceptions.HTTPError as e:
                status = e.response.status_code if e.response is not None else 0
                if status >= 500:
                    logger.warning(f"HiFi API server error ({status}): {instance}")
                    self._rotate_instance(instance)
                else:
                    logger.error(f"HiFi API HTTP error ({status}): {e}")
                    return None
            except Exception as e:
                logger.error(f"HiFi API unexpected error: {e}")
                return None

    def is_available(self) -> bool:
        try:
            data = self._api_get('/', timeout=5)
            return data is not None
        except Exception:
            return False

    def is_configured(self) -> bool:
        return self._current_instance is not None

    async def check_connection(self) -> bool:
        try:
            import asyncio
            loop = asyncio.get_event_loop()
            return await loop.run_in_executor(None, self.is_available)
        except Exception as e:
            logger.error(f"HiFi connection check failed: {e}")
            return False

    def get_version(self) -> Optional[str]:
        data = self._api_get('/')
        if data and isinstance(data, dict):
            return data.get('version') or data.get('data', {}).get('version')
        return None

    @staticmethod
    def _extract_manifest_uri(data: Any) -> Optional[str]:
        try:
            inner = data.get('data', data) if isinstance(data, dict) else data
            attrs = inner.get('data', {}).get('attributes', {})
            return attrs.get('uri')
        except (AttributeError, KeyError):
            return None

    @staticmethod
    def _extract_track_manifest_urls(data: Any) -> List[str]:
        try:
            inner = data.get('data', data) if isinstance(data, dict) else data
            manifest_b64 = inner.get('manifest')
            if not manifest_b64:
                return []
            manifest = json.loads(base64.b64decode(manifest_b64))
            if manifest.get('encryptionType') not in (None, 'NONE'):
                return []
            urls = manifest.get('urls') or []
            return [url for url in urls if isinstance(url, str) and url]
        except Exception as e:
            logger.debug("Failed to extract legacy HiFi track manifest URLs: %s", e)
            return []

    @staticmethod
    def _extension_from_track_manifest(data: Any, fallback: str) -> str:
        try:
            inner = data.get('data', data) if isinstance(data, dict) else data
            manifest = json.loads(base64.b64decode(inner.get('manifest') or ''))
            mime = (manifest.get('mimeType') or '').lower()
            codecs = (manifest.get('codecs') or '').lower()
            if 'flac' in mime or 'flac' in codecs:
                return 'flac'
            if 'mp4' in mime or 'aac' in codecs:
                return 'm4a'
        except Exception as e:
            logger.debug("Failed to infer legacy HiFi track manifest extension: %s", e)
        return fallback

    def check_instance_capabilities(self, url: str, timeout: int = 5) -> Dict[str, Any]:
        """Probe one public HiFi instance using the endpoints SoulSync needs."""
        entry = {
            'url': url,
            'status': 'unknown',
            'version': None,
            'can_search': False,
            'can_download': False,
        }
        try:
            root = self.session.get(
                f'{url}/',
                timeout=timeout,
                headers={'Accept': 'application/json'},
            )
            if not root.ok:
                entry['status'] = f'error (HTTP {root.status_code})'
                return entry

            data = root.json()
            entry['version'] = data.get('version') or data.get('data', {}).get('version')
            entry['status'] = 'online'

            search = self.session.get(
                f'{url}/search/',
                params={'s': 'test', 'limit': 1},
                timeout=timeout,
            )
            entry['can_search'] = search.ok

            manifest = self.session.get(
                f'{url}/trackManifests/',
                params={
                    'id': '1550546',
                    'formats': 'FLAC',
                    'usage': 'DOWNLOAD',
                    'manifestType': 'HLS',
                    'adaptive': 'true',
                    'uriScheme': 'HTTPS',
                },
                timeout=timeout,
            )
            entry['can_download'] = (
                manifest.ok
                and bool(self._extract_manifest_uri(manifest.json()))
            )
            if not manifest.ok:
                entry['download_error'] = f'HTTP {manifest.status_code}'
            elif not entry['can_download']:
                legacy = self.session.get(
                    f'{url}/track/',
                    params={'id': '1550546', 'quality': 'LOSSLESS'},
                    timeout=timeout,
                )
                entry['can_download'] = (
                    legacy.ok
                    and bool(self._extract_track_manifest_urls(legacy.json()))
                )
                if not legacy.ok:
                    entry['download_error'] = f'HTTP {legacy.status_code}'
                elif not entry['can_download']:
                    entry['download_error'] = 'No playable manifest URL'
                else:
                    entry['download_probe'] = 'track'
            else:
                entry['download_probe'] = 'trackManifests'
        except http_requests.exceptions.SSLError:
            entry['status'] = 'ssl_error'
        except http_requests.exceptions.ConnectTimeout:
            entry['status'] = 'timeout'
        except http_requests.exceptions.ConnectionError:
            entry['status'] = 'offline'
        except Exception as e:
            entry['status'] = f'error ({type(e).__name__})'
        return entry

    def search_tracks(self, title: str = None, artist: str = None,
                      album: str = None, limit: int = 20) -> List[Dict]:
        params = {'limit': limit}
        if title:
            params['s'] = title
        if artist:
            params['a'] = artist
        if album:
            params['al'] = album

        if not any(k in params for k in ('s', 'a', 'al')):
            logger.warning("search_tracks called with no search terms")
            return []

        data = self._api_get('/search/', params=params)
        if not data:
            return []

        items = []
        if isinstance(data, dict):
            inner = data.get('data', data)
            if isinstance(inner, dict):
                items = inner.get('items', inner.get('tracks', []))
            elif isinstance(inner, list):
                items = inner

        results = []
        for item in items:
            try:
                results.append(self._parse_track(item))
            except Exception as e:
                logger.debug(f"Skipping unparseable track: {e}")

        logger.info(f"HiFi search: {len(results)} tracks found "
                     f"(title={title}, artist={artist}, album={album})")
        return results

    def search_raw(self, query: str, limit: int = 20) -> List[Dict]:
        return self.search_tracks(title=query, limit=limit)

    def _parse_track(self, item: dict) -> Dict:
        artist_name = 'Unknown Artist'
        artist_id = None
        artists_raw = item.get('artists', item.get('artist'))
        if isinstance(artists_raw, list):
            names = []
            for a in artists_raw:
                if isinstance(a, dict):
                    names.append(a.get('name', ''))
                    if artist_id is None:
                        artist_id = a.get('id')
                elif isinstance(a, str):
                    names.append(a)
            artist_name = ', '.join(n for n in names if n) or 'Unknown Artist'
        elif isinstance(artists_raw, dict):
            artist_name = artists_raw.get('name', 'Unknown Artist')
            artist_id = artists_raw.get('id')
        elif isinstance(artists_raw, str):
            artist_name = artists_raw

        album_raw = item.get('album', {})
        album_name = ''
        album_id = None
        if isinstance(album_raw, dict):
            album_name = album_raw.get('title', album_raw.get('name', ''))
            album_id = album_raw.get('id')
        elif isinstance(album_raw, str):
            album_name = album_raw

        duration_s = item.get('duration', 0)
        duration_ms = duration_s * 1000 if duration_s and duration_s < 100000 else duration_s

        return {
            'id': item.get('id'),
            'artist_id': artist_id,
            'album_id': album_id,
            'title': item.get('title', item.get('name', 'Unknown')),
            'artist': artist_name,
            'album': album_name,
            'duration_ms': int(duration_ms) if duration_ms else 0,
            'track_number': item.get('trackNumber', item.get('track_number')),
            'isrc': item.get('isrc'),
            'bpm': item.get('bpm'),
            'copyright': item.get('copyright'),
            'explicit': item.get('explicit', False),
            'quality': item.get('audioQuality', item.get('quality', '')),
        }

    def get_track_info(self, track_id: int) -> Optional[Dict]:
        data = self._api_get('/info/', params={'id': track_id})
        if not data:
            return None

        inner = data.get('data', data) if isinstance(data, dict) else data
        if isinstance(inner, dict):
            return self._parse_track(inner)
        return None

    def get_album(self, album_id: int, limit: int = 100) -> Optional[Dict]:
        data = self._api_get('/album/', params={'id': album_id, 'limit': limit})
        if not data:
            return None

        inner = data.get('data', data) if isinstance(data, dict) else data
        if not isinstance(inner, dict):
            return None

        tracks_raw = inner.get('items', inner.get('tracks', []))
        tracks = []
        for item in tracks_raw:
            try:
                tracks.append(self._parse_track(item))
            except Exception as e:
                logger.debug(f"Skipping album track: {e}")

        return {
            'id': inner.get('id', album_id),
            'title': inner.get('title', inner.get('name', 'Unknown Album')),
            'artist': inner.get('artist', {}).get('name', '') if isinstance(inner.get('artist'), dict) else str(inner.get('artist', '')),
            'tracks': tracks,
            'track_count': inner.get('numberOfTracks', len(tracks)),
            'duration_s': inner.get('duration', 0),
            'release_date': inner.get('releaseDate', ''),
            'cover_id': inner.get('cover', ''),
        }

    def get_artist(self, artist_id: int) -> Optional[Dict]:
        data = self._api_get('/artist/', params={'id': artist_id})
        if not data:
            return None

        inner = data.get('data', data) if isinstance(data, dict) else data
        return inner if isinstance(inner, dict) else None

    def _parse_hls_playlist(self, text: str, playlist_url: str):
        init_uri = None
        segment_uris = []
        variant_uri = None

        lines = [line.strip() for line in text.splitlines() if line.strip()]

        for index, line in enumerate(lines):
            if line.startswith('#EXTM3U'):
                continue

            if line.startswith('#EXT-X-STREAM-INF'):
                for next_line in lines[index + 1:]:
                    if not next_line.startswith('#'):
                        variant_uri = urljoin(playlist_url, next_line)
                        break
                break

            if line.startswith('#EXT-X-MAP'):
                match = HLS_MAP_TAG_RE.search(line)
                if match:
                    init_uri = match.group(1)
                continue

            if line.startswith('#'):
                continue

            segment_uris.append(urljoin(playlist_url, line))

        if variant_uri:
            return None, [variant_uri]

        if not segment_uris:
            raise ValueError('No segment URIs found in the HLS playlist')

        if init_uri:
            init_uri = urljoin(playlist_url, init_uri)

        return init_uri, segment_uris

    def _get_hls_manifest(self, track_id: int, quality: str = 'lossless') -> Optional[Dict]:
        q_info = HLS_QUALITY_MAP.get(quality, HLS_QUALITY_MAP['lossless'])
        formats = q_info['formats']

        params = [
            ('id', str(track_id)),
            ('formats', ','.join(formats)),
            ('usage', 'DOWNLOAD'),
            ('manifestType', 'HLS'),
            ('adaptive', 'true'),
            ('uriScheme', 'HTTPS'),
        ]

        data = self._api_get('/trackManifests/', params=params, timeout=20)
        if not data:
            return self._get_legacy_track_manifest(track_id, quality)

        uri = self._extract_manifest_uri(data)
        if uri is None:
            logger.warning("Failed to extract playlist URI from manifest response")
            return self._get_legacy_track_manifest(track_id, quality)

        if not uri:
            logger.warning(f"No playlist URI in manifest for track {track_id}")
            return None

        try:
            playlist_resp = self.session.get(uri, allow_redirects=True, timeout=30)
            playlist_resp.raise_for_status()
            playlist_text = playlist_resp.text
        except Exception as e:
            logger.warning(f"Failed to fetch HLS playlist for track {track_id}: {e}")
            return None

        try:
            init_uri, segment_uris = self._parse_hls_playlist(playlist_text, uri)
        except ValueError as e:
            logger.warning(f"Failed to parse HLS playlist for track {track_id}: {e}")
            return None

        if '#EXT-X-STREAM-INF' in playlist_text and segment_uris:
            playlist_uri = segment_uris[0]
            try:
                logger.debug(f"Detected master HLS playlist, following variant: {playlist_uri}")
                variant_resp = self.session.get(playlist_uri, allow_redirects=True, timeout=30)
                variant_resp.raise_for_status()
                variant_text = variant_resp.text
                init_uri, segment_uris = self._parse_hls_playlist(variant_text, playlist_uri)
            except Exception as e:
                logger.warning(f"Failed to fetch variant playlist for track {track_id}: {e}")
                return None

        if init_uri:
            logger.info(f"HiFi HLS manifest for track {track_id}: "
                        f"init segment + {len(segment_uris)} segments ({quality})")
        else:
            logger.info(f"HiFi HLS manifest for track {track_id}: "
                        f"{len(segment_uris)} segments ({quality})")

        return {
            'init_uri': init_uri,
            'segment_uris': segment_uris,
            'extension': q_info['extension'],
            'codec': q_info['codec'],
            'quality': quality,
        }

    def _get_legacy_track_manifest(self, track_id: int, quality: str = 'lossless') -> Optional[Dict]:
        q_info = HLS_QUALITY_MAP.get(quality, HLS_QUALITY_MAP['lossless'])
        api_quality = TRACK_ENDPOINT_QUALITY_MAP.get(quality, 'LOSSLESS')
        data = self._api_get('/track/', params={'id': track_id, 'quality': api_quality}, timeout=20)
        if not data:
            return None

        direct_urls = self._extract_track_manifest_urls(data)
        if not direct_urls:
            logger.warning(f"No playable URL in legacy HiFi manifest for track {track_id}")
            return None

        extension = self._extension_from_track_manifest(data, q_info['extension'])
        logger.info(f"HiFi legacy track manifest for track {track_id}: "
                    f"{len(direct_urls)} direct URL(s) ({quality})")
        return {
            'direct_urls': direct_urls,
            'extension': extension,
            'codec': q_info['codec'],
            'quality': quality,
        }

    def _demux_flac(self, input_path: Path, output_path: Path) -> None:
        ffmpeg = shutil.which('ffmpeg')
        if not ffmpeg:
            tools_dir = Path(__file__).parent.parent / 'tools'
            ffmpeg_candidate = tools_dir / ('ffmpeg.exe' if os.name == 'nt' else 'ffmpeg')
            if ffmpeg_candidate.exists():
                ffmpeg = str(ffmpeg_candidate)
            else:
                raise RuntimeError('ffmpeg is required to demux FLAC from MP4. Install ffmpeg and retry.')

        try:
            result = subprocess.run(
                [
                    ffmpeg,
                    '-y',
                    '-hide_banner',
                    '-loglevel', 'error',
                    '-i', str(input_path),
                    '-map', '0:a:0',
                    '-c', 'copy',
                    str(output_path),
                ],
                check=True,
                capture_output=True,
                text=True,
            )
        except subprocess.CalledProcessError as exc:
            raise RuntimeError(
                f'ffmpeg failed while demuxing {input_path} -> {output_path}: '
                f'{exc.returncode}\n{exc.stderr}'
            ) from exc

    async def search(self, query: str, timeout: int = None,
                     progress_callback=None) -> Tuple[List[TrackResult], List[AlbumResult]]:
        import asyncio

        try:
            loop = asyncio.get_event_loop()
            tracks = await loop.run_in_executor(None, lambda: self.search_raw(query))

            quality_key = config_manager.get('hifi_download.quality', 'lossless')
            q_info = HLS_QUALITY_MAP.get(quality_key, HLS_QUALITY_MAP['lossless'])

            results = []
            for t in tracks:
                try:
                    tr = self._to_track_result(t, q_info)
                    results.append(tr)
                except Exception as e:
                    logger.debug(f"Skipping track result conversion: {e}")

            return (results, [])

        except Exception as e:
            logger.error(f"HiFi compatible search failed: {e}")
            return ([], [])

    def _to_track_result(self, track: Dict, quality_info: Dict) -> TrackResult:
        display_name = f"{track['artist']} - {track['title']}"
        filename = f"{track['id']}||{display_name}"

        return TrackResult(
            username='hifi',
            filename=filename,
            size=0,
            bitrate=quality_info.get('bitrate'),
            duration=track.get('duration_ms'),
            quality=quality_info.get('codec', 'flac'),
            free_upload_slots=999,
            upload_speed=999999,
            queue_length=0,
            artist=track.get('artist'),
            title=track.get('title'),
            album=track.get('album'),
            track_number=track.get('track_number'),
            _source_metadata={
                'source': 'hifi',
                'track_id': track.get('id'),
                'artist_id': track.get('artist_id'),
                'album_id': track.get('album_id'),
                'isrc': track.get('isrc'),
                'bpm': track.get('bpm'),
                'copyright': track.get('copyright'),
            },
        )

    async def download(self, username: str, filename: str, file_size: int = 0) -> Optional[str]:
        if '||' not in filename:
            logger.error(f"Invalid filename format: {filename}")
            return None
        if self._engine is None:
            # Raise rather than return None so the orchestrator's
            # download_with_fallback surfaces a real warning + tries
            # the next source. Returning None silently dropped the
            # download with no user feedback (per JohnBaumb).
            raise RuntimeError("HiFi client has no engine reference — cannot dispatch download")

        track_id_str, display_name = filename.split('||', 1)
        try:
            track_id = int(track_id_str)
        except ValueError:
            logger.error(f"Invalid track ID: {track_id_str}")
            return None

        return self._engine.worker.dispatch(
            source_name='hifi',
            target_id=track_id,
            display_name=display_name,
            original_filename=filename,
            impl_callable=self._download_sync,
            extra_record_fields={
                'track_id': track_id,
                'display_name': display_name,
            },
        )

    def _download_sync(self, download_id: str, track_id: int, display_name: str) -> Optional[str]:
        quality_key = config_manager.get('hifi_download.quality', 'lossless')
        chain = ['hires', 'lossless', 'high', 'low']
        start = chain.index(quality_key) if quality_key in chain else 1
        allow_fallback = config_manager.get('hifi_download.allow_fallback', True)
        chain = chain[start:] if allow_fallback else [quality_key]

        MIN_AUDIO_SIZE = 100 * 1024

        for q_key in chain:
            if self.shutdown_check and self.shutdown_check():
                logger.info("Shutdown detected, aborting HiFi download")
                return None

            manifest_info = self._get_hls_manifest(track_id, quality=q_key)
            if (
                not manifest_info
                or (
                    not manifest_info.get('segment_uris')
                    and not manifest_info.get('direct_urls')
                )
            ):
                logger.warning(f"No HLS manifest at quality {q_key}, trying next")
                continue

            extension = manifest_info['extension']
            safe_name = re.sub(r'[<>:"/\\|?*]', '_', display_name)
            out_filename = f"{safe_name}.{extension}"
            out_path = self.download_path / out_filename

            is_direct = bool(manifest_info.get('direct_urls'))
            is_flac = q_key in ('hires', 'lossless') and not is_direct
            intermediate_path = out_path.with_suffix('.m4a') if is_flac else out_path

            try:
                init_uri = manifest_info.get('init_uri')
                segment_uris = manifest_info.get('segment_uris') or manifest_info.get('direct_urls') or []
                total_segments = len(segment_uris) + (1 if init_uri else 0)

                logger.info(f"Downloading from HiFi ({q_key}): {out_filename} "
                            f"({total_segments} {'URL(s)' if is_direct else 'segments'})")

                downloaded = 0
                speed_start = time.time()
                segments_completed = 0

                if self._engine is not None:
                    self._engine.update_record('hifi', download_id, {'size': 0})

                with intermediate_path.open('wb') as output_file:
                    if init_uri:
                        if self.shutdown_check and self.shutdown_check():
                            logger.info("Shutdown detected, aborting HiFi download")
                            intermediate_path.unlink(missing_ok=True)
                            return None

                        logger.debug(f"Downloading init segment: {init_uri}")
                        init_data = self._download_segment_with_retry(init_uri)
                        output_file.write(init_data)
                        downloaded += len(init_data)
                        segments_completed += 1

                        self._update_download_progress(download_id, downloaded,
                                                       segments_completed, total_segments, speed_start)

                    for segment_url in segment_uris:
                        if self.shutdown_check and self.shutdown_check():
                            logger.info("Shutdown detected, aborting HiFi download")
                            intermediate_path.unlink(missing_ok=True)
                            return None

                        segment_data = self._download_segment_with_retry(segment_url)
                        output_file.write(segment_data)
                        downloaded += len(segment_data)
                        segments_completed += 1

                        self._update_download_progress(download_id, downloaded,
                                                       segments_completed, total_segments, speed_start)

            except Exception as e:
                logger.warning(f"Download failed at quality {q_key}: {e}")
                intermediate_path.unlink(missing_ok=True)
                continue

            if downloaded < MIN_AUDIO_SIZE:
                logger.warning(f"File too small at {q_key} ({downloaded} bytes), trying next")
                intermediate_path.unlink(missing_ok=True)
                continue

            try:
                if is_flac:
                    logger.info(f"Demuxing FLAC from MP4 container: {intermediate_path} -> {out_path}")
                    self._demux_flac(intermediate_path, out_path)
                    intermediate_path.unlink(missing_ok=True)
                    final_size = out_path.stat().st_size if out_path.exists() else 0
                else:
                    final_size = intermediate_path.stat().st_size if intermediate_path.exists() else 0

                if final_size < MIN_AUDIO_SIZE:
                    logger.warning(f"Final file too small after processing at {q_key} "
                                   f"({final_size} bytes), trying next")
                    out_path.unlink(missing_ok=True)
                    continue

                logger.info(f"HiFi download complete ({q_key}): {out_path} "
                            f"({final_size / (1024*1024):.1f} MB)")
                return str(out_path)

            except Exception as e:
                logger.warning(f"Post-processing failed at quality {q_key}: {e}")
                out_path.unlink(missing_ok=True)
                intermediate_path.unlink(missing_ok=True)
                continue

        logger.error(f"All quality tiers exhausted for '{display_name}'")
        return None

    def _download_segment_with_retry(self, url: str) -> bytes:
        """Download a single HLS segment with 3 retries and 2s fixed backoff."""
        last_error = None
        for attempt in range(4):
            try:
                resp = self.session.get(url, allow_redirects=True, timeout=30)
                resp.raise_for_status()
                return resp.content
            except http_requests.exceptions.HTTPError as e:
                status = e.response.status_code if e.response is not None else 0
                if 400 <= status < 500:
                    raise
                last_error = e
            except (http_requests.exceptions.Timeout,
                    http_requests.exceptions.ConnectionError) as e:
                last_error = e

            if attempt < 3:
                if self.shutdown_check and self.shutdown_check():
                    raise RuntimeError("Shutdown requested")
                logger.warning(f"Segment download failed (attempt {attempt + 1}/4), "
                              f"retrying in 2s: {url}")
                time.sleep(2)

        raise last_error

    def _update_download_progress(self, download_id: str, downloaded: int,
                                  segments_completed: int, total_segments: int,
                                  speed_start: float):
        if self._engine is None:
            return
        record = self._engine.get_record('hifi', download_id)
        if record is None:
            return

        now = time.time()
        elapsed_total = now - speed_start
        speed = int(downloaded / elapsed_total) if elapsed_total > 0 else 0

        progress = record.get('progress', 0.0)
        if total_segments > 0:
            progress = round(min((segments_completed / total_segments) * 100, 99.9), 1)

        time_remaining = None
        if speed > 0:
            remaining_bytes = downloaded * (total_segments / max(segments_completed, 1)) - downloaded
            if remaining_bytes > 0:
                time_remaining = int(remaining_bytes / speed)

        self._engine.update_record('hifi', download_id, {
            'transferred': downloaded,
            'speed': speed,
            'progress': progress,
            'time_remaining': time_remaining,
        })

    def _record_to_status(self, record):
        return DownloadStatus(
            id=record['id'],
            filename=record['filename'],
            username=record['username'],
            state=record['state'],
            progress=record['progress'],
            size=record.get('size', 0),
            transferred=record.get('transferred', 0),
            speed=record.get('speed', 0),
            time_remaining=record.get('time_remaining'),
            file_path=record.get('file_path'),
        )

    async def get_all_downloads(self) -> List[DownloadStatus]:
        if self._engine is None:
            return []
        return [
            self._record_to_status(record)
            for record in self._engine.iter_records_for_source('hifi')
        ]

    async def get_download_status(self, download_id: str) -> Optional[DownloadStatus]:
        if self._engine is None:
            return None
        record = self._engine.get_record('hifi', download_id)
        return self._record_to_status(record) if record is not None else None

    async def cancel_download(self, download_id: str, username: str = None,
                              remove: bool = False) -> bool:
        if self._engine is None:
            return False
        if self._engine.get_record('hifi', download_id) is None:
            return False
        self._engine.update_record('hifi', download_id, {'state': 'Cancelled'})
        if remove:
            self._engine.remove_record('hifi', download_id)
        return True

    async def clear_all_completed_downloads(self) -> bool:
        if self._engine is None:
            return True
        terminal = {'Completed, Succeeded', 'Cancelled', 'Errored', 'Aborted'}
        for record in list(self._engine.iter_records_for_source('hifi')):
            if record.get('state') in terminal:
                self._engine.remove_record('hifi', record['id'])
        return True
