// Version: 1.3.0 | Created: 2026-04-01 | Updated: 2026-04-03
// Full call screen with LiveKit video/audio.
// - Remote video: full screen background
// - Local video: picture-in-picture overlay (bottom right)
// - Controls: mute, toggle video, end call
// - Duration timer and participant name

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart' show RTCVideoViewObjectFit;
import 'package:go_router/go_router.dart';
import 'package:livekit_client/livekit_client.dart';

import '../data/livekit_service.dart';
import '../domain/call_state.dart';
import 'call_controller.dart';

class CallScreen extends ConsumerStatefulWidget {
  const CallScreen({
    super.key,
    required this.roomId,
    this.isVideo = true,
  });

  final String roomId;
  final bool isVideo;

  @override
  ConsumerState<CallScreen> createState() => _CallScreenState();
}

class _CallScreenState extends ConsumerState<CallScreen> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      ref.read(callControllerProvider.notifier).joinCall(
            Uri.decodeComponent(widget.roomId),
            withVideo: widget.isVideo,
          );
    });
  }

  @override
  Widget build(BuildContext context) {
    final callState = ref.watch(callControllerProvider);

    // On call ended: show error reason for 3 seconds before popping,
    // so the user can see WHY the call failed.
    ref.listen<CallState>(callControllerProvider, (_, next) {
      if (next is CallEnded && mounted) {
        final reason = next.reason;
        if (reason != null && reason.isNotEmpty) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(
              content: Text(reason),
              backgroundColor: Theme.of(context).colorScheme.error,
              duration: const Duration(seconds: 3),
            ),
          );
        }
        // Delay pop so the user sees the error.
        final nav = GoRouter.of(context);
        Future.delayed(const Duration(seconds: 3), () {
          if (mounted) nav.pop();
        });
      }
    });

    return Scaffold(
      backgroundColor: Colors.black,
      body: SafeArea(
        child: Stack(
          children: [
            // Remote video — full screen
            const _RemoteVideoView(),

            // Local PiP — bottom right
            if (callState is CallActive && callState.isVideoEnabled)
              const _LocalVideoPip(),

            // Connecting / connecting overlay
            if (callState is CallConnecting) const _ConnectingOverlay(),

            // Call controls — pinned to bottom
            Positioned(
              left: 0,
              right: 0,
              bottom: 24,
              child: _CallControls(roomId: widget.roomId),
            ),

            // Participant info — top left
            Positioned(
              top: 16,
              left: 16,
              child: _CallInfo(callState: callState),
            ),
          ],
        ),
      ),
    );
  }
}

// ---------------------------------------------------------------------------
// Remote video view
// ---------------------------------------------------------------------------

/// Listens to the LiveKit Room's ChangeNotifier so it rebuilds when
/// remote participants join/leave or publish/unpublish tracks.
/// Also watches callControllerProvider so it rebuilds when the call state
/// transitions (connecting → active) — that's when activeRoom becomes non-null.
class _RemoteVideoView extends ConsumerWidget {
  const _RemoteVideoView();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Watch call state to trigger rebuild when call connects.
    ref.watch(callControllerProvider);
    final room = ref.watch(liveKitServiceProvider).activeRoom;
    if (room == null) {
      return const _NoVideoPlaceholder();
    }

    // Room extends ChangeNotifier — rebuilds on every participant/track event.
    return ListenableBuilder(
      listenable: room,
      builder: (context, _) {
        final remoteParticipants = room.remoteParticipants.values.toList();
        if (remoteParticipants.isEmpty) {
          return const _NoVideoPlaceholder();
        }

        final firstParticipant = remoteParticipants.first;
        final videoPubs = firstParticipant.videoTrackPublications;
        if (videoPubs.isEmpty || videoPubs.first.track == null) {
          // Participant joined but no video track yet — show audio indicator.
          return _AudioOnlyPlaceholder(name: firstParticipant.identity);
        }

        final videoTrack = videoPubs.first.track!;
        return VideoTrackRenderer(
          videoTrack,
          fit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
        );
      },
    );
  }
}

// ---------------------------------------------------------------------------
// Local PiP
// ---------------------------------------------------------------------------

class _LocalVideoPip extends ConsumerWidget {
  const _LocalVideoPip();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    ref.watch(callControllerProvider); // rebuild when call state changes
    final room = ref.watch(liveKitServiceProvider).activeRoom;
    if (room == null) return const SizedBox.shrink();

    return ListenableBuilder(
      listenable: room,
      builder: (context, _) {
        final local = room.localParticipant;
        if (local == null) return const SizedBox.shrink();

        final videoPubs = local.videoTrackPublications;
        if (videoPubs.isEmpty || videoPubs.first.track == null) {
          return const SizedBox.shrink();
        }

        final localTrack = videoPubs.first.track!;
        return Positioned(
          right: 16,
          bottom: 120,
          child: Container(
            width: 100,
            height: 150,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(12),
              border: Border.all(color: Colors.white38, width: 1),
            ),
            clipBehavior: Clip.hardEdge,
            child: VideoTrackRenderer(
              localTrack,
              mirrorMode: VideoViewMirrorMode.mirror,
            ),
          ),
        );
      },
    );
  }
}

