# Ultra-Performanslı Finans Uygulaması Stratejisi

## 🚀 Performans Hedefleri

### Metrikler
- **İlk Yükleme:** <500ms (Cold Start)
- **Sayfa Geçişi:** <100ms (Smooth 60 FPS)
- **Database Query:** <50ms (Indexed queries)
- **Grafik Render:** <200ms (İlk render)
- **PDF Oluşturma:** <2s (Background isolate)
- **Bellek Kullanımı:** <150MB (Ortalama)

---

## 🎯 Performans Stratejileri

### 1. Database Optimizasyonu

#### İndeksleme
```dart
// lib/apps/finans/core/models/hareket.model.dart
@collection
class Hareket {
  Id id = Isar.autoIncrement;

  @Index() // Hızlı tarih sorguları
  DateTime tarihi;

  @Index(composite: [CompositeIndex('tipi')]) // Composite index
  double miktar;

  @Index() // Kategori filtreleme
  String tipi; // "Gelir" / "Gider"
}
```

#### Query Optimizasyonu
```dart
// Kötü ❌
final tumHareketler = await isar.harekets.where().findAll();
final gelirler = tumHareketler.where((h) => h.tipi == "Gelir").toList();

// İyi ✅
final gelirler = await isar.harekets
  .filter()
  .tipiEqualTo("Gelir")
  .findAll();

// En İyi 🚀
final gelirler = await isar.harekets
  .filter()
  .tipiEqualTo("Gelir")
  .limit(50) // Pagination
  .findAll();
```

---

### 2. Önbellekleme (Caching) Sistemi

#### İstatistik Cache Servisi
```dart
// lib/apps/finans/core/services/cache/istatistik_cache.dart
class IstatistikCache extends GetxService {
  final _cache = <String, CachedData>{};
  final _cacheDuration = Duration(minutes: 5);

  Future<T?> getOrCompute<T>(
    String key,
    Future<T> Function() compute,
  ) async {
    final cached = _cache[key];
    if (cached != null && !cached.isExpired) {
      return cached.data as T;
    }

    final data = await compute();
    _cache[key] = CachedData(
      data: data,
      expiry: DateTime.now().add(_cacheDuration),
    );
    return data;
  }

  void invalidate(String key) => _cache.remove(key);
  void invalidateAll() => _cache.clear();
}

class CachedData {
  final dynamic data;
  final DateTime expiry;

  CachedData({required this.data, required this.expiry});

  bool get isExpired => DateTime.now().isAfter(expiry);
}
```

#### Kullanım
```dart
// lib/apps/finans/core/services/istatistik_servisi.dart
class IstatistikServisi extends GetxService {
  final cache = Get.find<IstatistikCache>();

  Future<double> toplamBakiye() async {
    return await cache.getOrCompute(
      'toplam_bakiye',
      () async {
        // Ağır hesaplama
        final hesaplar = await isar.hesaps.findAll();
        double toplam = 0;
        for (var hesap in hesaplar) {
          await hesap.islemler.load();
          toplam += _bakiyeHesapla(hesap);
        }
        return toplam;
      },
    );
  }

  // Cache invalidation
  Future<void> yeniIslemEklendi() async {
    cache.invalidateAll(); // Tüm istatistikler yeniden hesaplanacak
  }
}
```

---

### 3. Widget Optimizasyonu

#### Const Constructors
```dart
// Kötü ❌
Widget build(BuildContext context) {
  return Container(
    padding: EdgeInsets.all(16),
    child: Text('Merhaba'),
  );
}

// İyi ✅
Widget build(BuildContext context) {
  return Container(
    padding: const EdgeInsets.all(16),
    child: const Text('Merhaba'),
  );
}
```

#### Widget Separation
```dart
// Kötü ❌ - Tüm widget her seferinde rebuild olur
class HesapListesi extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Obx(() {
      final hesaplar = controller.hesaplar;
      return ListView.builder(
        itemCount: hesaplar.length,
        itemBuilder: (context, index) {
          final hesap = hesaplar[index];
          return HesapItem(hesap: hesap); // Her hesap rebuild
        },
      );
    });
  }
}

// İyi ✅ - Sadece değişen item rebuild olur
class HesapItem extends StatelessWidget {
  final Hesap hesap;
  const HesapItem({required this.hesap});

  @override
  Widget build(BuildContext context) {
    return Obx(() => Card(
      child: ListTile(
        title: Text(hesap.ismi),
        subtitle: Text('${hesap.bakiye.value} ₺'),
      ),
    ));
  }
}
```

