import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../app/theme.dart'; import '../../providers/session_provider.dart'; import '../../shared/api_client.dart'; import '../../shared/api_error.dart'; import '../../shared/models/match.dart'; import '../../shared/premium_dialog.dart'; import '../../shared/widgets/primary_cta.dart'; import '../../shared/widgets/screen_insets.dart'; import '../../shared/models/team.dart'; import '../matches/team_providers.dart'; class StepTransmission extends ConsumerStatefulWidget { const StepTransmission({ super.key, required this.match, required this.onBack, required this.onNext, }); final MatchModel match; final VoidCallback onBack; final VoidCallback onNext; @override ConsumerState createState() => _StepTransmissionState(); } class _StepTransmissionState extends ConsumerState { String _platform = 'matchlivetv'; String _privacy = 'public'; String? _youtubeChannel; bool _creating = false; void _syncYoutubeChannel(Team? team) { if (team == null) { _youtubeChannel = null; return; } if (!team.canChooseYoutubeChannel) { if (team.youtubeTeamChannelAvailable) { _youtubeChannel = 'team'; } else if (team.youtubePlatformAvailable) { _youtubeChannel = 'platform'; } else { _youtubeChannel = null; } return; } _youtubeChannel ??= 'platform'; } Future _createSession() async { setState(() => _creating = true); try { final client = ref.read(apiClientProvider); final session = await client.createSession( widget.match.id, platform: _platform, youtubeChannel: _platform == 'youtube' ? _youtubeChannel : null, privacyStatus: _privacy, qualityPreset: '720p_30_2.5mbps', targetBitrate: 2500000, targetFps: 30, ); ref.read(sessionProvider.notifier).setSession(session, match: widget.match); widget.onNext(); } on DioException catch (e) { final apiErr = ApiException.fromDio(e); if (mounted) { if (apiErr?.isPremiumRequired == true) { await showPremiumRequiredDialog( context, message: apiErr!.message, billingUrl: apiErr.billingUrl, ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(apiErr?.message ?? 'Errore nella creazione sessione')), ); } } } catch (_) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Errore nella creazione sessione')), ); } } finally { if (mounted) setState(() => _creating = false); } } void _onYoutubeTap(Team? team) { if (team == null) return; if (team.isYoutubeReady) { setState(() { _platform = 'youtube'; _syncYoutubeChannel(team); }); return; } if (team.canUseYoutube) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text( 'YouTube non è ancora disponibile. Riprova più tardi o usa Match Live TV sul sito.', ), ), ); return; } showPremiumRequiredDialog( context, message: 'YouTube Live richiede Premium Light o Full.', billingUrl: team.billingUrl, ); } String _youtubeSubtitle(Team? team) { if (team == null || !team.canUseYoutube) { return 'Premium Light o Full'; } if (!team.isYoutubeReady) { return 'Canale Match Live TV (in attivazione)'; } if (_platform == 'youtube' && team.canChooseYoutubeChannel) { return _youtubeChannel == 'team' ? 'Canale ${team.youtubeTeamChannelTitle ?? "società"}' : 'Canale Match Live TV'; } if (team.youtubeUsesPlatformChannel || team.youtubePlatformAvailable) { final label = team.youtubeChannelTitle; return label != null ? 'Canale $label' : 'Canale Match Live TV'; } final label = team.youtubeTeamChannelTitle ?? team.youtubeChannelTitle; return label != null ? 'Canale $label' : 'Canale società collegato'; } @override Widget build(BuildContext context) { final theme = Theme.of(context); final teamAsync = ref.watch(teamByIdProvider(widget.match.teamId)); return teamAsync.when( loading: () => const Center(child: CircularProgressIndicator(color: AppTheme.primaryRed)), error: (_, __) => const Center(child: Text('Errore caricamento squadra')), data: (team) { _syncYoutubeChannel(team); final youtubeSelectable = team != null && team.isYoutubeReady; final showYoutubeChannels = _platform == 'youtube' && team != null && team.canChooseYoutubeChannel; return SingleChildScrollView( padding: ScreenInsets.contentPadding(context, horizontal: 20, vertical: 12), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (team != null) ...[ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: AppTheme.surfaceElevated, borderRadius: BorderRadius.circular(10), border: Border.all(color: AppTheme.primaryRed.withValues(alpha: 0.3)), ), child: Text( 'Piano ${team.planName} · Staff ${team.staffLimitLabel}' '${team.concurrentStreamsLimit != null ? ' · Dirette ${team.concurrentStreamsUsed}/${team.concurrentStreamsLimit}' : ''}', style: theme.textTheme.bodySmall, ), ), const SizedBox(height: 12), ], Text('Piattaforma', style: theme.textTheme.titleLarge), const SizedBox(height: 12), _PlatformCard( title: 'Match Live TV', subtitle: 'Diretta sul nostro sito (incluso)', selected: _platform == 'matchlivetv', enabled: true, onTap: () => setState(() => _platform = 'matchlivetv'), ), const SizedBox(height: 8), _PlatformCard( title: 'YouTube Live', subtitle: _youtubeSubtitle(team), selected: _platform == 'youtube', enabled: youtubeSelectable, badge: team?.canUseYoutube == true ? null : 'Premium', onTap: () => _onYoutubeTap(team), ), if (showYoutubeChannels) ...[ const SizedBox(height: 16), Text('Canale YouTube', style: theme.textTheme.titleMedium), const SizedBox(height: 8), _PlatformCard( title: 'Match Live TV', subtitle: 'Canale ufficiale della piattaforma', selected: _youtubeChannel == 'platform', enabled: true, onTap: () => setState(() => _youtubeChannel = 'platform'), ), const SizedBox(height: 8), _PlatformCard( title: team!.youtubeTeamChannelTitle ?? 'Canale società', subtitle: 'Il tuo canale collegato', selected: _youtubeChannel == 'team', enabled: true, onTap: () => setState(() => _youtubeChannel = 'team'), ), ], const SizedBox(height: 24), Text('Visibilità', style: theme.textTheme.titleLarge), const SizedBox(height: 8), Text( 'Match Live TV e YouTube (canale nostro o società).', style: theme.textTheme.bodySmall, ), const SizedBox(height: 12), SegmentedButton( segments: const [ ButtonSegment( value: 'public', label: Text('Pubblico'), icon: Icon(Icons.public), ), ButtonSegment( value: 'unlisted', label: Text('Privato / non in elenco'), icon: Icon(Icons.link), ), ], selected: {_privacy}, onSelectionChanged: (s) => setState(() => _privacy = s.first), ), const SizedBox(height: 8), Text( _privacy == 'public' ? 'Compare nell\'elenco dirette e sul canale YouTube scelto.' : 'Solo chi ha il link. Non in elenco pubblico né nelle ricerche.', style: theme.textTheme.bodySmall?.copyWith(color: AppTheme.textSecondary), ), const SizedBox(height: 24), Text('Qualità', style: theme.textTheme.titleLarge), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppTheme.surfaceElevated, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppTheme.primaryRed.withValues(alpha: 0.4)), ), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('720p · 30fps · 2.5 Mbps', style: theme.textTheme.titleMedium), const SizedBox(height: 4), Text( 'Bitrate fisso consigliato per reti instabili', style: theme.textTheme.bodyMedium, ), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppTheme.primaryRed.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(6), ), child: Text( 'AUTO', style: theme.textTheme.labelLarge?.copyWith( color: AppTheme.primaryRed, fontSize: 11, ), ), ), ], ), ), const SizedBox(height: 32), Row( children: [ Expanded( child: OutlinedButton( onPressed: _creating ? null : widget.onBack, child: const Text('Indietro'), ), ), const SizedBox(width: 12), Expanded( flex: 2, child: PrimaryCta( label: 'AVANTI >', loading: _creating, onPressed: _createSession, icon: Icons.arrow_forward, ), ), ], ), ], ), ); }, ); } } class _PlatformCard extends StatelessWidget { const _PlatformCard({ required this.title, this.subtitle, required this.selected, required this.enabled, this.badge, this.onTap, }); final String title; final String? subtitle; final bool selected; final bool enabled; final String? badge; final VoidCallback? onTap; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Opacity( opacity: enabled ? 1 : 0.55, child: Material( color: Colors.transparent, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(10), child: Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: selected ? AppTheme.primaryRed.withValues(alpha: 0.15) : AppTheme.surfaceElevated, borderRadius: BorderRadius.circular(10), border: Border.all( color: selected ? AppTheme.primaryRed : Colors.transparent, ), ), child: Row( children: [ Icon( selected ? Icons.radio_button_checked : Icons.radio_button_off, color: selected ? AppTheme.primaryRed : AppTheme.textSecondary, ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: theme.textTheme.titleMedium), if (subtitle != null) Text(subtitle!, style: theme.textTheme.bodyMedium), ], ), ), if (badge != null) Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppTheme.textSecondary.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(6), ), child: Text(badge!, style: theme.textTheme.labelSmall), ), ], ), ), ), ), ); } }