import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:tasq/utils/app_time.dart';
import 'package:go_router/go_router.dart';

import '../../models/office.dart';
import '../../models/notification_item.dart';
import '../../models/profile.dart';
import '../../models/ticket.dart';
import '../../providers/notifications_provider.dart';
import '../../providers/profile_provider.dart';
import '../../providers/tickets_provider.dart';
import '../../providers/typing_provider.dart';
import '../../widgets/mono_text.dart';
import '../../widgets/responsive_body.dart';
import '../../widgets/tasq_adaptive_list.dart';
import '../../widgets/typing_dots.dart';
import '../../theme/app_surfaces.dart';

class TicketsListScreen extends ConsumerStatefulWidget {
  const TicketsListScreen({super.key});

  @override
  ConsumerState<TicketsListScreen> createState() => _TicketsListScreenState();
}

class _TicketsListScreenState extends ConsumerState<TicketsListScreen> {
  final TextEditingController _subjectController = TextEditingController();
  String? _selectedOfficeId;
  String? _selectedStatus;
  DateTimeRange? _selectedDateRange;

  @override
  void dispose() {
    _subjectController.dispose();
    super.dispose();
  }

  bool get _hasTicketFilters {
    return _subjectController.text.trim().isNotEmpty ||
        _selectedOfficeId != null ||
        _selectedStatus != null ||
        _selectedDateRange != null;
  }