#### ListView Performance
```dart
// En İyi 🚀 - Lazy loading + Caching
class HesapListesi extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: controller.hesaplar.length,
      cacheExtent: 500, // Önbellek boyutu
      addAutomaticKeepAlives: true,
      addRepaintBoundaries: true, // Repaint optimizasyonu
      itemBuilder: (context, index) {
        return HesapItem(
          key: ValueKey(controller.hesaplar[index].id),
          hesap: controller.hesaplar[index],
        );
      },
    );
  }
}
```

---

### 4. Grafik Optimizasyonu

#### fl_chart ile Performanslı Grafikler
```dart
// lib/apps/finans/uye/dashboard/widgets/grafikler/performansli_cizgi_grafik.dart
class PerformansliCizgiGrafik extends StatelessWidget {
  final List<FlSpot> spots;

  const PerformansliCizgiGrafik({required this.spots});

  @override
  Widget build(BuildContext context) {
    return RepaintBoundary( // Gereksiz repaint'leri engelle
      child: LineChart(
        LineChartData(
          lineBarsData: [
            LineBarData(
              spots: spots,
              isCurved: true,
              dotData: FlDotData(show: false), // Noktaları gizle = Performans
              belowBarData: BarAreaData(
                show: true,
                gradient: LinearGradient(
                  colors: [
                    Colors.blue.withOpacity(0.3),
                    Colors.blue.withOpacity(0.0),
                  ],
                ),
              ),
            ),
          ],
          gridData: FlGridData(show: false), // Grid gizle = Performans
          titlesData: _buildTitles(), // Lazy load
          borderData: FlBorderData(show: false),
        ),
        swapAnimationDuration: const Duration(milliseconds: 300),
        swapAnimationCurve: Curves.easeInOut,
      ),
    );
  }

  // Sadece gerektiğinde oluştur
  FlTitlesData _buildTitles() {
    return FlTitlesData(
      show: true,
      leftTitles: AxisTitles(
        sideTitles: SideTitles(
          showTitles: true,
          reservedSize: 40,
          getTitlesWidget: (value, meta) {
            // Formatla
            return Text('${value.toInt()}');
          },
        ),
      ),
      bottomTitles: AxisTitles(
        sideTitles: SideTitles(showTitles: false),
      ),
    );
  }
}
```

#### Grafik Veri Hazırlama (Background)
```dart
// lib/apps/finans/core/services/grafik_veri_servisi.dart
import 'dart:isolate';

class GrafikVeriServisi extends GetxService {
  Future<List<FlSpot>> aylikGelirGiderHazirla() async {
    // Ağır hesaplamayı isolate'de yap
    return await compute(_grafikVeriHesapla, await _veriGetir());
  }

  Future<Map<String, dynamic>> _veriGetir() async {
    final hareketler = await isar.harekets
      .filter()
      .tarihiGreaterThan(DateTime.now().subtract(Duration(days: 365)))
      .findAll();

    return {'hareketler': hareketler};
  }

  static List<FlSpot> _grafikVeriHesapla(Map<String, dynamic> data) {
    final hareketler = data['hareketler'] as List<Hareket>;
    final spots = <FlSpot>[];

    // Aylık gruplama
    final aylikToplam = <int, double>{};
    for (var hareket in hareketler) {
      final ay = hareket.tarihi.month;
      aylikToplam[ay] = (aylikToplam[ay] ?? 0) + hareket.miktar;
    }

    aylikToplam.forEach((ay, toplam) {
      spots.add(FlSpot(ay.toDouble(), toplam));
    });

    return spots..sort((a, b) => a.x.compareTo(b.x));
  }
}
```

---

### 5. Background İşlemler (Isolates)

#### PDF Oluşturma (Isolate)
```dart
// lib/apps/finans/core/services/pdf_servisi.dart
import 'dart:isolate';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;

class PDFServisi extends GetxService {
  Future<File> aylikRaporPdfOlustur(FinansalRapor rapor) async {
    // UI thread'i bloke etmeden PDF oluştur
    final pdfBytes = await compute(_pdfOlustur, rapor);

    final file = File('${await getTemporaryDirectory()}/rapor_${rapor.id}.pdf');
    await file.writeAsBytes(pdfBytes);
    return file;
  }

  static Future<Uint8List> _pdfOlustur(FinansalRapor rapor) async {
    final pdf = pw.Document();

    pdf.addPage(
      pw.Page(
        build: (pw.Context context) {
          return pw.Column(
            children: [
              pw.Text('Aylık Rapor', style: pw.TextStyle(fontSize: 24)),
              pw.SizedBox(height: 20),
              pw.Text('Gelir: ${rapor.toplamGelir} ₺'),
              pw.Text('Gider: ${rapor.toplamGider} ₺'),
              pw.Text('Net: ${rapor.netKar} ₺'),
            ],
          );
        },
      ),
    );

    return pdf.save();
  }
}
```

