// lib/features/home/pages/credit_page.dart
import 'package:flutter/material.dart';
import 'package:story_ai/features/home/models/credit.dart';
import 'package:story_ai/features/home/services/credit_database.dart';
import 'package:story_ai/features/home/widgets/credit_list_item.dart';

class CreditPage extends StatefulWidget {
  const CreditPage({super.key});

  @override
  State<CreditPage> createState() => _CreditPageState();
}

class _CreditPageState extends State<CreditPage> {
  late final CreditDatabase _creditDb;
  final _scrollController = ScrollController();

  final List<Credit> _credits = [];
  int _currentPage = 1;
  bool _isLoading = false;
  bool _hasMore = true;
  final int _limit = 20;

  // Filter parameters
  CreditType? _filterType;
  DateTime? _filterStartTime;
  DateTime? _filterEndTime;
  String? _filterModel;
  CreditStatus? _filterStatus;
  RangeValues? _filterWordCount;

  @override
  void initState() {
    super.initState();
    _initialize();
    _scrollController.addListener(_onScroll);
  }

  Future<void> _initialize() async {
    _creditDb = await CreditDatabase.getInstance();
    _fetchCredits();
  }

  void _onScroll() {
    // Load more when we are 200 pixels from the bottom
    if (_scrollController.position.pixels >=
            _scrollController.position.maxScrollExtent - 200 &&
        !_isLoading) {
      _fetchCredits();
    }
  }

  Future<void> _fetchCredits({bool isRefresh = false}) async {
    if (_isLoading || (!_hasMore && !isRefresh)) return;

    setState(() {
      _isLoading = true;
      if (isRefresh) {
        _credits.clear();
        _currentPage = 1;
        _hasMore = true;
      }
    });

    final newCredits = await _creditDb.getCredits(
      sortAscending: false, // Show newest first
      page: _currentPage,
      limit: _limit,
      type: _filterType,
      startTime: _filterStartTime,
      endTime: _filterEndTime,
      model: _filterModel,
      status: _filterStatus,
      minWords: _filterWordCount?.start.round(),
      maxWords: _filterWordCount?.end.round(),
    );

    setState(() {
      _credits.addAll(newCredits);
      _currentPage++;
      _isLoading = false;
      if (newCredits.length < _limit) {
        _hasMore = false;
      }
    });
  }

  @override
  void dispose() {
    _scrollController.removeListener(_onScroll);
    _scrollController.dispose();
    super.dispose();
  }