  @override
  Widget build(BuildContext context) {
    final ticketsAsync = ref.watch(ticketsProvider);
    final officesAsync = ref.watch(officesProvider);
    final notificationsAsync = ref.watch(notificationsProvider);
    final profilesAsync = ref.watch(profilesProvider);

    return Stack(
      children: [
        ResponsiveBody(
          maxWidth: double.infinity,
          child: ticketsAsync.when(
            data: (tickets) {
              if (tickets.isEmpty) {
                return const Center(child: Text('No tickets yet.'));
              }
              final officeById = <String, Office>{
                for (final office in officesAsync.valueOrNull ?? <Office>[])
                  office.id: office,
              };
              final profileById = <String, Profile>{
                for (final profile in profilesAsync.valueOrNull ?? <Profile>[])
                  profile.id: profile,
              };
              final unreadByTicketId = _unreadByTicketId(notificationsAsync);
              final offices = officesAsync.valueOrNull ?? <Office>[];
              final officeOptions = <DropdownMenuItem<String?>>[
                const DropdownMenuItem<String?>(
                  value: null,
                  child: Text('All offices'),
                ),
                ...offices.map(
                  (office) => DropdownMenuItem<String?>(
                    value: office.id,
                    child: Text(office.name),
                  ),
                ),
              ];
              final statusOptions = _ticketStatusOptions(tickets);
              final filteredTickets = _applyTicketFilters(
                tickets,
                subjectQuery: _subjectController.text,
                officeId: _selectedOfficeId,
                status: _selectedStatus,
                dateRange: _selectedDateRange,
              );
              final summaryDashboard = _StatusSummaryRow(
                counts: _statusCounts(filteredTickets),
              );
              final filterHeader = Wrap(
                spacing: 12,
                runSpacing: 12,
                crossAxisAlignment: WrapCrossAlignment.center,
                children: [
                  SizedBox(
                    width: 220,
                    child: TextField(
                      controller: _subjectController,
                      onChanged: (_) => setState(() {}),
                      decoration: const InputDecoration(
                        labelText: 'Subject',
                        prefixIcon: Icon(Icons.search),
                      ),
                    ),
                  ),
                  SizedBox(
                    width: 200,
                    child: DropdownButtonFormField<String?>(
                      isExpanded: true,
                      key: ValueKey(_selectedOfficeId),
                      initialValue: _selectedOfficeId,
                      items: officeOptions,
                      onChanged: (value) =>
                          setState(() => _selectedOfficeId = value),
                      decoration: const InputDecoration(labelText: 'Office'),
                    ),
                  ),
                  SizedBox(
                    width: 180,
                    child: DropdownButtonFormField<String?>(
                      isExpanded: true,
                      key: ValueKey(_selectedStatus),
                      initialValue: _selectedStatus,
                      items: statusOptions,
                      onChanged: (value) =>
                          setState(() => _selectedStatus = value),
                      decoration: const InputDecoration(labelText: 'Status'),
                    ),
                  ),
                  OutlinedButton.icon(
                    onPressed: () async {
                      final next = await showDateRangePicker(
                        context: context,
                        firstDate: DateTime(2020),
                        lastDate: AppTime.now().add(const Duration(days: 365)),
                        currentDate: AppTime.now(),
                        initialDateRange: _selectedDateRange,
                      );
                      if (!mounted) return;
                      setState(() => _selectedDateRange = next);
                    },
                    icon: const Icon(Icons.date_range),
                    label: Text(
                      _selectedDateRange == null
                          ? 'Date range'
                          : AppTime.formatDateRange(_selectedDateRange!),
                    ),
                  ),
                  if (_hasTicketFilters)
                    TextButton.icon(
                      onPressed: () => setState(() {
                        _subjectController.clear();
                        _selectedOfficeId = null;
                        _selectedStatus = null;
                        _selectedDateRange = null;
                      }),
                      icon: const Icon(Icons.close),
                      label: const Text('Clear'),
                    ),
                ],
              );
              final listBody = TasQAdaptiveList<Ticket>(
                items: filteredTickets,
                onRowTap: (ticket) => context.go('/tickets/${ticket.id}'),
                summaryDashboard: summaryDashboard,
                filterHeader: filterHeader,
                onRequestRefresh: () {
                  // For server-side pagination, update the query provider
                  // This will trigger a reload with new pagination parameters
                  ref.read(ticketsQueryProvider.notifier).state =
                      const TicketQuery(offset: 0, limit: 50);
                },
                isLoading: false,
                columns: [
                  TasQColumn<Ticket>(
                    header: 'Ticket ID',
                    technical: true,
                    cellBuilder: (context, ticket) => Text(ticket.id),
                  ),
                  TasQColumn<Ticket>(
                    header: 'Subject',
                    cellBuilder: (context, ticket) => Text(ticket.subject),
                  ),
                  TasQColumn<Ticket>(
                    header: 'Office',
                    cellBuilder: (context, ticket) => Text(
                      officeById[ticket.officeId]?.name ?? ticket.officeId,
                    ),
                  ),
                  TasQColumn<Ticket>(
                    header: 'Filed by',
                    cellBuilder: (context, ticket) =>
                        Text(_assignedAgent(profileById, ticket.creatorId)),
                  ),
                  TasQColumn<Ticket>(
                    header: 'Status',
                    cellBuilder: (context, ticket) =>
                        _StatusBadge(status: ticket.status),
                  ),
                  TasQColumn<Ticket>(
                    header: 'Timestamp',
                    technical: true,
                    cellBuilder: (context, ticket) =>
                        Text(_formatTimestamp(ticket.createdAt)),
                  ),
                ],
                mobileTileBuilder: (context, ticket, actions) {
                  final officeName =
                      officeById[ticket.officeId]?.name ?? ticket.officeId;
                  final assigned = _assignedAgent(
                    profileById,
                    ticket.creatorId,
                  );
                  final hasMention = unreadByTicketId[ticket.id] == true;
                  final typingState = ref.watch(
                    typingIndicatorProvider(ticket.id),
                  );
                  final showTyping = typingState.userIds.isNotEmpty;
                  return Card(
                    child: ListTile(
                      leading: const Icon(Icons.confirmation_number_outlined),
                      dense: true,
                      visualDensity: VisualDensity.compact,
                      title: Text(ticket.subject),
                      subtitle: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(officeName),
                          const SizedBox(height: 2),
                          Text('Filed by: $assigned'),
                          const SizedBox(height: 4),
                          MonoText('ID ${ticket.id}'),
                          const SizedBox(height: 2),
                          Text(_formatTimestamp(ticket.createdAt)),
                        ],
                      ),
                      trailing: Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          _StatusBadge(status: ticket.status),
                          if (showTyping) ...[
                            const SizedBox(width: 6),
                            TypingDots(
                              size: 6,
                              color: Theme.of(context).colorScheme.primary,
                            ),
                          ],
                          if (hasMention)
                            const Padding(
                              padding: EdgeInsets.only(left: 8),
                              child: Icon(
                                Icons.circle,
                                size: 10,
                                color: Colors.red,
                              ),
                            ),
                        ],
                      ),
                      onTap: () => context.go('/tickets/${ticket.id}'),
                    ),
                  );
                },
              );

              return Column(
                mainAxisSize: MainAxisSize.max,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Padding(
                    padding: const EdgeInsets.only(top: 16, bottom: 8),
                    child: Align(
                      alignment: Alignment.center,
                      child: Text(
                        'Tickets',
                        textAlign: TextAlign.center,
                        style: Theme.of(context).textTheme.titleLarge?.copyWith(
                          fontWeight: FontWeight.w700,
                        ),
                      ),
                    ),
                  ),
                  Expanded(child: listBody),
                ],
              );
            },
            loading: () => const Center(child: CircularProgressIndicator()),
            error: (error, _) =>
                Center(child: Text('Failed to load tickets: $error')),
          ),
        ),
        Positioned(
          right: 16,
          bottom: 16,
          child: SafeArea(
            child: FloatingActionButton.extended(
              onPressed: () => _showCreateTicketDialog(context, ref),
              icon: const Icon(Icons.add),
              label: const Text('New Ticket'),
            ),
          ),
        ),
      ],
    );
  }

  Future<void> _showCreateTicketDialog(
    BuildContext context,
    WidgetRef ref,
  ) async {
    final subjectController = TextEditingController();
    final descriptionController = TextEditingController();
    Office? selectedOffice;

    await showDialog<void>(
      context: context,
      builder: (dialogContext) {
        return StatefulBuilder(
          builder: (context, setState) {
            return AlertDialog(
              shape: AppSurfaces.of(context).dialogShape,
              title: const Text('Create Ticket'),
              content: Consumer(
                builder: (context, ref, child) {
                  final officesAsync = ref.watch(officesProvider);
                  return SizedBox(
                    width: 360,
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        TextField(
                          controller: subjectController,
                          decoration: const InputDecoration(
                            labelText: 'Subject',
                          ),
                        ),
                        const SizedBox(height: 12),
                        TextField(
                          controller: descriptionController,
                          decoration: const InputDecoration(
                            labelText: 'Description',
                          ),
                          maxLines: 3,
                        ),
                        const SizedBox(height: 12),
                        officesAsync.when(
                          data: (offices) {
                            if (offices.isEmpty) {
                              return const Text('No offices assigned.');
                            }
                            selectedOffice ??= offices.first;
                            return DropdownButtonFormField<Office>(
                              key: ValueKey(selectedOffice?.id),
                              initialValue: selectedOffice,
                              items: offices
                                  .map(
                                    (office) => DropdownMenuItem(
                                      value: office,
                                      child: Text(office.name),
                                    ),
                                  )
                                  .toList(),
                              onChanged: (value) =>
                                  setState(() => selectedOffice = value),
                              decoration: const InputDecoration(
                                labelText: 'Office',
                              ),
                            );
                          },
                          loading: () => const LinearProgressIndicator(),
                          error: (error, _) =>
                              Text('Failed to load offices: $error'),
                        ),
                      ],
                    ),
                  );
                },
              ),
              actions: [
                TextButton(
                  onPressed: () => Navigator.of(dialogContext).pop(),
                  child: const Text('Cancel'),
                ),
                FilledButton(
                  onPressed: () async {
                    final subject = subjectController.text.trim();
                    final description = descriptionController.text.trim();
                    if (subject.isEmpty ||
                        description.isEmpty ||
                        selectedOffice == null) {
                      ScaffoldMessenger.of(context).showSnackBar(
                        const SnackBar(content: Text('Fill out all fields.')),
                      );
                      return;
                    }
                    await ref
                        .read(ticketsControllerProvider)
                        .createTicket(
                          subject: subject,
                          description: description,
                          officeId: selectedOffice!.id,
                        );
                    // Supabase stream will emit the new ticket — no explicit
                    // invalidation required and avoids a temporary reload.
                    if (context.mounted) {
                      Navigator.of(dialogContext).pop();
                    }
                  },
                  child: const Text('Create'),
                ),
              ],
            );
          },
        );
      },
    );
  }

  Map<String, bool> _unreadByTicketId(
    AsyncValue<List<NotificationItem>> notificationsAsync,
  ) {
    return notificationsAsync.maybeWhen(
      data: (items) {
        final map = <String, bool>{};
        for (final item in items) {
          if (item.ticketId == null) continue;
          if (item.isUnread) {
            map[item.ticketId!] = true;
          }
        }
        return map;
      },
      orElse: () => <String, bool>{},
    );
  }
}