#### Periyodik İşlem Background Worker
```dart
// lib/apps/finans/core/services/background_worker_servisi.dart
import 'package:workmanager/workmanager.dart';

class BackgroundWorkerServisi extends GetxService {
  static const String PERIYODIK_ISLEM_TASK = "periyodik_islem_kontrol";

  Future<void> init() async {
    await Workmanager().initialize(
      callbackDispatcher,
      isInDebugMode: false,
    );

    // Her gün sabah 9:00'da çalış
    await Workmanager().registerPeriodicTask(
      PERIYODIK_ISLEM_TASK,
      PERIYODIK_ISLEM_TASK,
      frequency: Duration(hours: 24),
      initialDelay: _sabah9Hesapla(),
      constraints: Constraints(
        networkType: NetworkType.not_required,
      ),
    );
  }

  Duration _sabah9Hesapla() {
    final now = DateTime.now();
    final sabah9 = DateTime(now.year, now.month, now.day, 9, 0);
    if (now.isAfter(sabah9)) {
      return sabah9.add(Duration(days: 1)).difference(now);
    }
    return sabah9.difference(now);
  }
}

@pragma('vm:entry-point')
void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    switch (task) {
      case BackgroundWorkerServisi.PERIYODIK_ISLEM_TASK:
        await _periyodikIslemleriKontrolEt();
        break;
    }
    return Future.value(true);
  });
}

Future<void> _periyodikIslemleriKontrolEt() async {
  // Isar'ı aç
  final isar = await Isar.open(/* ... */);

  // Bugün vadesi gelenler
  final bugun = DateTime.now();
  final vadesiGelenler = await isar.periyodikIslemlers
    .filter()
    .ilkOdemeTarihiLessThan(bugun)
    .findAll();

  for (var islem in vadesiGelenler) {
    // Yeni hareket oluştur
    await isar.writeTxn(() async {
      final yeniHareket = Hareket()
        ..ismi = islem.ismi
        ..miktar = islem.miktar
        ..tarihi = bugun
        ..tipi = islem.tipi;
      await isar.harekets.put(yeniHareket);
    });

    // Bildirim gönder
    await _bildirimGonder(islem);
  }
}
```

---

### 6. State Management Optimizasyonu

#### Granular Obx Kullanımı
```dart
// Kötü ❌ - Tüm widget rebuild
class HesapDetay extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Obx(() => Column(
      children: [
        Text('Bakiye: ${controller.bakiye}'),
        Text('Hesap: ${controller.hesapAdi}'),
        Text('Para Birimi: ${controller.paraBirimi}'),
      ],
    ));
  }
}

// İyi ✅ - Sadece değişen kısım rebuild
class HesapDetay extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Obx(() => Text('Bakiye: ${controller.bakiye}')), // Sadece bakiye değişince
        Text('Hesap: ${controller.hesapAdi.value}'), // Static
        Text('Para Birimi: ${controller.paraBirimi.value}'), // Static
      ],
    );
  }
}
```

#### Worker Kullanımı (Debounce)
```dart
// lib/apps/finans/uye/hareketler/hareket_controller.dart
class HareketController extends GetxController {
  final aramaMetni = ''.obs;
  final filtrelenmisHareketler = <Hareket>[].obs;

  @override
  void onInit() {
    super.onInit();

    // Debounce: 500ms bekle, sonra ara
    debounce(
      aramaMetni,
      (_) => _aramaYap(),
      time: Duration(milliseconds: 500),
    );
  }

  Future<void> _aramaYap() async {
    if (aramaMetni.value.isEmpty) {
      filtrelenmisHareketler.value = tumHareketler;
      return;
    }

    // Background'da ara
    final sonuclar = await compute(_aramaIslemi, {
      'metin': aramaMetni.value,
      'hareketler': tumHareketler,
    });

    filtrelenmisHareketler.value = sonuclar;
  }

  static List<Hareket> _aramaIslemi(Map<String, dynamic> data) {
    final metin = data['metin'] as String;
    final hareketler = data['hareketler'] as List<Hareket>;

    return hareketler
      .where((h) => h.ismi.toLowerCase().contains(metin.toLowerCase()))
      .toList();
  }
}
```

---

### 7. Image Optimization

