import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:localstore/localstore.dart';

import '../providers/otp_provider.dart';

class OTPPage extends StatefulWidget {
  const OTPPage({Key? key}) : super(key: key);

  @override
  State<OTPPage> createState() => _OTPPageState();
}

class _OTPPageState extends State<OTPPage> {
  final TextEditingController _codigo = TextEditingController();
  final _otpProvider = OTPProvider();
  final db = Localstore.instance;

  late Timer _timer;
  late String _oneTimePwd;

  int _errorCounter = 0;
  int _minutes = 5;
  int _seconds = 0;
  bool _verifyActive = false;
  bool _isWaiting = true;
  dynamic _logInfo;

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

    _oneTimePwd = _generateKey();
    _init();
  }

  void _startTimer(){
    const oneSec = Duration(seconds: 1);
    _timer = Timer.periodic(oneSec, (timer) => setState(() {
      if(_minutes < 1 && _seconds < 1){
        timer.cancel();
      }else if(_seconds == 0){
        _minutes -= 1;
        _seconds = 59;
      }else{
        _seconds -= 1;
      }
    }));
  }

  String _generateKey(){
    final rand = Random();
    String num = rand.nextInt(999999).toString();

    num = num.length == 5 ? "0$num" : num.length == 4 ? "00$num" : num.length == 3 ? "000$num" : num.length == 2 ? "0000$num" : num.length == 1 ? "00000$num" : num;
    return num;
  }

  void _init() async{
    final items = await db.collection('quiosco').get();
    final key = items!.keys.last;

    final info = items[key];
    _logInfo = info;

    _otpProvider.fetchOTP(info['accessToken'], info['dinum'], _oneTimePwd,
      _formattedDate(DateTime.now().toIso8601String()),
      _formattedDate(DateTime.now().add(const Duration(minutes: 5)).toIso8601String()),
      DateTime.now().year.toString());

    _startTimer();
    setState(() => _isWaiting = false);
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final _screenSize = MediaQuery.of(context).size;
    return Scaffold(
      body: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            children: [
              const SizedBox(height: 32.0),
              Row(
                children: const [
                  SizedBox(
                    width: 32.0,
                  ),
                  Image(
                    image: AssetImage('assets/logo.png'),
                    width: 64.0,
                  ),
                  SizedBox(width: 16.0),
                  Expanded(
                    child: Image(
                      image: AssetImage('assets/logo_completo.png'),
                    ),
                  ),
                  SizedBox(width: 32.0)
                ],
              ),
              const SizedBox(height: 48.0),
              const Image(
                image: AssetImage('assets/quiosco.png'),
                width: 88.0,
                fit: BoxFit.cover,
              ),
              const SizedBox(height: 16.0),
              const Text(
                'QUIOSCO',
                textAlign: TextAlign.center,
                style: TextStyle(
                    fontFamily: 'Helvetica Neue Black Cond',
                    fontSize: 28.0
                ),
              ),
              const Text(
                'Colaborador',
                textAlign: TextAlign.center,
                style: TextStyle(
                    fontFamily: 'Helvetica Neue Light',
                    fontSize: 22.0,
                    fontWeight: FontWeight.w600,
                    color: Color.fromRGBO(104, 104, 104, 1)
                ),
              ),
              const SizedBox(height: 16.0),
              if(_seconds > 0 || _minutes > 0)
                Container(
                  margin: const EdgeInsets.symmetric(horizontal: 32.0),
                  child: Text(
                    'Hola ${_isWaiting ? '' : _logInfo['user']}, hemos enviado un código a tu correo. '
                        'Por favor introdúcelo debajo para saber que eres tú.',
                    textAlign: TextAlign.center,
                    style: const TextStyle(
                        fontFamily: 'Helvetica Neue Light',
                        fontSize: 16.0,
                        fontWeight: FontWeight.w300,
                        color: Colors.grey
                    ),
                  ),
                ),
              if(_seconds < 1 && _minutes < 1)
                Container(
                  margin: const EdgeInsets.symmetric(horizontal: 32.0),
                  child: Text(
                    'Hola ${_logInfo['user']}, el código anterior ha expirado. '
                        'Por favor genera uno nuevo.',
                    textAlign: TextAlign.center,
                    style: const TextStyle(
                        fontFamily: 'Helvetica Neue Light',
                        fontSize: 16.0,
                        fontWeight: FontWeight.w300,
                        color: Colors.grey
                    ),
                  ),
                ),
              const SizedBox(height: 8.0),
              Text(
                _time(_minutes, _seconds),
                textAlign: TextAlign.center,
                style: const TextStyle(
                    fontFamily: 'Helvetica Neue Light',
                    fontSize: 22.0,
                    fontWeight: FontWeight.w600,
                    color: Color.fromRGBO(104, 104, 104, 1)
                ),
              ),
              const SizedBox(height: 16.0),
              Container(
                margin: const EdgeInsets.symmetric(horizontal: 32.0),
                child: Column(
                  children: <Widget>[
                    if(_seconds > 0 || _minutes > 0)
                      TextField(
                        keyboardType: TextInputType.number,
                        controller: _codigo,
                        decoration: const InputDecoration(
                          hintText: 'Código de verificación:',
                          contentPadding: EdgeInsets.zero,
                        ),
                        maxLines: 1,
                        cursorColor: const Color.fromRGBO(180, 4, 4, 1),
                        style: const TextStyle(
                          fontSize: 20.0,
                        ),
                        onChanged: (value){
                          setState(() {
                            if(value.length == 6){
                              _verifyActive = true;
                            }else{
                              _verifyActive = false;
                            }
                          });
                        },
                      ),
                    if(_seconds < 1 && _minutes < 1)
                      MaterialButton(
                        elevation: 4.0,
                        padding: const EdgeInsets.symmetric(vertical: 8.0),
                        minWidth: _screenSize.width-64.0,
                        color: const Color.fromRGBO(255, 0, 0, 1),
                        child: const Text(
                          'Generar nuevo código',
                          style: TextStyle(
                            fontFamily: 'Helvetica Neue Black Cond',
                            fontSize: 28.0,
                            color: Colors.white,
                          ),
                        ),
                        onPressed: () async{
                          setState(() {
                            _minutes = 5;
                            _isWaiting = true;
                          });

                          _oneTimePwd = _generateKey();
                          await _otpProvider.fetchOTP(
                              _logInfo['accessToken'],
                              _logInfo['dinum'],
                              _oneTimePwd,
                              _formattedDate(DateTime.now().toIso8601String()),
                              _formattedDate(DateTime.now().add(const Duration(minutes: 5)).toIso8601String()),
                              DateTime.now().year.toString()
                          );

                          _startTimer();
                          setState(() {
                            _isWaiting = false;
                          });
                        },
                      ),
                    const SizedBox(height: 16.0),
                    if(_isWaiting)
                      const CircularProgressIndicator(),
                    if(!_isWaiting)
                      MaterialButton(
                        elevation: 4.0,
                        padding: const EdgeInsets.symmetric(vertical: 8.0),
                        minWidth: _screenSize.width-64.0,
                        color: const Color.fromRGBO(255, 0, 0, 1),
                        disabledColor: Colors.grey,
                        child: const Text(
                          'Verificar',
                          style: TextStyle(
                            fontFamily: 'Helvetica Neue Black Cond',
                            fontSize: 28.0,
                            color: Colors.white,
                          ),
                        ),
                        onPressed: !_verifyActive ? null : () async{
                          FocusScope.of(context).requestFocus(FocusNode());
                          if(_codigo.text == _oneTimePwd){ //Si entra en el intervalo de tiempo da true
                            Fluttertoast.showToast(
                              msg: 'Bienvenido ${_logInfo['user']}',
                              toastLength: Toast.LENGTH_SHORT,
                              gravity: ToastGravity.CENTER,
                              timeInSecForIosWeb: 1,
                            );
                            final action = await Navigator.pushNamed(context, 'home');

                            if(action == 'logout'){
                              Navigator.pop(context);
                            }else{
                              print(action);
                            }
                          }else{
                            setState(() {
                              Fluttertoast.showToast(
                                msg: 'Código inválido, intento ${_errorCounter + 1} de 3',
                                toastLength: Toast.LENGTH_SHORT,
                                gravity: ToastGravity.CENTER,
                                timeInSecForIosWeb: 1,
                              );

                              _codigo.text = '';
                              _verifyActive = false;

                              _errorCounter += 1;
                              if(_errorCounter > 2){
                                Fluttertoast.showToast(
                                  msg: 'Ha exedido el número de intentos permitidos.',
                                  toastLength: Toast.LENGTH_LONG,
                                  gravity: ToastGravity.CENTER,
                                  timeInSecForIosWeb: 3,
                                );
                                _minutes = 0;
                                _seconds = 0;
                              }
                            });
                          }
                        },
                      ),
                  ],
                ),
              ),
              const SizedBox(height: 32.0),
            ],
          ),
        ),
      ),
    );
  }

  String _formattedDate(String date){
    final year = date.substring(2, 4);
    final month = date.substring(5, 7);
    final day = date.substring(8, 10);
    final hour = date.substring(11, 13);
    final minuts = date.substring(14, 16);
    final seconds = date.substring(17, 19);

    return '$day/$month/$year $hour:$minuts:$seconds';
  }

  String _time(int min, int sec){
    if(sec < 10){
      return '0$min:0$sec';
    }else{
      return '0$min:$sec';
    }
  }
}
