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

import '../../../core/api/api_client.dart';
import '../data/boloes_repository.dart';
import 'bolao_page.dart';
import 'editor_de_regras.dart';
import 'rodada_page.dart';
import '../../../core/tema/tema.dart';

/// Criação de bolão. O admin escolhe campeonato e intervalo de rodadas — os
/// jogos já vêm carregados, porque cadastrar jogo a jogo é o que faz ele
/// desistir e voltar para a planilha.
class CriarBolaoPage extends ConsumerStatefulWidget {
  const CriarBolaoPage({super.key});

  @override
  ConsumerState<CriarBolaoPage> createState() => _CriarBolaoPageState();
}

class _CriarBolaoPageState extends ConsumerState<CriarBolaoPage> {
  final _form = GlobalKey<FormState>();
  final _nome = TextEditingController();
  final _de = TextEditingController();
  final _ate = TextEditingController();

  List<Competicao>? _competicoes;
  String? _competicao;
  String? _erro;

  /// Regras da criação. Começam no padrão do PRD: o admin casual não quer
  /// configurar nada, e mexer nisso é a exceção.
  ValoresDeRegras _regras = ValoresDeRegras.padrao;
  bool _mostrarRegras = false;
  bool _carregandoCompeticoes = true;
  bool _enviando = false;

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

  @override
  void dispose() {
    _nome.dispose();
    _de.dispose();
    _ate.dispose();
    super.dispose();
  }

  Future<void> _carregarCompeticoes() async {
    setState(() {
      _carregandoCompeticoes = true;
      _erro = null;
    });
    try {
      final lista = await ref.read(boloesRepositoryProvider).competicoes();
      if (!mounted) return;
      setState(() {
        _competicoes = lista;
        _competicao = lista.isNotEmpty ? lista.first.code : null;
        // Sugere o intervalo daqui até o fim do campeonato: o admin quase
        // sempre quer isso, e digitar dois números a menos importa.
        final atual = lista.isNotEmpty ? lista.first.rodadaAtual : null;
        if (atual != null) {
          _de.text = '${atual + 1}';
          _ate.text = '38';
        }
      });
    } on ApiError catch (e) {
      // Fonte indisponível é estado próprio, com retry — não tela vazia.
      if (mounted) setState(() => _erro = e.mensagem);
    } finally {
      if (mounted) setState(() => _carregandoCompeticoes = false);
    }
  }

  Future<void> _criar() async {
    setState(() => _erro = null);
    if (!_form.currentState!.validate() || _competicao == null) return;
    // Tabela inconsistente é bolão em que acertar mais vale menos. Barra aqui,
    // porque o servidor aceita qualquer combinação de 0 a 100.
    if (_regras.inconsistencia != null) {
      setState(() {
        _erro = _regras.inconsistencia;
        _mostrarRegras = true;
      });
      return;
    }

    setState(() => _enviando = true);
    try {
      final bolao = await ref
          .read(boloesRepositoryProvider)
          .criar(
            nome: _nome.text.trim(),
            competitionCode: _competicao!,
            rodadaInicial: int.parse(_de.text),
            rodadaFinal: int.parse(_ate.text),
            pontosExato: _regras.exato,
            pontosVencedorSaldo: _regras.vencedorSaldo,
            pontosVencedor: _regras.vencedor,
            ordemDesempate: _regras.ordemDesempate,
          );
      if (!mounted) return;

      // Bolão inteiro em rodadas que já começaram é criado com sucesso e é
      // inútil: ninguém palpita e o convite é recusado. Avisar aqui é a
      // diferença entre o admin corrigir agora e descobrir pelo grupo.
      if (bolao.openMatches == 0) {
        await showDialog<void>(
          context: context,
          builder: (_) => AlertDialog(
            title: const Text('Nenhum jogo com prazo aberto'),
            content: Text(
              'As rodadas ${bolao.matchdayFrom}–${bolao.matchdayTo} já '
              'começaram, então ninguém vai conseguir palpitar neste bolão — '
              'e o convite também será recusado, porque a entrada fecha no '
              'primeiro jogo.\n\nCrie outro bolão com rodadas que ainda não '
              'começaram.',
            ),
            actions: [
              TextButton(
                onPressed: () => Navigator.of(context).pop(),
                child: const Text('Entendi'),
              ),
            ],
          ),
        );
        if (!mounted) return;
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(
              'Bolão criado com ${bolao.totalMatches} jogos '
              '(${bolao.openMatches} com prazo aberto)',
            ),
            backgroundColor: CoresDoApp.sucesso,
          ),
        );
      }