// ---------------------------------------------------------------------------
// Placeholders and overlays
// ---------------------------------------------------------------------------

class _AudioOnlyPlaceholder extends StatelessWidget {
  const _AudioOnlyPlaceholder({required this.name});
  final String name;

  @override
  Widget build(BuildContext context) {
    final initials = name.isNotEmpty ? name[0].toUpperCase() : '?';
    return Container(
      color: const Color(0xFF1A1A2E),
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CircleAvatar(
              radius: 48,
              backgroundColor: const Color(0xFF5C35C9),
              child: Text(initials,
                  style: const TextStyle(fontSize: 36, color: Colors.white)),
            ),
            const SizedBox(height: 16),
            Text(name,
                style: const TextStyle(color: Colors.white, fontSize: 18)),
            const SizedBox(height: 8),
            Text('Audio only',
                style: TextStyle(
                    color: Colors.white.withAlpha(153), fontSize: 14)),
          ],
        ),
      ),
    );
  }
}

class _NoVideoPlaceholder extends StatelessWidget {
  const _NoVideoPlaceholder();

  @override
  Widget build(BuildContext context) {
    return Container(
      color: const Color(0xFF1A1A2E),
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(
              Icons.person_outline,
              size: 96,
              color: Colors.white.withAlpha(77),
            ),
            const SizedBox(height: 12),
            Text(
              'Waiting for video...',
              style: TextStyle(
                color: Colors.white.withAlpha(153),
                fontSize: 16,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _ConnectingOverlay extends StatelessWidget {
  const _ConnectingOverlay();

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black.withAlpha(153),
      child: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CircularProgressIndicator(color: Colors.white),
            SizedBox(height: 16),
            Text(
              'Connecting...',
              style: TextStyle(color: Colors.white, fontSize: 18),
            ),
          ],
        ),
      ),
    );
  }
}

// ---------------------------------------------------------------------------
// Call info (top)
// ---------------------------------------------------------------------------

class _CallInfo extends StatelessWidget {
  const _CallInfo({required this.callState});

  final CallState callState;

  @override
  Widget build(BuildContext context) {
    final durationText = switch (callState) {
      CallActive(:final duration) => _formatDuration(duration),
      CallConnecting() => 'Connecting…',
      _ => '',
    };

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        if (durationText.isNotEmpty)
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
            decoration: BoxDecoration(
              color: Colors.black54,
              borderRadius: BorderRadius.circular(8),
            ),
            child: Text(
              durationText,
              style: const TextStyle(
                color: Colors.white,
                fontSize: 14,
                fontFeatures: [FontFeature.tabularFigures()],
              ),
            ),
          ),
      ],
    );
  }

  String _formatDuration(Duration d) {
    final minutes = d.inMinutes.remainder(60).toString().padLeft(2, '0');
    final seconds = d.inSeconds.remainder(60).toString().padLeft(2, '0');
    return '${d.inHours > 0 ? '${d.inHours}:' : ''}$minutes:$seconds';
  }
}

// ---------------------------------------------------------------------------
// Call controls (bottom)
// ---------------------------------------------------------------------------

class _CallControls extends ConsumerWidget {
  const _CallControls({required this.roomId});

  final String roomId;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final callState = ref.watch(callControllerProvider);
    final notifier = ref.read(callControllerProvider.notifier);

    final isAudioEnabled = callState is CallActive
        ? callState.isAudioEnabled
        : true;
    final isVideoEnabled = callState is CallActive
        ? callState.isVideoEnabled
        : true;

    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        // Mute button
        _ControlButton(
          icon: isAudioEnabled ? Icons.mic : Icons.mic_off,
          label: isAudioEnabled ? 'Mute' : 'Unmute',
          onTap: () => notifier.toggleAudio(),
          active: isAudioEnabled,
        ),
        // End call button — prominent red
        GestureDetector(
          onTap: () async {
            await notifier.endCall();
            if (context.mounted && context.canPop()) context.pop();
          },
          child: Container(
            width: 72,
            height: 72,
            decoration: const BoxDecoration(
              color: Colors.red,
              shape: BoxShape.circle,
            ),
            child: const Icon(Icons.call_end, color: Colors.white, size: 32),
          ),
        ),
        // Video toggle
        _ControlButton(
          icon: isVideoEnabled ? Icons.videocam : Icons.videocam_off,
          label: isVideoEnabled ? 'Hide video' : 'Show video',
          onTap: () => notifier.toggleVideo(),
          active: isVideoEnabled,
        ),
      ],
    );
  }
}

class _ControlButton extends StatelessWidget {
  const _ControlButton({
    required this.icon,
    required this.label,
    required this.onTap,
    required this.active,
  });

  final IconData icon;
  final String label;
  final VoidCallback onTap;
  final bool active;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: 56,
            height: 56,
            decoration: BoxDecoration(
              color: active
                  ? Colors.white.withAlpha(51)
                  : Colors.white.withAlpha(26),
              shape: BoxShape.circle,
            ),
            child: Icon(icon, color: Colors.white, size: 24),
          ),
          const SizedBox(height: 6),
          Text(
            label,
            style: const TextStyle(color: Colors.white70, fontSize: 11),
          ),
        ],
      ),
    );
  }
}
