import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';

import '../../features/auth/presentation/cadastro_page.dart';
import '../../features/auth/presentation/login_page.dart';
import '../../features/auth/presentation/sessao_controller.dart';
import '../../features/boloes/data/convite_pendente.dart';
import '../../features/home/presentation/home_page.dart';

/// Rotas do app. O redirect observa o estado da sessão: restaurada no cold
/// start, o participante entra direto sem ver tela de login.
final routerProvider = Provider<GoRouter>((ref) {
  final notificador = ValueNotifier<EstadoSessao>(const SessaoCarregando());
  ref.listen<EstadoSessao>(
    sessaoProvider,
    (_, novo) => notificador.value = novo,
    fireImmediately: true,
  );
  ref.onDispose(notificador.dispose);

  return GoRouter(
    initialLocation: '/',
    refreshListenable: notificador,
    redirect: (context, state) {
      final sessao = notificador.value;
      final rota = state.matchedLocation;
      // Deep link do convite: guarda o token **antes de qualquer outra
      // decisão**, inclusive antes da guarda de sessão carregando.
      //
      // No cold start a URI chega enquanto a sessão ainda está sendo restaurada
      // — é sempre esse o caso, porque o link é o que abriu o app. Deixar a
      // guarda de "carregando" vir primeiro descartava o token em silêncio: o
      // link abria o app e não fazia nada.
      if (rota.startsWith('/convite/')) {
        final token = Uri.decodeComponent(rota.substring('/convite/'.length));
        ref.read(convitePendenteProvider.notifier).guardar(token);
        // Sessão ainda carregando manda para a tela de espera; quando ela
        // resolve, o redirect roda de novo e leva ao destino certo. O token já
        // está guardado nos três caminhos.
        if (sessao is SessaoCarregando) return '/carregando';
        return sessao is Autenticado ? '/' : '/login';
      }

      if (sessao is SessaoCarregando) {
        return rota == '/carregando' ? null : '/carregando';
      }

      final autenticado = sessao is Autenticado;
      final emTelaPublica = rota == '/login' || rota == '/cadastro';

      if (!autenticado) return emTelaPublica ? null : '/login';
      if (emTelaPublica || rota == '/carregando') return '/';
      return null;
    },
    routes: [
      GoRoute(
        path: '/carregando',
        builder: (context, state) => const _Carregando(),
      ),
      GoRoute(path: '/login', builder: (context, state) => const LoginPage()),
      GoRoute(
        path: '/cadastro',
        builder: (context, state) => const CadastroPage(),
      ),
      GoRoute(path: '/', builder: (context, state) => const HomePage()),
      // Alvo do deep link. Nunca constrói tela: o redirect acima sempre desvia,
      // depois de guardar o token.
      GoRoute(
        path: '/convite/:token',
        builder: (context, state) => const HomePage(),
      ),
    ],
  );
});

class _Carregando extends StatelessWidget {
  const _Carregando();

  @override
  Widget build(BuildContext context) =>
      const Scaffold(body: Center(child: CircularProgressIndicator()));
}
