import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; import '../../durum/proje_durumu.dart'; import '../../servisler/csv_toplu_import.dart'; import '../../servisler/proje_deposu.dart'; import '../../servisler/proje_export_import.dart'; import '../proje_olustur/yeni_proje_dialog.dart'; class ProjelerSayfasi extends ConsumerWidget { const ProjelerSayfasi({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final liste = ref.watch(projelerListesiProvider); return Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text('Projeler', style: Theme.of(context).textTheme.headlineMedium), const Spacer(), OutlinedButton.icon( icon: const Icon(Icons.upload_file, size: 16), label: const Text('İçe aktar'), onPressed: () => _iceAktar(context, ref), ), const SizedBox(width: 8), OutlinedButton.icon( icon: const Icon(Icons.list_alt, size: 16), label: const Text('CSV toplu'), onPressed: () => _csvToplu(context, ref), ), const SizedBox(width: 8), FilledButton.icon( icon: const Icon(Icons.add), label: const Text('Yeni Proje'), onPressed: () => showDialog( context: context, builder: (_) => const YeniProjeDialog(), ), ), ], ), const SizedBox(height: 16), Expanded( child: liste.when( data: (l) { if (l.isEmpty) { return const Center( child: Text('Henüz proje yok. "Yeni Proje" ile başla.'), ); } return ListView.separated( itemCount: l.length, separatorBuilder: (_, __) => const SizedBox(height: 8), itemBuilder: (ctx, i) { final o = l[i]; return Card( child: ListTile( leading: const Icon(Icons.movie), title: Text(o.isim), subtitle: Text( '${o.klasorYolu}\nGüncellendi: ${o.guncellendi.toLocal()}', ), isThreeLine: true, onTap: () async { final p = await ProjeDeposu.yukle(o.klasorYolu); if (p != null) { ref.read(projeProvider.notifier).ayarla(p); if (ctx.mounted) ctx.go('/studyo'); } }, trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: const Icon(Icons.archive_outlined), tooltip: 'Dışa aktar (.fikoproj)', onPressed: () => _disaAktar(ctx, o), ), IconButton( icon: const Icon(Icons.delete_outline), onPressed: () async { final onay = await showDialog( context: ctx, builder: (dialogCtx) => AlertDialog( title: const Text('Projeyi sil?'), content: const Text( 'Disk klasörü dahil tamamen silinecek.', ), actions: [ TextButton( onPressed: () => Navigator.pop(dialogCtx, false), child: const Text('İptal'), ), FilledButton( onPressed: () => Navigator.pop(dialogCtx, true), child: const Text('Sil'), ), ], ), ); if (onay == true) { // Aktif proje silinen ise state'i temizle — // aksi halde studyo widget'ları silinmiş bir // projeye referans tutar. final aktif = ref.read(projeProvider); final aktifSiliniyor = aktif?.id == o.id; if (aktifSiliniyor) { ref.read(projeProvider.notifier).temizle(); // Video player ve dosya handle'larının // serbest bırakılması için kısa bekleme await Future.delayed( const Duration(milliseconds: 250)); } try { await ProjeDeposu.sil(o.id); } catch (e) { if (ctx.mounted) { ScaffoldMessenger.of(ctx).showSnackBar( SnackBar( backgroundColor: Colors.red.shade700, content: Text( 'Silme hatası (dosya kullanımda olabilir): $e', style: const TextStyle(color: Colors.white), ), ), ); } } ref.invalidate(projelerListesiProvider); } }, ), ], ), ), ); }, ); }, loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Text('Hata: $e'), ), ), ], ), ); } Future _disaAktar(BuildContext context, ProjeOzeti o) async { final result = await FilePicker.platform.saveFile( dialogTitle: 'Projeyi dışa aktar', fileName: '${o.isim.replaceAll(RegExp(r"[^\w-]"), "_")}.fikoproj', type: FileType.custom, allowedExtensions: ['fikoproj'], ); if (result == null) return; final proje = await ProjeDeposu.yukle(o.klasorYolu); if (proje == null) return; if (!context.mounted) return; showDialog( context: context, barrierDismissible: false, builder: (_) => const Center(child: CircularProgressIndicator()), ); try { await ProjeExportImport.disaAktar( proje: proje, hedefZipYolu: result, ); if (context.mounted) { Navigator.pop(context); // progress ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Dışa aktarıldı: $result')), ); } } catch (e) { if (context.mounted) { Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Hata: $e'), backgroundColor: Colors.red), ); } } } Future _iceAktar(BuildContext context, WidgetRef ref) async { final r = await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['fikoproj', 'zip'], ); if (r == null || r.files.single.path == null) return; final docs = await getApplicationDocumentsDirectory(); final hedef = p.join(docs.path, 'FikoYT-VideoStudyo', 'projeler'); if (!context.mounted) return; showDialog( context: context, barrierDismissible: false, builder: (_) => const Center(child: CircularProgressIndicator()), ); try { final proje = await ProjeExportImport.iceAktar( zipYolu: r.files.single.path!, hedefKokKlasor: hedef, ); if (context.mounted) { Navigator.pop(context); ref.invalidate(projelerListesiProvider); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(proje != null ? 'İçe aktarıldı: ${proje.isim}' : 'Hata: proje.json yok'), ), ); } } catch (e) { if (context.mounted) { Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Hata: $e'), backgroundColor: Colors.red), ); } } } Future _csvToplu(BuildContext context, WidgetRef ref) async { await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('CSV Toplu İçe Aktar'), content: SizedBox( width: 480, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'CSV formatı (UTF-8):', style: TextStyle(fontWeight: FontWeight.bold), ), const SizedBox(height: 4), Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Theme.of(ctx).colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(4), ), child: const SelectableText( 'proje_ismi,ses_dosyasi,gorsel_dosyasi,prompt,segment_suresi,cozunurluk,oran\n' 'Klip1,C:/sarki1.mp3,C:/img1.png,cinematic dawn,20,540p,16:9\n' 'Klip2,,,prompt only,10,720p,9:16', style: TextStyle(fontSize: 10, fontFamily: 'monospace'), ), ), const SizedBox(height: 12), Row( children: [ OutlinedButton.icon( icon: const Icon(Icons.copy, size: 14), label: const Text('Şablon kopyala'), onPressed: () { // Could copy to clipboard }, ), const Spacer(), FilledButton.icon( icon: const Icon(Icons.upload_file, size: 14), label: const Text('CSV seç'), onPressed: () async { final r = await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['csv'], ); if (r == null || r.files.single.path == null) return; final satirlar = await CsvTopluImport.oku(r.files.single.path!); if (!ctx.mounted) return; Navigator.pop(ctx); _csvIslemBaslat(context, ref, satirlar); }, ), ], ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Kapat'), ), ], ), ); } Future _csvIslemBaslat( BuildContext context, WidgetRef ref, List satirlar, ) async { if (satirlar.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('CSV boş veya format hatalı')), ); return; } final ilerlemeNotifier = ValueNotifier('Başlatılıyor...'); showDialog( context: context, barrierDismissible: false, builder: (_) => AlertDialog( title: Text('${satirlar.length} proje oluşturuluyor'), content: ValueListenableBuilder( valueListenable: ilerlemeNotifier, builder: (c, v, _) => Column( mainAxisSize: MainAxisSize.min, children: [ const LinearProgressIndicator(), const SizedBox(height: 8), Text(v, style: const TextStyle(fontSize: 12)), ], ), ), ), ); final sonuc = await CsvTopluImport.projeleriOlustur( satirlar: satirlar, ilerleme: (i, t, ad) { ilerlemeNotifier.value = '$i/$t · $ad'; }, ); if (context.mounted) { Navigator.pop(context); ref.invalidate(projelerListesiProvider); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('${sonuc.length} proje oluşturuldu')), ); } } }