import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:design_system/design_system.dart';

void main() {
  themePackages();

  testGoldens('Step Indicator', (tester) async {
    StepIndicator stepIndicator(int step) =>
        StepIndicator(total: 3, current: step, color: Colors.blueAccent);

    final builder = GoldenBuilder.column()
      ..addScenario('step -1', stepIndicator(-1))
      ..addScenario('step 0', stepIndicator(0))
      ..addScenario('step 1', stepIndicator(1))
      ..addScenario('step 2', stepIndicator(2))
      ..addScenario('step 3', stepIndicator(3))
      ..addScenario('step 4', stepIndicator(4));

    await tester.pumpWidgetBuilder(builder.build());
    await screenMatchesGolden(tester, 'step_indicator');
  });

  testGoldens('Progress Bar - Small', (tester) async {
    ProgressBar progressBar(double value, double max) => ProgressBar(
      max: max,
      value: value,
      height: 24,
      textSize: 16,
      textSecondarySize: 12,
      backgroundColor: Colors.blueGrey,
      foregroundColor: Colors.blueAccent,
      textColor: Colors.black87,
    );

    final builder = GoldenBuilder.column()
      ..addScenario('full', progressBar(100, 100))
      ..addScenario('empty', progressBar(0, 100))
      ..addScenario('half', progressBar(75, 150))
      ..addScenario('overflowing', progressBar(200, 150))
      // ..addScenario('negative', progressBar(-20, 83))
      ..addScenario('tiny value', progressBar(2.15, 150));

    await tester.pumpWidgetBuilder(builder.build());
    await screenMatchesGolden(tester, 'progress_bar_small');
  });

  testGoldens('Progress Bar - Large', (tester) async {
    ProgressBar progressBar(double value, double max) => ProgressBar(
      max: max,
      value: value,
      height: 83,
      textSize: 40,
      textSecondarySize: 24,
      backgroundColor: Colors.blueGrey,
      foregroundColor: Colors.blueAccent,
      textColor: Colors.black87,
    );

    final builder = GoldenBuilder.grid(columns: 3, widthToHeightRatio: 1)
      ..addScenario('full', progressBar(100, 100))
      ..addScenario('empty', progressBar(0, 100))
      ..addScenario('half', progressBar(75, 150))
      ..addScenario('overflowing', progressBar(200, 150))
      ..addScenario('tiny value', progressBar(2.15, 150));

    await tester.pumpWidgetBuilder(builder.build());
    await screenMatchesGolden(tester, 'progress_bar_large');
  });

  testGoldens('Text Field', (tester) async {
    final builder = GoldenBuilder.grid(columns: 3, widthToHeightRatio: 1)
      ..addScenario(
        'basic',
        SizedBox(height: 70, width: 250, child: CustomTextField()),
      )
      ..addScenario(
        'hint',
        SizedBox(
          height: 70,
          width: 250,
          child: CustomTextField(hint: "type something"),
        ),
      )
      ..addScenario(
        'label',
        SizedBox(
          height: 100,
          width: 250,
          child: CustomTextField(hint: "type something", label: "text input"),
        ),
      )
      ..addScenario(
        'numeric',
        SizedBox(
          height: 70,
          width: 250,
          child: CustomTextField(keyboardType: TextInputType.number),
        ),
      )
      ..addScenario(
        'password',
        SizedBox(
          height: 70,
          width: 250,
          child: CustomTextField(showPassword: false),
        ),
      )
      ..addScenario(
        'multiline',
        SizedBox(height: 200, width: 250, child: CustomTextField(lines: 4)),
      );

    await tester.pumpWidgetBuilder(builder.build());
    await screenMatchesGolden(tester, 'textfield');
  });

  testGoldens('Primary Button', (tester) async {
    const double buttonHeight = 70;
    const double buttonWidth = 250;

    final builder = GoldenBuilder.grid(columns: 2, widthToHeightRatio: 1)
      ..addScenario(
        'empty',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: PrimaryButton(
            onPressed: () {},
            text: "",
            color: Colors.blueAccent,
          ),
        ),
      )
      ..addScenario(
        'basic',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: PrimaryButton(
            onPressed: () {},
            text: "press me",
            color: Colors.blueAccent,
          ),
        ),
      )
      ..addScenario(
        'round',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: PrimaryButton(
            onPressed: () {},
            radius: 100,
            text: "press me",
            color: Colors.blueAccent,
          ),
        ),
      )
      ..addScenario(
        'small',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: PrimaryButton(
            onPressed: () {},
            width: 100,
            text: "press me",
            color: Colors.blueAccent,
          ),
        ),
      );

    await tester.pumpWidgetBuilder(builder.build());
    await screenMatchesGolden(tester, 'primary_button');
  });

  testGoldens('Text Button', (tester) async {
    const tapTarget = Key("tap-target");

    final builder = GoldenBuilder.column()
      ..addScenario('empty', CustomTextButton(onPressed: () {}, text: ""))
      ..addScenario(
        'basic',
        CustomTextButton(onPressed: () {}, text: "press me"),
      )
      ..addScenario(
        'tapped',
        CustomTextButton(onPressed: () {}, text: "press me", key: tapTarget),
      )
      ..addScenario(
        'large text',
        CustomTextButton(
          onPressed: () {},
          text: "press me",
          size: 40,
          weight: FontWeight.w500,
        ),
      )
      ..addScenario(
        'small text',
        CustomTextButton(onPressed: () {}, text: "press me", size: 10),
      )
      ..addScenario(
        'colored',
        CustomTextButton(
          onPressed: () {},
          text: "press me",
          color: Colors.blueAccent,
        ),
      );

    await tester.pumpWidgetBuilder(builder.build());
    await tester.tap(find.byKey(tapTarget));
    await tester.pumpAndSettle();
    await screenMatchesGolden(tester, 'text_button');
  });

  testGoldens('Money Text', (tester) async {
    final builder = GoldenBuilder.column()
      ..addScenario(
        'basic',
        MoneyText(text: "29.13€", size: 20, color: Colors.blueAccent),
      )
      ..addScenario(
        'without cents',
        MoneyText(text: "50€", size: 20, color: Colors.blueAccent),
      )
      ..addScenario(
        'different sizes',
        MoneyText(
          text: "29.13€",
          size: 30,
          secondarySize: 15,
          color: Colors.blueAccent,
        ),
      )
      ..addScenario(
        'different sizes without cents',
        MoneyText(
          text: "50€",
          size: 30,
          secondarySize: 15,
          color: Colors.blueAccent,
        ),
      );

    await tester.pumpWidgetBuilder(builder.build());
    await screenMatchesGolden(tester, 'money_text');
  });

  testGoldens('Secondary Button', (tester) async {
    const double buttonHeight = 70;
    const double buttonWidth = 250;

    final builder = GoldenBuilder.grid(columns: 3, widthToHeightRatio: 1)
      ..addScenario(
        'empty',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: SecondaryButton(onPressed: () {}, text: ""),
        ),
      )
      ..addScenario(
        'text',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: SecondaryButton(onPressed: () {}, text: "press me"),
        ),
      )
      ..addScenario(
        'icon',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: SecondaryButton(
            onPressed: () {},
            icon: Icons.account_circle_outlined,
          ),
        ),
      )
      ..addScenario(
        'colored',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: SecondaryButton(
            onPressed: () {},
            text: "press me",
            color: Colors.blueAccent,
          ),
        ),
      )
      ..addScenario(
        'small',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: SecondaryButton(
            onPressed: () {},
            width: 100,
            text: "press me",
          ),
        ),
      )
      ..addScenario(
        'round',
        SizedBox(
          height: buttonHeight,
          width: buttonWidth,
          child: SecondaryButton(
            onPressed: () {},
            radius: 100,
            text: "press me",
            color: Colors.blueAccent,
          ),
        ),
      );

    await tester.pumpWidgetBuilder(builder.build());
    await screenMatchesGolden(tester, 'secondary_button');
  });

  void snackbarTest({
    required String message,
    required MessageType? type,
    required String testName,
  }) {
    testGoldens('Snackbar $testName', (tester) async {
      const Key tapTarget = Key('tap-target');

      SizedBox buildScaffold() => SizedBox(
        width: 800,
        height: 600,
        child: MaterialApp(
          home: Scaffold(
            body: Builder(
              builder: (BuildContext context) {
                return GestureDetector(
                  onTap: () {
                    ScaffoldMessenger.of(context).showSnackBar(
                      CustomSnackBar(
                        message: message,
                        type: type,
                      ).build(context),
                    );
                  },
                  behavior: HitTestBehavior.opaque,
                  key: tapTarget,
                );
              },
            ),
          ),
        ),
      );

      final builder = DeviceBuilder()
        ..overrideDevicesForAllScenarios(
          devices: const [Device(size: Size(750, 550), name: 'base')],
        )
        ..addScenario(name: testName, widget: buildScaffold());

      await tester.pumpWidgetBuilder(builder.build());
      await tester.tap(find.byKey(tapTarget));
      await tester.pumpAndSettle();

      await screenMatchesGolden(tester, 'snackbar/$testName');
    });
  }

  const shortText = "Mensaje de prueba";
  const longText =
      "Mensaje de prueba largo para comprobar los casos en los que el texto ocupa varias líneas";

  snackbarTest(message: "", type: null, testName: "default_empty");
  snackbarTest(message: shortText, type: null, testName: "default");
  snackbarTest(message: longText, type: null, testName: "default_long_text");
  snackbarTest(message: "", type: MessageType.info, testName: "info_empty");
  snackbarTest(message: shortText, type: MessageType.info, testName: "info");
  snackbarTest(
    message: longText,
    type: MessageType.info,
    testName: "info_long_text",
  );
  snackbarTest(
    message: "",
    type: MessageType.success,
    testName: "success_empty",
  );
  snackbarTest(
    message: shortText,
    type: MessageType.success,
    testName: "success",
  );
  snackbarTest(
    message: longText,
    type: MessageType.success,
    testName: "success_long_text",
  );
  snackbarTest(
    message: "",
    type: MessageType.warning,
    testName: "warning_empty",
  );
  snackbarTest(
    message: shortText,
    type: MessageType.warning,
    testName: "warning",
  );
  snackbarTest(
    message: longText,
    type: MessageType.warning,
    testName: "warning_long_text",
  );
  snackbarTest(message: "", type: MessageType.error, testName: "error_empty");
  snackbarTest(message: shortText, type: MessageType.error, testName: "error");
  snackbarTest(
    message: longText,
    type: MessageType.error,
    testName: "error_long_text",
  );

  testGoldens('Dropdown', (tester) async {
    const List<Widget> emptyList = [];
    const List<Widget> shortList = [Text("A"), Text("B"), Text("C")];

    final builder = GoldenBuilder.column()
      ..addScenario(
        'empty',
        CustomDropdown(items: emptyList, onChanged: (_) {}, width: 200),
      )
      ..addScenario(
        'initial value',
        CustomDropdown(
          items: shortList,
          value: 1,
          onChanged: (_) {},
          width: 300,
        ),
      )
      ..addScenario(
        'hint',
        CustomDropdown(
          items: shortList,
          hint: "choose an option",
          onChanged: (_) {},
        ),
      )
      ..addScenario(
        'label',
        CustomDropdown(
          items: shortList,
          label: "select",
          onChanged: (_) {},
          width: 200,
        ),
      );

    await tester.pumpWidgetBuilder(builder.build());
    await screenMatchesGolden(tester, 'dropdown');
  });
}
