import 'dart:async';

import 'package:flutter/foundation.dart';

import '../models/ai_model.dart';
import '../models/api_response.dart';
import '../services/http_api_service.dart';
import 'debug_provider.dart';

class ModelProvider extends ChangeNotifier {
  ModelProvider({
    required HttpApiService httpApiService,
    required DebugProvider debugProvider,
  })  : _http = httpApiService,
        _debug = debugProvider;

  final HttpApiService _http;
  final DebugProvider _debug;

  ModelsSnapshot? _snapshot;
  bool _loading = false;
  bool _acting = false;
  String? _error;
  String? _status;
  Timer? _pollTimer;

  ModelsSnapshot? get snapshot => _snapshot;
  bool get isLoading => _loading;
  bool get isActing => _acting;
  String? get error => _error;
  String? get status => _status;

  Future<void> refresh() async {
    _loading = true;
    _error = null;
    notifyListeners();
    try {
      _snapshot = await _http.getModels();
      _debug.addHttpLog(
        'Loaded models',
        details: 'count=${_snapshot?.models.length ?? 0}',
      );
    } catch (error) {
      _error = error.toString();
      _debug.addHttpLog('Load models failed', details: _error);
    } finally {
      _loading = false;
      notifyListeners();
    }
  }

  Future<void> download(String modelId) async {
    await _runAction(() => _http.downloadModel(modelId), '下载已启动: $modelId');
    _startPolling();
  }

  Future<void> switchTo({required String modelId, required String kind}) async {
    await _runAction(
      () => _http.switchModel(modelId: modelId, kind: kind),
      '已切换: $modelId',
    );
    await refresh();
  }

  Future<void> delete(String modelId) async {
    await _runAction(() => _http.deleteModel(modelId), '已删除: $modelId');
    await refresh();
  }

  Future<void> _runAction(
    Future<ApiResponse> Function() action,
    String okStatus,
  ) async {
    if (_acting) return;
    _acting = true;
    _error = null;
    notifyListeners();
    try {
      final result = await action();
      _status = result.message.isNotEmpty ? result.message : okStatus;
      if (!result.isOk) {
        _error = _status;
      }
      _debug.addHttpLog('Model action ok', details: _status);
    } catch (error) {
      _error = error.toString();
      _status = _error;
      _debug.addHttpLog('Model action failed', details: _error);
    } finally {
      _acting = false;
      notifyListeners();
    }
  }

  void _startPolling() {
    _pollTimer?.cancel();
    var ticks = 0;
    _pollTimer = Timer.periodic(const Duration(seconds: 2), (timer) async {
      ticks += 1;
      await refresh();
      final downloading = _snapshot?.models.any(
            (m) => m.downloadProgress > 0 && m.downloadProgress < 100 && !m.downloaded,
          ) ??
          false;
      if (!downloading || ticks > 90) {
        timer.cancel();
      }
    });
  }

  @override
  void dispose() {
    _pollTimer?.cancel();
    super.dispose();
  }
}
