// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import 'package:flutter_test/flutter_test.dart';
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';

void main() {
  group('WyattForm', () {
    final WyattForm form = WyattFormImpl(
      [
        FormInput(
          'email',
          const Email.pure(),
        ),
        FormInput(
          'password',
          const Password.pure(),
        ),
      ],
      name: 'signInForm',
    );

    test('returns inputs', () {
      final inputs = <
          FormInput<dynamic, FormInputValidator<dynamic, ValidationError>,
              dynamic>>[
        FormInput(
          'email',
          const Email.pure(),
        ),
        FormInput(
          'password',
          const Password.pure(),
        ),
      ];

      expect(form.inputs, inputs);
    });

    test('returns validation strategy', () {
      final strategy = form.formValidationStrategy;
      expect(strategy, const EveryInputValidator());
    });

    test('returns validator list', () {
      final validators = [
        const Email.pure(),
        const Password.pure(),
      ];
      expect(form.asValidatorList<dynamic, ValidationError>(), validators);
    });

    test('returns name', () {
      final name = form.name;
      expect(name, 'signInForm');
    });

    group('containsKey', () {
      test('returns `true` on key `email`', () {
        expect(form.containsKey('email'), true);
      });

      test('returns `true` on key `password`', () {
        expect(form.containsKey('password'), true);
      });

      test('return `false` on key `incorrect`', () {
        expect(form.containsKey('incorrect'), false);
      });
    });

    group('inputOf', () {
      test('returns email input', () {
        final input = FormInput<dynamic,
            FormInputValidator<dynamic, ValidationError>, dynamic>(
          'email',
          const Email.pure(),
        );

        expect(form.inputOf('email'), input);
      });

      test('returns password input', () {
        final input = FormInput<dynamic,
            FormInputValidator<dynamic, ValidationError>, dynamic>(
          'password',
          const Password.pure(),
        );

        expect(form.inputOf('password'), input);
      });

      test('throw on unknown key', () {
        expect(() => form.inputOf('incorrect'), throwsException);
      });
    });

    group('errorOf', () {
      final WyattForm errorForm = WyattFormImpl(
        [
          FormInput(
            'email',
            const Email.dirty('incorrect'),
          ),
          FormInput(
            'password',
            const Password.dirty('toto1234'),
          ),
        ],
        name: 'signInForm',
      );

      test('returns `invalid` on invalid input', () {
        expect(errorForm.errorOf('email'), ValidationStandardError.invalid);
      });

      test('returns `null` on valid input', () {
        expect(errorForm.errorOf('password'), isNull);
      });
    });

    group('errorOf', () {
      final WyattForm metadataForm = WyattFormImpl(
        [
          FormInput(
            'email',
            const Email.pure(),
            metadata: const FormInputMetadata<int>(
              extra: 1,
            ),
          ),
          FormInput(
            'password',
            const Password.pure(),
            metadata: const FormInputMetadata<int>(
              extra: 2,
            ),
          ),
        ],
        name: 'signInForm',
      );

      test('returns `1` on email extra', () {
        expect(metadataForm.metadataOf<int>('email').extra, 1);
      });

      test('returns `2` on password extra', () {
        expect(metadataForm.metadataOf<int>('password').extra, 2);
      });
    });
  });

  // TODO(hpcl): add more tests on WyattForm
}