  void _showFilterSheet() {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
      ),
      builder: (context) {
        // Use a StatefulWidget to manage the temporary state of the filters
        return StatefulBuilder(
          builder: (BuildContext context, StateSetter setSheetState) {
            // Helper for picking dates
            Future<void> pickDate(bool isStart) async {
              final date = await showDatePicker(
                context: context,
                initialDate: (isStart ? _filterStartTime : _filterEndTime) ??
                    DateTime.now(),
                firstDate: DateTime(2022),
                lastDate: DateTime.now().add(const Duration(days: 1)),
              );
              if (date != null) {
                setSheetState(() {
                  if (isStart) {
                    _filterStartTime = date;
                  } else {
                    _filterEndTime = date.add(
                        const Duration(days: 1, seconds: -1)); // End of the day
                  }
                });
              }
            }

            return Padding(
              padding: EdgeInsets.only(
                  left: 20,
                  right: 20,
                  top: 20,
                  bottom: MediaQuery.of(context).viewInsets.bottom + 20),
              child: SingleChildScrollView(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Text('Filter Credits',
                        style: Theme.of(context).textTheme.headlineSmall),
                    const SizedBox(height: 24),

                    // Type Filter
                    Text('Type',
                        style: Theme.of(context).textTheme.titleMedium),
                    const SizedBox(height: 8),
                    SegmentedButton<CreditType>(
                      segments: const [
                        ButtonSegment(
                            value: CreditType.story,
                            label: Text('Story'),
                            icon: Icon(Icons.history_edu)),
                        ButtonSegment(
                            value: CreditType.audio,
                            label: Text('Audio'),
                            icon: Icon(Icons.volume_up)),
                      ],
                      selected: _filterType == null ? {} : {_filterType!},
                      onSelectionChanged: (selection) {
                        setSheetState(
                            () => _filterType = selection.firstOrNull);
                      },
                    ),
                    const SizedBox(height: 16),

                    // Status Filter
                    Text('Status',
                        style: Theme.of(context).textTheme.titleMedium),
                    const SizedBox(height: 8),
                    SegmentedButton<CreditStatus>(
                      segments: const [
                        ButtonSegment(
                            value: CreditStatus.done,
                            label: Text('Done'),
                            icon: Icon(Icons.check_circle)),
                        ButtonSegment(
                            value: CreditStatus.cancel,
                            label: Text('Canceled'),
                            icon: Icon(Icons.cancel)),
                      ],
                      selected: _filterStatus == null ? {} : {_filterStatus!},
                      onSelectionChanged: (selection) {
                        setSheetState(
                            () => _filterStatus = selection.firstOrNull);
                      },
                    ),
                    const SizedBox(height: 16),

                    // Date Range Filter
                    Text('Date Range',
                        style: Theme.of(context).textTheme.titleMedium),
                    const SizedBox(height: 8),
                    Row(
                      children: [
                        Expanded(
                            child: OutlinedButton.icon(
                                onPressed: () => pickDate(true),
                                icon: const Icon(Icons.calendar_today),
                                label: Text(_filterStartTime
                                        ?.toLocal()
                                        .toString()
                                        .split(' ')[0] ??
                                    'Start Date'))),
                        const SizedBox(width: 8),
                        Expanded(
                            child: OutlinedButton.icon(
                                onPressed: () => pickDate(false),
                                icon: const Icon(Icons.calendar_today),
                                label: Text(_filterEndTime
                                        ?.toLocal()
                                        .toString()
                                        .split(' ')[0] ??
                                    'End Date'))),
                      ],
                    ),
                    const SizedBox(height: 16),

                    // Word Count Filter
                    Text(
                        'Word Count (${_filterWordCount?.start.round() ?? 'Any'} - ${_filterWordCount?.end.round() ?? 'Any'})',
                        style: Theme.of(context).textTheme.titleMedium),
                    RangeSlider(
                      values: _filterWordCount ?? const RangeValues(0, 5000),
                      min: 0,
                      max: 5000,
                      divisions: 50,
                      labels: RangeLabels(
                        _filterWordCount?.start.round().toString() ?? "0",
                        _filterWordCount?.end.round().toString() ?? "5000",
                      ),
                      onChanged: (values) =>
                          setSheetState(() => _filterWordCount = values),
                    ),
                    const SizedBox(height: 16),

                    // Model Filter
                    Text('Model Name',
                        style: Theme.of(context).textTheme.titleMedium),
                    const SizedBox(height: 8),
                    TextFormField(
                      initialValue: _filterModel,
                      decoration: const InputDecoration(
                          hintText: 'e.g., gpt-4-turbo',
                          border: OutlineInputBorder(),
                          prefixIcon: Icon(Icons.model_training)),
                      onChanged: (value) => _filterModel = value,
                    ),
                    const SizedBox(height: 24),

                    // Action Buttons
                    Row(
                      children: [
                        Expanded(
                          child: TextButton(
                            onPressed: () {
                              setSheetState(() {
                                _filterType = null;
                                _filterStartTime = null;
                                _filterEndTime = null;
                                _filterModel = null;
                                _filterStatus = null;
                                _filterWordCount = null;
                              });
                            },
                            child: const Text('Reset'),
                          ),
                        ),
                        const SizedBox(width: 8),
                        Expanded(
                          flex: 2,
                          child: ElevatedButton.icon(
                            icon: const Icon(Icons.check),
                            label: const Text('Apply Filters'),
                            style: ElevatedButton.styleFrom(
                                padding:
                                    const EdgeInsets.symmetric(vertical: 12)),
                            onPressed: () {
                              Navigator.pop(context); // Close sheet
                              _fetchCredits(
                                  isRefresh: true); // Apply filters and refresh
                            },
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            );
          },
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Credit History'),
        actions: [
          IconButton(
            icon: const Icon(Icons.filter_list),
            onPressed: _showFilterSheet,
            tooltip: 'Filter Credits',
          ),
        ],
      ),
      body: RefreshIndicator(
        onRefresh: () => _fetchCredits(isRefresh: true),
        child: _buildBody(),
      ),
    );
  }

  Widget _buildBody() {
    if (_isLoading && _credits.isEmpty) {
      return const Center(child: CircularProgressIndicator());
    }

    if (_credits.isEmpty) {
      return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.history_toggle_off, size: 60, color: Colors.grey),
            const SizedBox(height: 16),
            const Text(
              'No Credits Found',
              style: TextStyle(fontSize: 20),
            ),
            const SizedBox(height: 8),
            const Text(
              'Try adjusting your filters or creating new content.',
              style: TextStyle(color: Colors.grey),
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () => _fetchCredits(isRefresh: true),
              child: const Text('Refresh'),
            )
          ],
        ),
      );
    }

    return ListView.builder(
      controller: _scrollController,
      padding: const EdgeInsets.all(8.0),
      // Add 1 to item count for the loading indicator at the bottom
      itemCount: _credits.length + (_hasMore ? 1 : 0),
      itemBuilder: (context, index) {
        if (index == _credits.length) {
          return const Padding(
            padding: EdgeInsets.symmetric(vertical: 16.0),
            child: Center(child: CircularProgressIndicator()),
          );
        }
        return CreditListItem(credit: _credits[index]);
      },
    );
  }
}

