import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.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/tickets_provider.dart';
import 'package:tasq/providers/user_offices_provider.dart';
import 'package:tasq/providers/auth_provider.dart';
import 'package:tasq/screens/profile/profile_screen.dart';
import 'package:tasq/widgets/multi_select_picker.dart';

class _FakeProfileController implements ProfileController {
  String? lastFullName;
  String? lastPassword;

  @override
  Future<void> updateFullName({
    required String userId,
    required String fullName,
  }) async {
    lastFullName = fullName;
  }

  @override
  Future<void> updatePassword(String password) async {
    lastPassword = password;
  }
}

class _FakeUserOfficesController implements UserOfficesController {
  final List<Map<String, String>> assigned = [];

  @override
  Future<void> assignUserOffice({
    required String userId,
    required String officeId,
  }) async {
    assigned.add({'userId': userId, 'officeId': officeId});
  }

  @override
  Future<void> removeUserOffice({
    required String userId,
    required String officeId,
  }) async {
    assigned.removeWhere(
      (e) => e['userId'] == userId && e['officeId'] == officeId,
    );
  }
}

void main() {
  final officeA = Office(id: 'office-1', name: 'HQ');
  final officeB = Office(id: 'office-2', name: 'Branch');
  final profile = Profile(id: 'user-1', role: 'standard', fullName: 'Paola');

  ProviderScope buildApp({required List<Override> overrides}) {
    return ProviderScope(
      overrides: [
        currentUserIdProvider.overrideWithValue(profile.id),
        sessionProvider.overrideWithValue(null),
        ...overrides,
      ],
      child: const MaterialApp(home: Scaffold(body: ProfileScreen())),
    );
  }

  testWidgets('renders fields and sections', (tester) async {
    await tester.pumpWidget(
      buildApp(
        overrides: [
          currentProfileProvider.overrideWith((ref) => Stream.value(profile)),
          officesProvider.overrideWith(
            (ref) => Stream.value([officeA, officeB]),
          ),
          userOfficesProvider.overrideWith(
            (ref) => Stream.value(const <UserOffice>[]),
          ),
        ],
      ),
    );

    await tester.pumpAndSettle();

    expect(find.text('My Profile'), findsOneWidget);
    expect(find.text('Account details'), findsOneWidget);
    expect(find.widgetWithText(TextFormField, 'Full name'), findsOneWidget);
    expect(
      find.byWidgetPredicate(
        (w) => w is MultiSelectPicker<Office> && w.label == 'Offices',
      ),
      findsOneWidget,
    );
  });

  testWidgets('save details calls profile controller', (tester) async {
    final fake = _FakeProfileController();

    await tester.pumpWidget(
      buildApp(
        overrides: [
          currentProfileProvider.overrideWith((ref) => Stream.value(profile)),
          officesProvider.overrideWith((ref) => Stream.value([officeA])),
          userOfficesProvider.overrideWith(
            (ref) => Stream.value(const <UserOffice>[]),
          ),
          profileControllerProvider.overrideWithValue(fake),
        ],
      ),
    );

    await tester.pumpAndSettle();

    await tester.enterText(
      find.widgetWithText(TextFormField, 'Full name'),
      'New Name',
    );
    await tester.tap(find.text('Save details'));
    await tester.pumpAndSettle();

    expect(fake.lastFullName, equals('New Name'));
  });

  testWidgets('save offices assigns selected office', (tester) async {
    final fakeOffices = _FakeUserOfficesController();

    await tester.pumpWidget(
      buildApp(
        overrides: [
          currentProfileProvider.overrideWith((ref) => Stream.value(profile)),
          officesProvider.overrideWith(
            (ref) => Stream.value([officeA, officeB]),
          ),
          userOfficesProvider.overrideWith(
            (ref) => Stream.value(const <UserOffice>[]),
          ),
          userOfficesControllerProvider.overrideWithValue(fakeOffices),
        ],
      ),
    );

    await tester.pumpAndSettle();

    // Open MultiSelect picker
    final selectChip = find.byWidgetPredicate(
      (w) => w is ActionChip && (w.label as Text).data == 'Select',
    );
    expect(selectChip, findsOneWidget);
    await tester.ensureVisible(selectChip);
    await tester.tap(selectChip);
    await tester.pumpAndSettle();

    // In the dialog, tap the first office checkbox and press Done
    await tester.tap(find.text('HQ'));
    await tester.pumpAndSettle();
    await tester.tap(find.text('Done'));
    await tester.pumpAndSettle();

    // Save offices
    await tester.tap(find.text('Save offices'));
    await tester.pumpAndSettle();

    expect(fakeOffices.assigned, isNotEmpty);
    expect(fakeOffices.assigned.first['officeId'], equals('office-1'));
  });

  testWidgets('change password calls controller', (tester) async {
    final fake = _FakeProfileController();

    await tester.pumpWidget(
      buildApp(
        overrides: [
          currentProfileProvider.overrideWith((ref) => Stream.value(profile)),
          officesProvider.overrideWith((ref) => Stream.value([officeA])),
          userOfficesProvider.overrideWith(
            (ref) => Stream.value(const <UserOffice>[]),
          ),
          profileControllerProvider.overrideWithValue(fake),
        ],
      ),
    );

    await tester.pumpAndSettle();

    await tester.enterText(
      find.widgetWithText(TextFormField, 'New password'),
      'new-pass-123',
    );
    await tester.enterText(
      find.widgetWithText(TextFormField, 'Confirm password'),
      'new-pass-123',
    );
    await tester.tap(find.text('Change password'));
    await tester.pumpAndSettle();

    expect(fake.lastPassword, equals('new-pass-123'));
  });
}