#### Cached Network Image
```dart
// pubspec.yaml
dependencies:
  cached_network_image: ^3.4.1

// Kullanım
CachedNetworkImage(
  imageUrl: controller.profilResmiUrl,
  placeholder: (context, url) => CircularProgressIndicator(),
  errorWidget: (context, url, error) => Icon(Icons.person),
  memCacheWidth: 200, // Memory'de resize
  maxWidthDiskCache: 400, // Disk'te resize
)
```

#### Asset Image Compression
```bash
# PNG -> WebP (90% küçülme)
flutter pub run flutter_native_splash:create
```

---

### 8. Pagination & Infinite Scroll

#### Performanslı Pagination
```dart
// lib/apps/finans/core/services/kok.servis.dart (güncellenmiş)
class IsarFullService<T> extends GetxService {
  final limit = 20.obs; // Başlangıçta 20 item
  final offset = 0.obs;
  final hasMore = true.obs;

  Future<void> dahaFazla() async {
    if (!hasMore.value) return;

    offset.value += limit.value;
    final yeniVeriler = await _fetchData(offset.value, limit.value);

    if (yeniVeriler.length < limit.value) {
      hasMore.value = false;
    }

    liste.addAll(yeniVeriler);
  }

  // Infinite scroll widget
  Widget buildList() {
    return NotificationListener<ScrollNotification>(
      onNotification: (notification) {
        if (notification is ScrollEndNotification) {
          final maxScroll = notification.metrics.maxScrollExtent;
          final currentScroll = notification.metrics.pixels;

          // %90'a geldiğinde yükle
          if (currentScroll >= maxScroll * 0.9) {
            dahaFazla();
          }
        }
        return false;
      },
      child: ListView.builder(/* ... */),
    );
  }
}
```

---

## 📦 Gerekli Paketler

```yaml
# pubspec.yaml
dependencies:
  # Performans
  flutter_riverpod: ^2.6.1          # Alternative state management
  cached_network_image: ^3.4.1      # Image caching
  flutter_cache_manager: ^3.4.1     # Generic caching

  # Background
  workmanager: ^0.5.2                # Background tasks
  flutter_local_notifications: ^18.0.1  # Notifications

  # Grafikler
  fl_chart: ^0.69.0                  # Charts

  # Export
  pdf: ^3.11.1                       # PDF generation

  # Dev Tools
  flutter_performance_profiler: ^0.0.1  # Performance monitoring
```

---

## 🔍 Performans Monitoring

```dart
// lib/core/performance_monitor.dart
class PerformanceMonitor {
  static void measureWidgetBuild(String widgetName, VoidCallback build) {
    final stopwatch = Stopwatch()..start();
    build();
    stopwatch.stop();

    if (stopwatch.elapsedMilliseconds > 16) { // 60 FPS = 16ms frame budget
      print('⚠️ SLOW WIDGET: $widgetName took ${stopwatch.elapsedMilliseconds}ms');
    }
  }

  static Future<T> measureAsyncOperation<T>(
    String operationName,
    Future<T> Function() operation,
  ) async {
    final stopwatch = Stopwatch()..start();
    final result = await operation();
    stopwatch.stop();

    print('⏱️ $operationName: ${stopwatch.elapsedMilliseconds}ms');
    return result;
  }
}

// Kullanım
await PerformanceMonitor.measureAsyncOperation(
  'Toplam Bakiye Hesapla',
  () => istatistikServisi.toplamBakiye(),
);
```

---

## ✅ Performans Checklist

### Database
- [x] İndeksler oluşturuldu
- [x] Composite index'ler tanımlandı
- [x] Query pagination aktif
- [x] Lazy relationship loading

### Widget
- [ ] Const constructor'lar kullanıldı
- [ ] RepaintBoundary kullanıldı
- [ ] Widget separation yapıldı
- [ ] Keys tanımlandı

### State Management
- [ ] Granular Obx kullanımı
- [ ] Debounce/Throttle uygulandı
- [ ] Worker'lar optimize edildi

### Caching
- [ ] İstatistik cache sistemi
- [ ] Image cache sistemi
- [ ] Query result cache

### Background
- [ ] PDF isolate
- [ ] Periyodik işlem worker
- [ ] Notification service

### Monitoring
- [ ] Performance profiler entegre
- [ ] Slow operation logging
- [ ] Memory leak detection

---

## 🎯 Sonraki Adımlar

1. **Önce:** Performans altyapısını kur (cache, isolate, monitoring)
2. **Sonra:** Dashboard'u performanslı geliştir
3. **En son:** Diğer özellikleri aynı pattern'le ekle

**Hedef:** Her özellik eklenirken performans testi geçsin! 🚀