List<DropdownMenuItem<String?>> _ticketStatusOptions(List<Ticket> tickets) {
  final statuses = tickets.map((ticket) => ticket.status).toSet().toList()
    ..sort();
  return [
    const DropdownMenuItem<String?>(value: null, child: Text('All statuses')),
    ...statuses.map(
      (status) => DropdownMenuItem<String?>(value: status, child: Text(status)),
    ),
  ];
}

List<Ticket> _applyTicketFilters(
  List<Ticket> tickets, {
  required String subjectQuery,
  required String? officeId,
  required String? status,
  required DateTimeRange? dateRange,
}) {
  final query = subjectQuery.trim().toLowerCase();
  return tickets.where((ticket) {
    if (query.isNotEmpty &&
        !ticket.subject.toLowerCase().contains(query) &&
        !ticket.id.toLowerCase().contains(query)) {
      return false;
    }
    if (officeId != null && ticket.officeId != officeId) {
      return false;
    }
    if (status != null && ticket.status != status) {
      return false;
    }
    if (dateRange != null) {
      final start = DateTime(
        dateRange.start.year,
        dateRange.start.month,
        dateRange.start.day,
      );
      final end = DateTime(
        dateRange.end.year,
        dateRange.end.month,
        dateRange.end.day,
        23,
        59,
        59,
      );
      if (ticket.createdAt.isBefore(start) || ticket.createdAt.isAfter(end)) {
        return false;
      }
    }
    return true;
  }).toList();
}

