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

import 'package:tasq/models/office.dart';
import 'package:tasq/models/profile.dart';
import 'package:tasq/models/user_office.dart';
import 'package:tasq/providers/profile_provider.dart';

import 'package:tasq/providers/user_offices_provider.dart';
import 'package:tasq/providers/admin_user_provider.dart';
import 'package:tasq/providers/tickets_provider.dart';
import 'package:tasq/screens/admin/user_management_screen.dart';

class _FakeAdminController extends AdminUserController {
  _FakeAdminController()
    : super(SupabaseClient('http://localhost', 'test-key'));

  String? lastSetPasswordUserId;
  String? lastSetPasswordValue;

  String? lastSetLockUserId;
  bool? lastSetLockedValue;

  @override
  Future<void> setPassword({
    required String userId,
    required String password,
  }) async {
    lastSetPasswordUserId = userId;
    lastSetPasswordValue = password;
    return Future.value();
  }

  @override
  Future<void> setLock({required String userId, required bool locked}) async {
    lastSetLockUserId = userId;
    lastSetLockedValue = locked;
    return Future.value();
  }
}

void main() {
  final office = Office(id: 'office-1', name: 'HQ');
  final profile = Profile(id: 'user-1', role: 'admin', fullName: 'Alice Admin');

  ProviderScope buildApp({required List<Override> overrides}) {
    return ProviderScope(
      overrides: overrides,
      child: const MaterialApp(home: UserManagementScreen()),
    );
  }

  testWidgets('sanity - basic Text widgets render', (tester) async {
    await tester.pumpWidget(
      const MaterialApp(home: Scaffold(body: Text('SANITY'))),
    );
    await tester.pump();
    expect(find.text('SANITY'), findsOneWidget);
  });

  testWidgets('Edit dialog pre-fills fields and shows actions', (tester) async {
    await tester.pumpWidget(
      buildApp(
        overrides: [
          currentProfileProvider.overrideWith((ref) => Stream.value(profile)),
          profilesProvider.overrideWith((ref) => Stream.value([profile])),
          officesProvider.overrideWith((ref) => Stream.value([office])),
          userOfficesProvider.overrideWith(
            (ref) => Stream.value([
              UserOffice(userId: 'user-1', officeId: 'office-1'),
            ]),
          ),
          ticketMessagesAllProvider.overrideWith((ref) => const Stream.empty()),
          isAdminProvider.overrideWith((ref) => true),
          // Provide an AdminUserStatus so the dialog can show email/status immediately.
          adminUserStatusProvider.overrideWithProvider(
            FutureProvider.autoDispose.family<AdminUserStatus, String>(
              (ref, id) async => AdminUserStatus(
                email: 'alice@example.com',
                bannedUntil: null,
              ),
            ),
          ),
        ],
      ),
    );

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 16));

    expect(find.text('Alice Admin'), findsOneWidget);

    // Open edit dialog
    await tester.tap(find.text('Alice Admin'));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 16));

    // Dialog should show and the Full name TextField should contain the profile name
    final alert = find.byType(AlertDialog);
    expect(alert, findsOneWidget);

    final editable = find.descendant(
      of: alert,
      matching: find.byType(EditableText),
    );
    expect(editable, findsWidgets);

    // The first EditableText inside the dialog is the Full name field
    final fullNameEditable = editable.first;
    final et = tester.widget<EditableText>(fullNameEditable);
    expect(et.controller.text, equals('Alice Admin'));

    // Role should show selected value
    expect(
      find.descendant(of: alert, matching: find.text('admin')),
      findsWidgets,
    );

    // Reset password and Lock buttons must be visible
    expect(
      find.descendant(
        of: alert,
        matching: find.widgetWithText(OutlinedButton, 'Reset password'),
      ),
      findsOneWidget,
    );
    expect(
      find.descendant(
        of: alert,
        matching: find.widgetWithText(OutlinedButton, 'Lock'),
      ),
      findsOneWidget,
    );
  });

  testWidgets('Reset password and lock call admin controller', (tester) async {
    final fake = _FakeAdminController();

    await tester.pumpWidget(
      buildApp(
        overrides: [
          currentProfileProvider.overrideWith((ref) => Stream.value(profile)),
          profilesProvider.overrideWith((ref) => Stream.value([profile])),
          officesProvider.overrideWith((ref) => Stream.value([office])),
          userOfficesProvider.overrideWith(
            (ref) => Stream.value([
              UserOffice(userId: 'user-1', officeId: 'office-1'),
            ]),
          ),
          ticketMessagesAllProvider.overrideWith((ref) => const Stream.empty()),
          isAdminProvider.overrideWith((ref) => true),
          adminUserStatusProvider.overrideWithProvider(
            FutureProvider.autoDispose.family<AdminUserStatus, String>(
              (ref, id) async => AdminUserStatus(
                email: 'alice@example.com',
                bannedUntil: null,
              ),
            ),
          ),
          adminUserControllerProvider.overrideWithValue(fake),
        ],
      ),
    );

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 16));

    // Open edit dialog (again)
    await tester.tap(find.text('Alice Admin'));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 16));

    // Tap Reset password
    await tester.tap(find.widgetWithText(OutlinedButton, 'Reset password'));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 16));

    // Enter new password in the nested dialog
    final pwdField = find.byType(TextFormField).last;
    await tester.enterText(pwdField, 'new-pass-123');
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 16));

    // Confirm update
    await tester.tap(find.text('Update password'));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 16));

    expect(fake.lastSetPasswordUserId, equals('user-1'));
    expect(fake.lastSetPasswordValue, equals('new-pass-123'));

    // Back in the main dialog - press Lock
    await tester.tap(find.widgetWithText(OutlinedButton, 'Lock'));
    await tester.pumpAndSettle();

    expect(fake.lastSetLockUserId, equals('user-1'));
    expect(fake.lastSetLockedValue, isTrue);
  });
}
