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

import '../../../core/api/api_client.dart';
import '../data/participantes_repository.dart';
import 'participantes_page.dart';
import 'ranking_page.dart';

/// Avisos do bolão, lidos **dentro do app**.
///
/// Existe porque o push depende de credencial que não está nesta versão, e o
/// aviso precisa aparecer de todo jeito: descobrir por acaso que perdeu pontos
/// numa correção é o pior resultado possível (PR-7).
class AvisosPage extends ConsumerStatefulWidget {
  const AvisosPage({required this.poolId, required this.matchday, super.key});

  final String poolId;

  /// Rodada aberta ao tocar num aviso de correção — é onde está a conta do
  /// ponto que mudou.
  final int matchday;

  @override
  ConsumerState<AvisosPage> createState() => _AvisosPageState();
}

class _AvisosPageState extends ConsumerState<AvisosPage> {
  List<Aviso>? _avisos;
  String? _erro;
  bool _carregando = true;

  @override
  void initState() {
    super.initState();
    _carregar();
  }

  Future<void> _carregar() async {
    setState(() => _erro = null);
    try {
      final lista = await ref
          .read(participantesRepositoryProvider)
          .avisos(widget.poolId);
      if (!mounted) return;
      setState(() => _avisos = lista);
    } on ApiError catch (e) {
      if (mounted) setState(() => _erro = e.mensagem);
    } finally {
      if (mounted) setState(() => _carregando = false);
    }
  }

  Future<void> _marcarLido(Aviso a) async {
    if (a.lido) return;
    try {
      await ref
          .read(participantesRepositoryProvider)
          .marcarLido(widget.poolId, a.id);
      await _carregar();
    } on ApiError catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text(e.mensagem)));
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Avisos')),
      body: RefreshIndicator(onRefresh: _carregar, child: _corpo()),
    );
  }

  Widget _corpo() {
    if (_carregando) return const Center(child: CircularProgressIndicator());

    if (_avisos == null) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.all(32),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Icon(Icons.cloud_off, size: 48),
              const SizedBox(height: 12),
              Text(_erro ?? 'falha ao carregar', textAlign: TextAlign.center),
              const SizedBox(height: 16),
              FilledButton(
                onPressed: _carregar,
                child: const Text('Tentar de novo'),
              ),
            ],
          ),
        ),
      );
    }

    if (_avisos!.isEmpty) {
      return const Center(
        child: Padding(
          padding: EdgeInsets.all(32),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(Icons.notifications_none, size: 48),
              SizedBox(height: 12),
              Text('Nenhum aviso neste bolão'),
              SizedBox(height: 6),
              Text(
                'Você é avisado aqui quando um placar é corrigido e sua '
                'pontuação muda, e quando um prazo está fechando.',
                textAlign: TextAlign.center,
              ),
            ],
          ),
        ),
      );
    }

    return ListView.separated(
      itemCount: _avisos!.length,
      separatorBuilder: (_, _) => const Divider(height: 1),
      itemBuilder: (_, i) {
        final a = _avisos![i];
        return ListTile(
          leading: Icon(
            switch (a.kind) {
              'PRAZO_FECHANDO' => Icons.timer_outlined,
              'PLACAR_CORRIGIDO_MANUAL' => Icons.edit_note,
              'JOGO_REABERTO' => Icons.event_repeat,
              'PONTO_REVERTIDO' => Icons.undo,
              'BOLAO_RECRIADO' => Icons.autorenew,
              _ => Icons.published_with_changes,
            },
            // Não lido fica destacado: aviso que se perde no meio da lista não
            // cumpre a função de avisar.
            color: a.lido ? Theme.of(context).colorScheme.outline : null,
          ),
          title: Text(
            a.titulo,
            style: TextStyle(fontWeight: a.lido ? null : FontWeight.bold),
          ),
          subtitle: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(a.corpo),
              const SizedBox(height: 4),
              Text(
                _quando(a.criadoEm) +
                    // Correção manual é intervenção humana e precisa ficar
                    // visível como tal (PR-10).
                    (a.kind == 'PLACAR_CORRIGIDO_MANUAL'
                        ? ' · alterado pelo administrador'
                        : ''),
                style: TextStyle(
                  fontSize: 11,
                  color: Theme.of(context).colorScheme.outline,
                ),
              ),
            ],
          ),
          trailing: a.lido
              ? null
              : TextButton(
                  onPressed: () => _marcarLido(a),
                  child: const Text('Marcar lido'),
                ),
          // Aviso de pontuação leva ao extrato, que é onde está a conta: sem
          // isso o participante lê "sua pontuação mudou" e não tem para onde ir.
          onTap: a.kind.startsWith('PLACAR_CORRIGIDO')
              ? () {
                  if (!a.lido) _marcarLido(a);
                  Navigator.of(context).push(
                    MaterialPageRoute<void>(
                      builder: (_) => Scaffold(
                        appBar: AppBar(title: const Text('Extrato da rodada')),
                        body: ExtratoPage(
                          poolId: widget.poolId,
                          matchday: widget.matchday,
                        ),
                      ),
                    ),
                  );
                }
              : null,
          isThreeLine: true,
        );
      },
    );
  }

  String _quando(DateTime utc) {
    final l = utc.toLocal();
    return '${l.day.toString().padLeft(2, '0')}/'
        '${l.month.toString().padLeft(2, '0')} às '
        '${l.hour.toString().padLeft(2, '0')}:'
        '${l.minute.toString().padLeft(2, '0')}';
  }
}
