import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:dio/dio.dart'; import '../../core/api/tmdb_api.dart'; import '../../core/api/backend_api.dart'; import '../shared/providers.dart'; class ImportScreen extends ConsumerStatefulWidget { const ImportScreen({super.key}); @override ConsumerState createState() => _ImportScreenState(); } class _ImportScreenState extends ConsumerState { final _movieCtrl = TextEditingController(text: '603, 27205'); // Matrix, Inception final _showCtrl = TextEditingController(text: '1396, 1399'); // Breaking Bad, GoT String _log = ''; bool _busy = false; void _append(String msg) => setState(() => _log += msg + '\n'); Future _importMovies() async { setState(() => _busy = true); final tmdb = ref.read(tmdbApiProvider); final backend = ref.read(backendApiProvider); final ids = _movieCtrl.text .split(RegExp(r'[,\s]+')) .where((s) => s.isNotEmpty) .map(int.parse); for (final id in ids) { try { _append('Film $id: TMDB laden …'); final json = await tmdb.getMovie(id); await backend.upsertMovie(json); _append('Film $id: OK ✓'); } catch (e) { _append('Film $id: Fehler → $e'); } } setState(() => _busy = false); } Future _importShows() async { setState(() => _busy = true); final tmdb = ref.read(tmdbApiProvider); final backend = ref.read(backendApiProvider); final ids = _showCtrl.text .split(RegExp(r'[,\s]+')) .where((s) => s.isNotEmpty) .map(int.parse); for (final showId in ids) { try { _append('Serie $showId: TMDB laden …'); final showJson = await tmdb.getShow(showId); print('SHOW JSON: $showJson'); // Debug-Ausgabe await backend.upsertShow(showJson); _append('Serie $showId: Show OK ✓'); final seasons = (showJson['seasons'] as List? ?? const []) .where((s) => (s['season_number'] ?? 0) is int) .cast>(); for (final s in seasons) { final seasonNo = (s['season_number'] as num).toInt(); if (seasonNo < 0) continue; _append(' S$seasonNo: TMDB Season laden …'); final seasonJson = await tmdb.getSeason(showId, seasonNo); final dbShowId = await _getDbShowIdByTmdb(backend, showId); final dbSeasonId = await backend.upsertSeason(dbShowId, seasonJson); _append(' S$seasonNo: Season OK (db:$dbSeasonId)'); final eps = (seasonJson['episodes'] as List? ?? const []) .cast>(); for (final e in eps) { await backend.upsertEpisode(dbSeasonId, e); } _append(' S$seasonNo: ${eps.length} Episoden OK ✓'); } } catch (e) { // 👇 Hier kommt der erweiterte Catch hin! if (e is DioException) { print('❗ TMDB DioException für $showId'); print('➡️ Request: ${e.requestOptions.uri}'); print('➡️ Response: ${e.response?.data}'); print('➡️ Status: ${e.response?.statusCode}'); } _append('Serie $showId: Fehler → $e'); } } setState(() => _busy = false); } Future _getDbShowIdByTmdb(BackendApi backend, int tmdbId) async { final id = await backend.getShowDbIdByTmdbId(tmdbId); if (id == null) { throw Exception( 'Show mit tmdb_id=$tmdbId nicht gefunden – zuerst upsert_show aufrufen.'); } return id; } @override Widget build(BuildContext context) { final inputStyle = const TextStyle(fontSize: 13); return Scaffold( appBar: AppBar(title: const Text('Import (TMDB → DB)')), body: Padding( padding: const EdgeInsets.all(12), child: Column( children: [ Row( children: [ const Text('Filme TMDB-IDs: '), const SizedBox(width: 8), Expanded( child: TextField(controller: _movieCtrl, style: inputStyle)), const SizedBox(width: 8), FilledButton( onPressed: _busy ? null : _importMovies, child: const Text('Import Filme'), ), ], ), const SizedBox(height: 12), Row( children: [ const Text('Serien TMDB-IDs: '), const SizedBox(width: 8), Expanded( child: TextField(controller: _showCtrl, style: inputStyle)), const SizedBox(width: 8), FilledButton( onPressed: _busy ? null : _importShows, child: const Text('Import Serien'), ), ], ), const SizedBox(height: 12), if (_busy) const LinearProgressIndicator(), const SizedBox(height: 12), Expanded( child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( border: Border.all(color: Colors.black12), borderRadius: BorderRadius.circular(8), ), alignment: Alignment.topLeft, child: SingleChildScrollView( child: SelectableText(_log, style: const TextStyle( fontFamily: 'monospace', fontSize: 12)), ), ), ), ], ), ), ); } }