import 'package:isar/isar.dart';
import 'package:story_ai/core/config/config_service.dart';
import 'package:story_ai/features/home/models/credit.dart';

class CreditDatabase {
  late final Isar _isar;

  static Future<CreditDatabase> getInstance() async {
    // A small helper to avoid re-opening the database in hot reloads
    if (Isar.instanceNames.contains('credit')) {
      return CreditDatabase._(Isar.getInstance('credit')!);
    }
    final dir = await ConfigService.getAppLocalDirectory();
    final isar = await Isar.open(
      [CreditSchema],
      directory: dir,
      name: 'credit',
    );
    return CreditDatabase._(isar);
  }

  CreditDatabase._(this._isar);

  Future<void> addCredit(Credit credit) async {
    await _isar.writeTxn(() async {
      await _isar.credits.put(credit);
    });
  }

  // Helper to add some mock data for testing
  Future<void> addMockData() async {
    final count = await _isar.credits.count();
    if (count > 0) return; // Don't add if data exists

    final mockCredits = List.generate(100, (i) {
      final type = i % 3 == 0 ? CreditType.audio : CreditType.story;
      return Credit()
        ..createTime = DateTime.now().subtract(Duration(days: i))
        ..type = type
        ..prompt = 'A mock prompt for item #$i about a magical forest.'
        ..words = type == CreditType.story ? 150 + (i * 5) : null
        ..inputTokens = 50 + i
        ..outputTokens = 200 + i
        ..audioBytes = type == CreditType.audio ? 1024 * (i + 1) : null
        ..model = i % 4 == 0 ? 'gpt-4-turbo' : 'gpt-3.5-turbo'
        ..cost = 0.0015 + (i * 0.0001)
        ..status = i % 10 == 0 ? CreditStatus.cancel : CreditStatus.done;
    });

    await _isar.writeTxn(() async {
      await _isar.credits.putAll(mockCredits);
    });
  }

  Future<List<Credit>> getCredits({
    required bool sortAscending,
    int page = 1,
    int limit = 20,
    CreditType? type,
    DateTime? startTime,
    DateTime? endTime,
    String? model,
    CreditStatus? status,
    // ADDED: Word count range filter
    int? minWords,
    int? maxWords,
  }) async {
    var query = _isar.credits.filter();

    if (type != null) {
      query = query.typeEqualTo(type);
    }

    // Isar supports filtering on nullable fields.
    // We can chain `greaterThan` and `lessThan` on the same property.
    if (startTime != null && endTime != null) {
      query = query.createTimeBetween(startTime, endTime);
    } else if (startTime != null) {
      query = query.createTimeGreaterThan(startTime);
    } else if (endTime != null) {
      query = query.createTimeLessThan(endTime);
    }

    if (model != null && model.isNotEmpty) {
      // Use contains for more flexible matching
      query = query.modelContains(model, caseSensitive: false);
    }

    if (status != null) {
      query = query.statusEqualTo(status);
    }

    // ADDED: Word count filter logic
    if (minWords != null && maxWords != null) {
      query = query.wordsBetween(minWords, maxWords);
    } else if (minWords != null) {
      query = query.wordsGreaterThan(minWords);
    } else if (maxWords != null) {
      query = query.wordsLessThan(maxWords);
    }
    QueryBuilder<Credit, Credit, QAfterFilterCondition> queryAfter =
        query.createTimeLessThan(DateTime.now());
    QueryBuilder<Credit, Credit, QAfterSortBy> sortQuery;
    if (sortAscending) {
      sortQuery = queryAfter.sortByCreateTime();
    } else {
      sortQuery = queryAfter.sortByCreateTimeDesc();
    }

    return await sortQuery.offset((page - 1) * limit).limit(limit).findAll();
  }
}



_initialize() in initialize() to create _creditDb, but not sync with build() function. Maybe enter build() that _creditDb is not created