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

import '../models/profile.dart';
import '../providers/profile_provider.dart';
import '../providers/tasks_provider.dart';
import '../theme/app_surfaces.dart';

class TaskAssignmentSection extends ConsumerWidget {
  const TaskAssignmentSection({
    super.key,
    required this.taskId,
    required this.canAssign,
  });

  final String taskId;
  final bool canAssign;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final profilesAsync = ref.watch(profilesProvider);
    final tasksAsync = ref.watch(tasksProvider);
    final assignmentsAsync = ref.watch(taskAssignmentsProvider);

    final profiles = profilesAsync.valueOrNull ?? <Profile>[];
    final tasks = tasksAsync.valueOrNull ?? [];
    final taskTicketId = tasks
        .where((task) => task.id == taskId)
        .map((task) => task.ticketId)
        .firstOrNull;
    final assignments = assignmentsAsync.valueOrNull ?? [];

    final itStaff =
        profiles.where((profile) => profile.role == 'it_staff').toList()
          ..sort((a, b) => a.fullName.compareTo(b.fullName));

    final assignedForTask = assignments
        .where((assignment) => assignment.taskId == taskId)
        .toList();
    final assignedIds = assignedForTask.map((a) => a.userId).toSet();

    final activeTaskIds = tasks
        .where(
          (task) => task.status == 'queued' || task.status == 'in_progress',
        )
        .map((task) => task.id)
        .toSet();

    final activeAssignmentsByUser = <String, Set<String>>{};
    for (final assignment in assignments) {
      if (!activeTaskIds.contains(assignment.taskId)) {
        continue;
      }
      activeAssignmentsByUser
          .putIfAbsent(assignment.userId, () => <String>{})
          .add(assignment.taskId);
    }

    bool isVacant(String userId) {
      final active = activeAssignmentsByUser[userId];
      if (active == null || active.isEmpty) {
        return true;
      }
      return active.length == 1 && active.contains(taskId);
    }

    final eligibleStaff = itStaff
        .where(
          (profile) => isVacant(profile.id) || assignedIds.contains(profile.id),
        )
        .toList();

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Text(
              'Assigned IT Staff',
              style: Theme.of(
                context,
              ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700),
            ),
            const Spacer(),
            if (canAssign)
              TextButton.icon(
                onPressed: () => _showAssignmentDialog(
                  context,
                  ref,
                  eligibleStaff,
                  assignedIds,
                  taskTicketId,
                ),
                icon: const Icon(Icons.group_add),
                label: const Text('Assign'),
              ),
          ],
        ),
        const SizedBox(height: 8),
        if (assignedForTask.isEmpty)
          Text(
            'No IT staff assigned.',
            style: Theme.of(context).textTheme.bodyMedium,
          )
        else
          Wrap(
            spacing: 8,
            runSpacing: 6,
            children: assignedForTask.map((assignment) {
              final profile = profiles
                  .where((item) => item.id == assignment.userId)
                  .firstOrNull;
              final label = profile?.fullName.isNotEmpty == true
                  ? profile!.fullName
                  : assignment.userId;
              return InputChip(
                label: Text(label),
                onDeleted: canAssign
                    ? () => ref
                          .read(taskAssignmentsControllerProvider)
                          .removeAssignment(
                            taskId: taskId,
                            userId: assignment.userId,
                          )
                    : null,
              );
            }).toList(),
          ),
      ],
    );
  }

  Future<void> _showAssignmentDialog(
    BuildContext context,
    WidgetRef ref,
    List<Profile> eligibleStaff,
    Set<String> assignedIds,
    String? taskTicketId,
  ) async {
    if (eligibleStaff.isEmpty && assignedIds.isEmpty) {
      await showDialog<void>(
        context: context,
        builder: (dialogContext) {
          return AlertDialog(
            shape: AppSurfaces.of(context).dialogShape,
            title: const Text('Assign IT Staff'),
            content: const Text('No vacant IT staff available.'),
            actions: [
              TextButton(
                onPressed: () => Navigator.of(dialogContext).pop(),
                child: const Text('Close'),
              ),
            ],
          );
        },
      );
      return;
    }

    final selection = assignedIds.toSet();
    await showDialog<void>(
      context: context,
      builder: (dialogContext) {
        return StatefulBuilder(
          builder: (context, setState) {
            return AlertDialog(
              shape: AppSurfaces.of(context).dialogShape,
              title: const Text('Assign IT Staff'),
              contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 12),
              content: SizedBox(
                width: 360,
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 12),
                  child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: eligibleStaff.length,
                    itemBuilder: (context, index) {
                      final staff = eligibleStaff[index];
                      final name = staff.fullName.isNotEmpty
                          ? staff.fullName
                          : staff.id;
                      final selected = selection.contains(staff.id);
                      return CheckboxListTile(
                        value: selected,
                        title: Text(name),
                        contentPadding: const EdgeInsets.symmetric(
                          horizontal: 12,
                          vertical: 2,
                        ),
                        onChanged: (value) {
                          setState(() {
                            if (value == true) {
                              selection.add(staff.id);
                            } else {
                              selection.remove(staff.id);
                            }
                          });
                        },
                      );
                    },
                  ),
                ),
              ),
              actions: [
                TextButton(
                  onPressed: () => Navigator.of(dialogContext).pop(),
                  child: const Text('Cancel'),
                ),
                FilledButton(
                  onPressed: () async {
                    await ref
                        .read(taskAssignmentsControllerProvider)
                        .replaceAssignments(
                          taskId: taskId,
                          ticketId: taskTicketId,
                          newUserIds: selection.toList(),
                          currentUserIds: assignedIds.toList(),
                        );
                    if (context.mounted) {
                      Navigator.of(dialogContext).pop();
                    }
                  },
                  child: const Text('Save'),
                ),
              ],
            );
          },
        );
      },
    );
  }
}

extension _FirstOrNull<T> on Iterable<T> {
  T? get firstOrNull => isEmpty ? null : first;
}
