// Drift row → model adapters and reverse-write adapters for populating
// drift from REST responses (#357 plan C).
//
// The cache loses some server-derived fields:
//   - ArtistRef.coverUrl (server computes from most-recent album)
//   - AlbumRef.coverUrl (server-emitted derived path)
//   - TrackRef.streamUrl (could be reconstructed but kept empty for clarity)
// UI already handles empty coverUrl/streamUrl gracefully. REST cold-cache
// fallback briefly shows the real values before drift takes over.

import 'package:drift/drift.dart' as drift;

import '../models/album.dart';
import '../models/artist.dart';
import '../models/playlist.dart';
import '../models/track.dart';
import 'db.dart';

extension CachedArtistAdapter on CachedArtist {
  /// `coverAlbumId` lets the caller pass a representative album id so
  /// the ArtistRef carries a reconstructed `/api/albums/<id>/cover`
  /// URL. cached_artists doesn't store this directly — the server
  /// derives it from the most-recent album at query time — so drift
  /// readers that want the cover URL join cached_albums and pass the
  /// first album's id through. Empty string yields empty coverUrl,
  /// matching the server's behavior for endpoints that don't carry
  /// the lookup (artist detail, search, raw cached_artists row reads).
  ArtistRef toRef({String coverAlbumId = ''}) => ArtistRef(
        id: id,
        name: name,
        sortName: sortName,
        coverUrl: coverAlbumId.isNotEmpty
            ? '/api/albums/$coverAlbumId/cover'
            : '',
      );
}

extension ArtistRefDriftWrite on ArtistRef {
  CachedArtistsCompanion toDrift() => CachedArtistsCompanion.insert(
        id: id,
        name: name,
        sortName: sortName.isNotEmpty ? sortName : name,
      );
}

extension CachedAlbumAdapter on CachedAlbum {
  /// `artistName` is supplied by the joined CachedArtists row at query time.
  /// `coverUrl` is reconstructed deterministically from the album id —
  /// the server emits the same shape (see internal/api/convert.go:69).
  /// We don't need to persist it, so AlbumRef.coverUrl is non-empty
  /// even when the row was populated from a sync that didn't carry the
  /// derived URL.
  AlbumRef toRef({String artistName = ''}) => AlbumRef(
        id: id,
        title: title,
        sortTitle: sortTitle,
        artistId: artistId,
        artistName: artistName,
        coverUrl: '/api/albums/$id/cover',
      );
}

extension AlbumRefDriftWrite on AlbumRef {
  CachedAlbumsCompanion toDrift() => CachedAlbumsCompanion.insert(
        id: id,
        artistId: artistId,
        title: title,
        sortTitle: sortTitle.isNotEmpty ? sortTitle : title,
      );
}

extension CachedTrackAdapter on CachedTrack {
  /// `artistName` and `albumTitle` come from joined rows.
  TrackRef toRef({String artistName = '', String albumTitle = ''}) => TrackRef(
        id: id,
        title: title,
        albumId: albumId,
        albumTitle: albumTitle,
        artistId: artistId,
        artistName: artistName,
        trackNumber: trackNumber,
        discNumber: discNumber,
        durationSec: durationMs ~/ 1000,
      );
}

extension TrackRefDriftWrite on TrackRef {
  CachedTracksCompanion toDrift() => CachedTracksCompanion.insert(
        id: id,
        albumId: albumId,
        artistId: artistId,
        title: title,
        durationMs: drift.Value(durationSec * 1000),
        trackNumber: drift.Value(trackNumber),
        discNumber: drift.Value(discNumber),
      );
}

extension CachedPlaylistAdapter on CachedPlaylist {
  /// `ownerUsername` is server-derived; cache stores the userId only.
  /// Pass empty unless a join supplies it.
  /// `coverUrl` is reconstructed deterministically from the playlist
  /// id — the server serves the cached collage at this path
  /// (handleGetPlaylistCover). Mirrors the album-cover trick. When
  /// the server hasn't built a collage yet (system playlists with no
  /// tracks at build time), the endpoint 404s and PlaylistCard's
  /// ServerImage falls back to its slate placeholder.
  Playlist toRef({String ownerUsername = ''}) => Playlist(
        id: id,
        userId: userId,
        name: name,
        description: description,
        isPublic: isPublic,
        systemVariant: systemVariant,
        trackCount: trackCount,
        coverUrl: '/api/playlists/$id/cover',
        ownerUsername: ownerUsername,
        createdAt: '',
        updatedAt: '',
      );
}

extension PlaylistDriftWrite on Playlist {
  CachedPlaylistsCompanion toDrift() => CachedPlaylistsCompanion.insert(
        id: id,
        userId: userId,
        name: name,
        description: drift.Value(description),
        isPublic: drift.Value(isPublic),
        trackCount: drift.Value(trackCount),
        systemVariant: drift.Value(systemVariant),
      );
}
