import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:isar/isar.dart'; import '../veri/isar_servisi.dart'; import '../veri/modeller/bolum.dart'; import '../veri/modeller/film_proje.dart'; import '../veri/modeller/sahne.dart'; /// Aktif (seçili) proje id'si — null ise hiçbir proje açık değil. final aktifProjeProvider = StateProvider((ref) => null); /// Aktif (seçili) bölüm id'si. final aktifBolumProvider = StateProvider((ref) => null); /// Tüm projeler (canlı). final projeListesiProvider = StreamProvider>((ref) { return isar.filmProjes.where().sortByOlusturmaDesc().watch(fireImmediately: true); }); /// Aktif projenin bölümleri (canlı, sezon/bölüm sıralı). final bolumListesiProvider = StreamProvider>((ref) { final projeId = ref.watch(aktifProjeProvider); if (projeId == null) return Stream.value(const []); return isar.bolums .filter() .projeIdEqualTo(projeId) .sortBySezonNo() .thenByBolumNo() .watch(fireImmediately: true); }); /// Aktif bölümün sahneleri (canlı, pano sırasına göre). final sahneListesiProvider = StreamProvider>((ref) { final bolumId = ref.watch(aktifBolumProvider); if (bolumId == null) return Stream.value(const []); return isar.sahnes .filter() .bolumIdEqualTo(bolumId) .sortBySira() .watch(fireImmediately: true); }); /// Üretimi süren tüm sahneler (bölümden bağımsız) — üretim tamamlanma takibi. final uretiliyorSahnelerProvider = StreamProvider>((ref) { return isar.sahnes .filter() .durumEqualTo(SahneDurumu.uretiliyor) .watch(fireImmediately: true); }); abstract final class FilmServisi { // --- Proje --- static Future projeKaydet(FilmProje p) => isar.writeTxn(() => isar.filmProjes.put(p)); /// Projeyi ve altındaki tüm bölüm + sahneleri siler. static Future projeSil(int projeId) => isar.writeTxn(() async { final bolumlar = await isar.bolums.filter().projeIdEqualTo(projeId).findAll(); for (final b in bolumlar) { await isar.sahnes.filter().bolumIdEqualTo(b.id).deleteAll(); } await isar.bolums.filter().projeIdEqualTo(projeId).deleteAll(); await isar.filmProjes.delete(projeId); }); // --- Bölüm --- static Future bolumKaydet(Bolum b) => isar.writeTxn(() => isar.bolums.put(b)); /// Bölümü ve altındaki tüm sahneleri siler. static Future bolumSil(int bolumId) => isar.writeTxn(() async { await isar.sahnes.filter().bolumIdEqualTo(bolumId).deleteAll(); await isar.bolums.delete(bolumId); }); /// Yeni bölüm için sıradaki bölüm numarasını üretir. static Future sonrakiBolumNo(int projeId, int sezonNo) async { final son = await isar.bolums .filter() .projeIdEqualTo(projeId) .sezonNoEqualTo(sezonNo) .sortByBolumNoDesc() .findFirst(); return (son?.bolumNo ?? 0) + 1; } // --- Sahne --- static Future sahneKaydet(Sahne s) => isar.writeTxn(() => isar.sahnes.put(s)); static Future sahneSil(int sahneId) => isar.writeTxn(() => isar.sahnes.delete(sahneId)); /// Yeni sahne için sıradaki pano sırasını üretir. static Future sonrakiSira(int bolumId) async { final son = await isar.sahnes .filter() .bolumIdEqualTo(bolumId) .sortBySiraDesc() .findFirst(); return (son?.sira ?? -1) + 1; } /// Sürükle-bırak sonrası sahneleri yeni sıraya göre yeniden numaralandırır. static Future sahneSiralariniGuncelle(List sirali) => isar.writeTxn(() async { for (var i = 0; i < sirali.length; i++) { sirali[i].sira = i; await isar.sahnes.put(sirali[i]); } }); /// Sahnenin üretim durumu/çıktı alanlarını günceller (üretim akışı için). static Future sahneDurumGuncelle( int sahneId, { SahneDurumu? durum, String? promptId, String? videoYolu, String? keyframeYolu, }) => isar.writeTxn(() async { final s = await isar.sahnes.get(sahneId); if (s == null) return; if (durum != null) s.durum = durum; if (promptId != null) s.uretimPromptId = promptId; if (videoYolu != null) s.uretilenVideoYolu = videoYolu; if (keyframeYolu != null) s.keyframeYolu = keyframeYolu; await isar.sahnes.put(s); }); /// AI'nin çözümlediği sahneleri bölüme ekler (mevcut sıranın sonuna). static Future senaryodanEkle( int bolumId, List sahneler, ) => isar.writeTxn(() async { var sira = await _sonrakiSiraTxn(bolumId); for (final s in sahneler) { s ..bolumId = bolumId ..sira = sira++; await isar.sahnes.put(s); } }); static Future _sonrakiSiraTxn(int bolumId) async { final son = await isar.sahnes .filter() .bolumIdEqualTo(bolumId) .sortBySiraDesc() .findFirst(); return (son?.sira ?? -1) + 1; } }