      await Navigator.of(context).push(
        MaterialPageRoute<void>(
          builder: (_) => BolaoPage(
            poolId: bolao.id,
            nome: bolao.name,
            matchday: bolao.matchdayFrom,
            // Quem cria é admin permanente do bolão.
            souAdmin: true,
            rodadaFinal: bolao.matchdayTo,
          ),
        ),
      );
    } on ApiError catch (e) {
      if (mounted) setState(() => _erro = e.mensagem);
    } finally {
      if (mounted) setState(() => _enviando = false);
    }
  }

  String? _validarRodada(String? v) {
    final n = int.tryParse(v ?? '');
    if (n == null) return 'informe um número';
    if (n < 1 || n > 38) return 'entre 1 e 38';
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Criar bolão')),
      body: SafeArea(
        child: _carregandoCompeticoes
            ? const Center(child: CircularProgressIndicator())
            : _competicoes == null
            ? _ErroComRetry(
                mensagem: _erro ?? 'falha ao carregar',
                onRetry: _carregarCompeticoes,
              )
            : SingleChildScrollView(
                padding: const EdgeInsets.all(24),
                child: Form(
                  key: _form,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      TextFormField(
                        controller: _nome,
                        decoration: const InputDecoration(
                          labelText: 'Nome do bolão',
                          helperText: 'Ex: Bolão do setor',
                        ),
                        validator: (v) => (v == null || v.trim().length < 3)
                            ? 'dê um nome ao bolão'
                            : null,
                      ),
                      const SizedBox(height: 16),
                      DropdownButtonFormField<String>(
                        initialValue: _competicao,
                        decoration: const InputDecoration(
                          labelText: 'Campeonato',
                        ),
                        items: _competicoes!
                            .map(
                              (c) => DropdownMenuItem(
                                value: c.code,
                                child: Text(c.nome),
                              ),
                            )
                            .toList(),
                        onChanged: (v) => setState(() => _competicao = v),
                      ),
                      const SizedBox(height: 16),
                      Row(
                        children: [
                          Expanded(
                            child: TextFormField(
                              controller: _de,
                              keyboardType: TextInputType.number,
                              decoration: const InputDecoration(
                                labelText: 'Da rodada',
                              ),
                              validator: _validarRodada,
                            ),
                          ),
                          const SizedBox(width: 16),
                          Expanded(
                            child: TextFormField(
                              controller: _ate,
                              keyboardType: TextInputType.number,
                              decoration: const InputDecoration(
                                labelText: 'Até a rodada',
                              ),
                              validator: _validarRodada,
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 8),
                      // Negrito de verdade, não asterisco: `Text` não
                      // interpreta markdown, então `**assim**` aparecia
                      // literal na tela — justamente no aviso que precisa
                      // ser lido.
                      const Text.rich(
                        TextSpan(
                          children: [
                            TextSpan(
                              text:
                                  'A pontuação padrão é 10 para placar '
                                  'exato, 5 para vencedor e saldo, 3 para '
                                  'vencedor. ',
                            ),
                            TextSpan(
                              text: 'As regras travam no primeiro palpite',
                              style: TextStyle(fontWeight: FontWeight.bold),
                            ),
                            TextSpan(text: ' — depois dele ninguém muda mais.'),
                          ],
                        ),
                        style: TextStyle(fontSize: 12),
                      ),
                      const SizedBox(height: 8),
                      // Etapa opcional e recolhida: obrigar o admin a passar
                      // por configuração de pontos é o que faz ele desistir
                      // e voltar para a planilha.
                      Align(
                        alignment: Alignment.centerLeft,
                        child: TextButton.icon(
                          onPressed: () =>
                              setState(() => _mostrarRegras = !_mostrarRegras),
                          icon: Icon(
                            _mostrarRegras
                                ? Icons.expand_less
                                : Icons.expand_more,
                          ),
                          label: Text(
                            _mostrarRegras
                                ? 'Esconder regras'
                                : 'Mudar a pontuação e o desempate',
                          ),
                        ),
                      ),
                      if (_mostrarRegras)
                        EditorDeRegras(
                          valores: _regras,
                          onMudou: (v) => setState(() => _regras = v),
                        ),
                      if (_erro != null) ...[
                        const SizedBox(height: 16),
                        Text(
                          _erro!,
                          style: TextStyle(
                            color: Theme.of(context).colorScheme.error,
                          ),
                        ),
                      ],
                      const SizedBox(height: 24),
                      FilledButton(
                        onPressed: _enviando ? null : _criar,
                        child: _enviando
                            ? const SizedBox(
                                height: 20,
                                width: 20,
                                child: CircularProgressIndicator(
                                  strokeWidth: 2,
                                ),
                              )
                            : const Text('Criar bolão'),
                      ),
                    ],
                  ),
                ),
              ),
      ),
    );
  }
}

class _ErroComRetry extends StatelessWidget {
  const _ErroComRetry({required this.mensagem, required this.onRetry});
  final String mensagem;
  final VoidCallback onRetry;

  @override
  Widget build(BuildContext context) => 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(mensagem, textAlign: TextAlign.center),
          const SizedBox(height: 16),
          FilledButton(onPressed: onRetry, child: const Text('Tentar de novo')),
        ],
      ),
    ),
  );
}