Map<String, int> _statusCounts(List<Ticket> tickets) {
  final counts = <String, int>{};
  for (final ticket in tickets) {
    counts.update(ticket.status, (value) => value + 1, ifAbsent: () => 1);
  }
  return counts;
}

class _StatusSummaryRow extends StatelessWidget {
  const _StatusSummaryRow({required this.counts});

  final Map<String, int> counts;

  @override
  Widget build(BuildContext context) {
    if (counts.isEmpty) {
      return const SizedBox.shrink();
    }
    final entries = counts.entries.toList()
      ..sort((a, b) => a.key.compareTo(b.key));

    return LayoutBuilder(
      builder: (context, constraints) {
        final maxWidth = constraints.maxWidth;
        final maxPerRow = maxWidth >= 1000
            ? 4
            : maxWidth >= 720
            ? 3
            : maxWidth >= 480
            ? 2
            : entries.length;
        final perRow = entries.length < maxPerRow ? entries.length : maxPerRow;
        final spacing = maxWidth < 480 ? 8.0 : 12.0;
        final itemWidth = perRow == 0
            ? maxWidth
            : (maxWidth - spacing * (perRow - 1)) / perRow;

        return Wrap(
          spacing: spacing,
          runSpacing: spacing,
          children: [
            for (final entry in entries)
              SizedBox(
                width: itemWidth,
                child: _StatusSummaryCard(
                  status: entry.key,
                  count: entry.value,
                ),
              ),
          ],
        );
      },
    );
  }
}

class _StatusSummaryCard extends StatelessWidget {
  const _StatusSummaryCard({required this.status, required this.count});

  final String status;
  final int count;

  @override
  Widget build(BuildContext context) {
    final scheme = Theme.of(context).colorScheme;
    final background = switch (status) {
      'critical' => scheme.errorContainer,
      'pending' => scheme.tertiaryContainer,
      'promoted' => scheme.secondaryContainer,
      'closed' => scheme.primaryContainer,
      _ => scheme.surfaceContainerHigh,
    };
    final foreground = switch (status) {
      'critical' => scheme.onErrorContainer,
      'pending' => scheme.onTertiaryContainer,
      'promoted' => scheme.onSecondaryContainer,
      'closed' => scheme.onPrimaryContainer,
      _ => scheme.onSurfaceVariant,
    };

    return Card(
      color: background,
      // summary cards are compact — use compact token for consistent density
      shape: AppSurfaces.of(context).compactShape,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              status.toUpperCase(),
              style: Theme.of(context).textTheme.labelSmall?.copyWith(
                color: foreground,
                fontWeight: FontWeight.w600,
                letterSpacing: 0.4,
              ),
            ),
            const SizedBox(height: 6),
            Text(
              count.toString(),
              style: Theme.of(context).textTheme.headlineSmall?.copyWith(
                color: foreground,
                fontWeight: FontWeight.w700,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

String _assignedAgent(Map<String, Profile> profileById, String? userId) {
  if (userId == null || userId.isEmpty) {
    return 'Unassigned';
  }
  final profile = profileById[userId];
  if (profile == null) {
    return userId;
  }
  return profile.fullName.isNotEmpty ? profile.fullName : profile.id;
}

String _formatTimestamp(DateTime value) {
  final year = value.year.toString().padLeft(4, '0');
  final month = value.month.toString().padLeft(2, '0');
  final day = value.day.toString().padLeft(2, '0');
  final hour = value.hour.toString().padLeft(2, '0');
  final minute = value.minute.toString().padLeft(2, '0');
  return '$year-$month-$day $hour:$minute';
}

class _StatusBadge extends StatelessWidget {
  const _StatusBadge({required this.status});

  final String status;

  @override
  Widget build(BuildContext context) {
    final scheme = Theme.of(context).colorScheme;
    final background = switch (status) {
      'critical' => scheme.errorContainer,
      'pending' => scheme.tertiaryContainer,
      'promoted' => scheme.secondaryContainer,
      'closed' => scheme.primaryContainer,
      _ => scheme.surfaceContainerHighest,
    };
    final foreground = switch (status) {
      'critical' => scheme.onErrorContainer,
      'pending' => scheme.onTertiaryContainer,
      'promoted' => scheme.onSecondaryContainer,
      'closed' => scheme.onPrimaryContainer,
      _ => scheme.onSurfaceVariant,
    };

    return Badge(
      backgroundColor: background,
      label: Text(
        status.toUpperCase(),
        style: Theme.of(context).textTheme.labelSmall?.copyWith(
          color: foreground,
          fontWeight: FontWeight.w600,
          letterSpacing: 0.3,
        ),
      ),
    );
  }
}
