import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../shared/models/device_state.dart';
import '../shared/models/match.dart';
import '../shared/models/stream_session.dart';

enum DeviceRole { camera, controller }

class SessionState {
  const SessionState({
    this.session,
    this.match,
    this.connected = false,
    this.deviceRole = DeviceRole.controller,
    this.cameraDevice,
    this.elapsed = Duration.zero,
    this.viewerCount = 0,
    this.loading = false,
    this.error,
  });

  final StreamSession? session;
  final MatchModel? match;
  final bool connected;
  final DeviceRole deviceRole;
  final DeviceStateModel? cameraDevice;
  final Duration elapsed;
  final int viewerCount;
  final bool loading;
  final String? error;

  SessionState copyWith({
    StreamSession? session,
    MatchModel? match,
    bool? connected,
    DeviceRole? deviceRole,
    DeviceStateModel? cameraDevice,
    Duration? elapsed,
    int? viewerCount,
    bool? loading,
    String? error,
    bool clearError = false,
  }) {
    return SessionState(
      session: session ?? this.session,
      match: match ?? this.match,
      connected: connected ?? this.connected,
      deviceRole: deviceRole ?? this.deviceRole,
      cameraDevice: cameraDevice ?? this.cameraDevice,
      elapsed: elapsed ?? this.elapsed,
      viewerCount: viewerCount ?? this.viewerCount,
      loading: loading ?? this.loading,
      error: clearError ? null : (error ?? this.error),
    );
  }
}

class SessionNotifier extends StateNotifier<SessionState> {
  SessionNotifier() : super(const SessionState());

  void setSession(StreamSession session, {MatchModel? match}) {
    state = state.copyWith(
      session: session,
      match: match,
      clearError: true,
    );
  }

  void setMatch(MatchModel match) {
    state = state.copyWith(match: match);
  }

  void setConnected(bool connected) {
    state = state.copyWith(connected: connected);
  }

  void setDeviceRole(DeviceRole role) {
    state = state.copyWith(deviceRole: role);
  }

  void updateDeviceState(DeviceStateModel device) {
    if (device.deviceRole == 'camera') {
      state = state.copyWith(cameraDevice: device);
    }
    if (device.status != null && state.session != null) {
      state = state.copyWith(
        session: StreamSession(
          id: state.session!.id,
          matchId: state.session!.matchId,
          status: device.status!,
          platform: state.session!.platform,
          rtmpIngestUrl: state.session!.rtmpIngestUrl,
          youtubeBroadcastId: state.session!.youtubeBroadcastId,
          privacyStatus: state.session!.privacyStatus,
          qualityPreset: state.session!.qualityPreset,
          targetBitrate: state.session!.targetBitrate,
          startedAt: state.session!.startedAt,
          disconnectionCount: state.session!.disconnectionCount,
          score: state.session!.score,
          devices: state.session!.devices,
        ),
      );
    }
  }

  void setElapsed(Duration elapsed) {
    state = state.copyWith(elapsed: elapsed);
  }

  void setViewerCount(int count) {
    state = state.copyWith(viewerCount: count);
  }

  void applyCommand(String action) {
    final session = state.session;
    if (session == null) return;

    String newStatus = session.status;
    switch (action) {
      case 'start_stream':
        newStatus = 'live';
        break;
      case 'pause_stream':
        newStatus = 'paused';
        break;
      case 'stop_stream':
        newStatus = 'ended';
        break;
    }

    state = state.copyWith(
      session: StreamSession(
        id: session.id,
        matchId: session.matchId,
        status: newStatus,
        platform: session.platform,
        rtmpIngestUrl: session.rtmpIngestUrl,
        youtubeBroadcastId: session.youtubeBroadcastId,
        privacyStatus: session.privacyStatus,
        qualityPreset: session.qualityPreset,
        targetBitrate: session.targetBitrate,
        startedAt: session.startedAt,
        disconnectionCount: session.disconnectionCount,
        score: session.score,
        devices: session.devices,
      ),
    );
  }

  void setLoading(bool loading) {
    state = state.copyWith(loading: loading);
  }

  void setError(String message) {
    state = state.copyWith(loading: false, error: message);
  }

  void reset() {
    state = const SessionState();
  }
}

final sessionProvider = StateNotifierProvider<SessionNotifier, SessionState>(
  (ref) => SessionNotifier(),
);
