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

import 'package:tasq/models/office.dart';
import 'package:tasq/models/profile.dart';
import 'package:tasq/models/team.dart';
import 'package:tasq/models/team_member.dart';
import 'package:tasq/providers/teams_provider.dart';
import 'package:tasq/providers/profile_provider.dart';
import 'package:tasq/providers/tickets_provider.dart';
import 'package:tasq/screens/teams/teams_screen.dart';
import 'package:tasq/providers/supabase_provider.dart';
import 'package:tasq/widgets/multi_select_picker.dart';

SupabaseClient _fakeSupabaseClient() =>
    SupabaseClient('http://localhost', 'test-key');

void main() {
  final office = Office(id: 'office-1', name: 'HQ');
  final admin = Profile(id: 'user-1', role: 'admin', fullName: 'Alex Admin');
  final tech = Profile(id: 'user-2', role: 'it_staff', fullName: 'Jamie Tech');

  List<Override> baseOverrides() {
    return [
      supabaseClientProvider.overrideWithValue(_fakeSupabaseClient()),
      currentProfileProvider.overrideWith((ref) => Stream.value(admin)),
      profilesProvider.overrideWith((ref) => Stream.value([admin, tech])),
      officesProvider.overrideWith((ref) => Stream.value([office])),
      teamsProvider.overrideWith((ref) => Stream.value(const <Team>[])),
      teamMembersProvider.overrideWith(
        (ref) => Stream.value(const <TeamMember>[]),
      ),
    ];
  }

  testWidgets('Add Team dialog: leader dropdown shows only it_staff', (
    WidgetTester tester,
  ) async {
    await tester.binding.setSurfaceSize(const Size(600, 800));
    addTearDown(() async => await tester.binding.setSurfaceSize(null));

    await tester.pumpWidget(
      ProviderScope(
        overrides: baseOverrides(),
        child: const MaterialApp(home: Scaffold(body: TeamsScreen())),
      ),
    );

    // Open Add Team dialog
    await tester.tap(find.byType(FloatingActionButton));
    await tester.pumpAndSettle();

    // Open the dropdown overlay and assert only the it_staff option is shown.
    final leaderDropdown = find.widgetWithText(
      DropdownButtonFormField<String>,
      'Team Leader',
    );
    expect(leaderDropdown, findsOneWidget);

    await tester.tap(leaderDropdown);
    await tester.pumpAndSettle();

    // The dropdown overlay should show the it_staff option and not the admin.
    expect(find.text('Jamie Tech'), findsOneWidget);
    expect(find.text('Alex Admin'), findsNothing);
  });

  testWidgets('Add Team dialog: Team Members picker shows only it_staff', (
    WidgetTester tester,
  ) async {
    await tester.binding.setSurfaceSize(const Size(600, 800));
    addTearDown(() async => await tester.binding.setSurfaceSize(null));

    await tester.pumpWidget(
      ProviderScope(
        overrides: baseOverrides(),
        child: const MaterialApp(home: Scaffold(body: TeamsScreen())),
      ),
    );

    // Open Add Team dialog
    await tester.tap(find.byType(FloatingActionButton));
    await tester.pumpAndSettle();

    // Inspect the MultiSelectPicker widget for 'Team Members' directly
    final pickerFinder = find.byWidgetPredicate(
      (w) => w is MultiSelectPicker<Profile> && w.label == 'Team Members',
    );
    expect(pickerFinder, findsOneWidget);
    final picker = tester.widget<MultiSelectPicker<Profile>>(pickerFinder);
    final labels = picker.items.map(picker.getLabel).toList();
    expect(labels, contains('Jamie Tech'));
    expect(labels, isNot(contains('Alex Admin')));
  });

  testWidgets(
    'Add Team dialog uses fixed width on desktop and bottom-sheet on mobile',
    (WidgetTester tester) async {
      // Desktop -> AlertDialog constrained to max width
      await tester.binding.setSurfaceSize(const Size(1024, 800));
      addTearDown(() async => await tester.binding.setSurfaceSize(null));

      await tester.pumpWidget(
        ProviderScope(
          overrides: baseOverrides(),
          child: const MaterialApp(home: Scaffold(body: TeamsScreen())),
        ),
      );

      await tester.tap(find.byType(FloatingActionButton));
      await tester.pumpAndSettle();

      expect(find.byType(AlertDialog), findsOneWidget);
      final dialogSize = tester.getSize(find.byType(AlertDialog));
      expect(dialogSize.width, lessThanOrEqualTo(720));

      // Close desktop dialog
      await tester.tap(find.text('Cancel'));
      await tester.pumpAndSettle();

      // Mobile -> bottom sheet presentation
      await tester.binding.setSurfaceSize(const Size(600, 800));
      await tester.pumpWidget(
        ProviderScope(
          overrides: baseOverrides(),
          child: const MaterialApp(home: Scaffold(body: TeamsScreen())),
        ),
      );

      await tester.tap(find.byType(FloatingActionButton));
      await tester.pumpAndSettle();

      expect(find.byType(BottomSheet), findsWidgets);
      expect(find.text('Team Name'), findsOneWidget);
    },
  );

  testWidgets('Edit Team dialog: Save button present and Cancel closes', (
    WidgetTester tester,
  ) async {
    await tester.binding.setSurfaceSize(const Size(1024, 800));
    addTearDown(() async => await tester.binding.setSurfaceSize(null));

    final team = Team(
      id: 'team-1',
      name: 'Support',
      leaderId: 'user-2',
      officeIds: ['office-1'],
      createdAt: DateTime.now(),
    );

    await tester.pumpWidget(
      ProviderScope(
        overrides: [
          ...baseOverrides(),
          teamsProvider.overrideWith((ref) => Stream.value([team])),
        ],
        child: const MaterialApp(home: Scaffold(body: TeamsScreen())),
      ),
    );

    // Tap edit and verify dialog shows Save button
    await tester.tap(find.byIcon(Icons.edit));
    await tester.pumpAndSettle();

    expect(find.text('Save'), findsOneWidget);

    // Cancel closes dialog
    await tester.tap(find.text('Cancel'));
    await tester.pumpAndSettle();
    expect(find.text('Save'), findsNothing);
  });
}
