import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../core/config/app_config.dart';
import '../../../../core/network/dio_client.dart';
import '../../data/datasources/voice_datasource.dart';
import '../../data/repositories/voice_repository_impl.dart';
import '../../domain/entities/voice_session.dart';
import '../../domain/repositories/voice_repository.dart';
import '../../domain/usecases/end_voice_session.dart';
import '../../domain/usecases/start_voice_session.dart';

// ---------------------------------------------------------------------------
// Dependency providers
// ---------------------------------------------------------------------------

final voiceDatasourceProvider = Provider<VoiceDatasource>((ref) {
  final dio = ref.watch(dioClientProvider);
  return VoiceDatasource(dio);
});

final voiceRepositoryProvider = Provider<VoiceRepository>((ref) {
  final datasource = ref.watch(voiceDatasourceProvider);
  final config = ref.watch(appConfigProvider);
  return VoiceRepositoryImpl(datasource: datasource, config: config);
});

// ---------------------------------------------------------------------------
// Use case providers
// ---------------------------------------------------------------------------

final startVoiceSessionUseCaseProvider = Provider<StartVoiceSession>((ref) {
  return StartVoiceSession(ref.watch(voiceRepositoryProvider));
});

final endVoiceSessionUseCaseProvider = Provider<EndVoiceSession>((ref) {
  return EndVoiceSession(ref.watch(voiceRepositoryProvider));
});

// ---------------------------------------------------------------------------
// Voice call state
// ---------------------------------------------------------------------------

enum CallPhase { idle, ringing, connecting, active, ended, error }

class VoiceCallState {
  final CallPhase phase;
  final VoiceSession? session;
  final String? error;
  final bool isMuted;
  final bool isSpeakerOn;
  final Duration elapsed;

  const VoiceCallState({
    this.phase = CallPhase.idle,
    this.session,
    this.error,
    this.isMuted = false,
    this.isSpeakerOn = false,
    this.elapsed = Duration.zero,
  });

  VoiceCallState copyWith({
    CallPhase? phase,
    VoiceSession? session,
    String? error,
    bool? isMuted,
    bool? isSpeakerOn,
    Duration? elapsed,
  }) {
    return VoiceCallState(
      phase: phase ?? this.phase,
      session: session ?? this.session,
      error: error,
      isMuted: isMuted ?? this.isMuted,
      isSpeakerOn: isSpeakerOn ?? this.isSpeakerOn,
      elapsed: elapsed ?? this.elapsed,
    );
  }
}

// ---------------------------------------------------------------------------
// Voice call notifier
// ---------------------------------------------------------------------------

class VoiceCallNotifier extends StateNotifier<VoiceCallState> {
  final Ref _ref;

  VoiceCallNotifier(this._ref) : super(const VoiceCallState());

  /// Initiates the ringing phase (incoming call simulation).
  void startRinging() {
    state = state.copyWith(phase: CallPhase.ringing);
  }

  /// Accepts the call: creates a voice session and connects.
  Future<void> acceptCall() async {
    state = state.copyWith(phase: CallPhase.connecting, error: null);

    try {
      final useCase = _ref.read(startVoiceSessionUseCaseProvider);
      final session = await useCase.execute();
      state = state.copyWith(
        phase: CallPhase.active,
        session: session,
      );
    } catch (e) {
      state = state.copyWith(
        phase: CallPhase.error,
        error: '通话连接失败: $e',
      );
    }
  }

  /// Ends the active call and cleans up the session.
  Future<void> endCall() async {
    final sessionId = state.session?.id;
    state = state.copyWith(phase: CallPhase.ended);

    if (sessionId != null) {
      try {
        final useCase = _ref.read(endVoiceSessionUseCaseProvider);
        await useCase.execute(sessionId);
      } catch (_) {
        // Best-effort cleanup
      }
    }
  }

  /// Declines the incoming call.
  void declineCall() {
    state = state.copyWith(phase: CallPhase.ended);
  }

  /// Toggles microphone mute state.
  void toggleMute() {
    state = state.copyWith(isMuted: !state.isMuted);
  }

  /// Toggles speaker state.
  void toggleSpeaker() {
    state = state.copyWith(isSpeakerOn: !state.isSpeakerOn);
  }

  /// Updates the elapsed time (called by a periodic timer in the UI).
  void updateElapsed(Duration elapsed) {
    state = state.copyWith(elapsed: elapsed);
  }

  /// Resets the call state to idle.
  void reset() {
    state = const VoiceCallState();
  }
}

// ---------------------------------------------------------------------------
// Main providers
// ---------------------------------------------------------------------------

final voiceCallProvider =
    StateNotifierProvider<VoiceCallNotifier, VoiceCallState>((ref) {
  return VoiceCallNotifier(ref);
});

final callPhaseProvider = Provider<CallPhase>((ref) {
  return ref.watch(voiceCallProvider).phase;
});

final callElapsedProvider = Provider<Duration>((ref) {
  return ref.watch(voiceCallProvider).elapsed;
});

final isCallMutedProvider = Provider<bool>((ref) {
  return ref.watch(voiceCallProvider).isMuted;
});
