import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:material_symbols_icons/symbols.dart';
import '../../../main.dart' show api, accountModule;
import '../../../backend/modules/account.dart';
import '../../../core/storage/app_database.dart';
import '../../../core/utils/format.dart';
import '../../../core/calls/call_controller.dart';
import '../../../core/calls/call_session.dart';
import '../../../backend/modules/calls.dart';
import '../../widgets/komet_avatar.dart';
import '../../widgets/connection_status.dart';
import '../../widgets/reload_on_reconnect.dart';
import '../../widgets/custom_notification.dart';
import '../../widgets/chat_menu_overlay.dart';
import '../../widgets/small_spinner.dart';
import '../../widgets/prompt_dialog.dart';
import '../../widgets/call_link_handler.dart';
import '../../widgets/spectrum_tint.dart';
import 'call_screen.dart';

class CallsTab extends StatefulWidget {
  const CallsTab({super.key});

  @override
  State<CallsTab> createState() => _CallsTabState();
}

class _CallsTabState extends State<CallsTab>
    with ReloadOnReconnect, SpectrumSurface {
  List<CallLogEntry> _calls = [];
  final Set<String> _removing = {};
  bool _isLoading = true;
  int _selectedTabIndex = 0; // 0 for 'Все', 1 for 'Пропущенные'
  StreamSubscription<LoginStatus>? _loginSub;

  @override
  void initState() {
    super.initState();
    if (accountModule.isLoggedIn) {
      _loadHistory();
    } else {
      _loginSub = accountModule.loginStatusStream.listen((status) {
        if (status == LoginStatus.success) {
          _loginSub?.cancel();
          _loginSub = null;
          _loadHistory();
        }
      });
    }
  }

  @override
  void dispose() {
    _loginSub?.cancel();
    super.dispose();
  }

  @override
  void reloadAfterReconnect() {
    if (accountModule.isLoggedIn) _loadHistory();
  }

  Future<void> _loadHistory() async {
    final p = await AppDatabase.loadActiveProfile();
    if (p == null) {
      if (mounted) setState(() => _isLoading = false);
      return;
    }

    final callsModule = CallsModule(api);
    List<CallLogEntry> calls;
    try {
      calls = await callsModule.fetchHistory(p.id, p.id);
    } catch (e) {
      if (mounted) setState(() => _isLoading = false);
      return;
    }

    final List<CallLogEntry> grouped = [];
    for (final call in calls) {
      if (grouped.isNotEmpty &&
          grouped.last.peerId == call.peerId &&
          grouped.last.status == call.status &&
          _isSameDay(grouped.last.time, call.time)) {
        final last = grouped.removeLast();
        grouped.add(
          CallLogEntry(
            id: last.id,
            accountId: last.accountId,
            peerId: last.peerId,
            name: last.name,
            avatarUrl: last.avatarUrl,
            status: last.status,
            time: last.time,
            count: last.count + 1,
            isGroup: last.isGroup,
          ),
        );
      } else {
        grouped.add(call);
      }
    }

    if (mounted) {
      setState(() {
        _calls = grouped;
        _isLoading = false;
      });
    }
  }

  bool _isSameDay(int time1, int time2) {
    if (time1 == 0 || time2 == 0) return false;
    final d1 = DateTime.fromMillisecondsSinceEpoch(time1);
    final d2 = DateTime.fromMillisecondsSinceEpoch(time2);
    return d1.year == d2.year && d1.month == d2.month && d1.day == d2.day;
  }

  String _formatDate(int timestamp) {
    if (timestamp == 0) return '';
    final dt = DateTime.fromMillisecondsSinceEpoch(timestamp);
    return '${dt.day} ${kRuMonthsShort[dt.month - 1]}';
  }

  Widget _buildCallItem(
    BuildContext context,
    ColorScheme cs,
    CallLogEntry call,
  ) {
    final bool isMissed = call.status == CallStatus.missed;

    String statusText;
    IconData statusIcon;
    switch (call.status) {
      case CallStatus.missed:
        statusText = 'Пропущенный';
        statusIcon = Symbols.phone_missed;
        break;
      case CallStatus.canceled:
        statusText = 'Отменённый';
        statusIcon = Symbols.phone_disabled;
        break;
      case CallStatus.outgoing:
        statusText = 'Исходящий';
        statusIcon = Symbols.call_made;
        break;
      case CallStatus.incoming:
        statusText = 'Входящий';
        statusIcon = Symbols.call_received;
        break;
    }

    final String displayName = call.count > 1
        ? '${call.name} (${call.count})'
        : call.name;

    return Material(
      color: Colors.transparent,
      child: InkWell(
        onTap: () {},
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
          child: Row(
            children: [
              Container(
                width: 48,
                height: 48,
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: call.isGroup ? cs.primaryContainer : null,
                  border: Border.all(
                    color: cs.primary.withValues(alpha: 0.1),
                    width: 1,
                  ),
                ),
                child: call.isGroup
                    ? Icon(
                        Symbols.groups,
                        color: cs.onPrimaryContainer,
                        size: 26,
                      )
                    : KometAvatar(
                        name: call.name,
                        imageUrl: call.avatarUrl,
                        size: 48,
                      ),
              ),
              const SizedBox(width: 16),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      displayName,
                      style: TextStyle(
                        color: isMissed ? cs.error : cs.onSurface,
                        fontSize: 16,
                        fontWeight: FontWeight.w500,
                      ),
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                    ),
                    const SizedBox(height: 4),
                    Row(
                      children: [
                        Icon(statusIcon, size: 14, color: cs.onSurfaceVariant),
                        const SizedBox(width: 4),
                        Text(
                          statusText,
                          style: TextStyle(
                            color: cs.onSurfaceVariant,
                            fontSize: 14,
                          ),
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                        ),
                      ],
                    ),
                  ],
                ),
              ),
              const SizedBox(width: 8),
              Text(
                _formatDate(call.time),
                style: TextStyle(
                  color: cs.onSurfaceVariant.withValues(alpha: 0.7),
                  fontSize: 12,
                ),
              ),
              const SizedBox(width: 4),
              Builder(
                builder: (btnContext) => IconButton(
                  icon: Icon(
                    Symbols.more_vert,
                    color: cs.onSurfaceVariant,
                    size: 20,
                    weight: 400,
                  ),
                  padding: EdgeInsets.zero,
                  visualDensity: VisualDensity.compact,
                  constraints: const BoxConstraints(
                    minWidth: 36,
                    minHeight: 36,
                  ),
                  onPressed: () => _showCallMenu(btnContext, call),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _showCallMenu(BuildContext anchorContext, CallLogEntry call) {
    final box = anchorContext.findRenderObject() as RenderBox?;
    if (box == null || !box.hasSize) return;
    final anchorRect = box.localToGlobal(Offset.zero) & box.size;
    showChatMenu(
      context: context,
      anchorRect: anchorRect,
      items: [
        ChatMenuItem(
          icon: Symbols.delete,
          label: 'Удалить',
          destructive: true,
          onTap: () => _deleteCall(call),
        ),
        if (!call.isGroup)
          ChatMenuItem(
            icon: Symbols.call,
            label: 'Перезвонить',
            onTap: () => _callBack(call),
          ),
      ],
    );
  }

  void _deleteCall(CallLogEntry call) {
    if (_removing.contains(call.id)) return;
    setState(() => _removing.add(call.id));
    final historyId = int.tryParse(call.id);
    if (historyId != null) {
      unawaited(CallsModule(api).deleteHistory([historyId]));
    }
  }

  void _onRemovalComplete(String id) {
    if (!mounted) return;
    setState(() {
      _calls.removeWhere((c) => c.id == id);
      _removing.remove(id);
    });
  }

  Future<void> _callBack(CallLogEntry call) async {
    if (call.peerId <= 0) {
      showCustomNotification(context, 'Не удалось определить собеседника');
      return;
    }
    final navigator = Navigator.of(context);
    final avatarUrl = (call.avatarUrl?.isNotEmpty ?? false)
        ? call.avatarUrl
        : null;
    final active = CallController.instance.activeSession;
    if (active != null) {
      await navigator.push(
        MaterialPageRoute(
          builder: (_) => CallScreen(
            name: call.name,
            avatarUrl: avatarUrl,
            session: active,
          ),
        ),
      );
      return;
    }
    try {
      final session = await CallController.instance.startOutgoing(call.peerId);
      if (!mounted) return;
      await navigator.push(
        MaterialPageRoute(
          builder: (_) => CallScreen(
            name: call.name,
            avatarUrl: avatarUrl,
            session: session,
          ),
        ),
      );
    } catch (_) {
      if (!mounted) return;
      showCustomNotification(context, 'Не удалось начать звонок');
    }
  }

  Widget _buildLinkAction(
    ColorScheme cs, {
    required IconData icon,
    required String label,
    required VoidCallback onTap,
    bool alignEnd = false,
  }) {
    return InkWell(
      onTap: onTap,
      borderRadius: BorderRadius.circular(12),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
        child: Row(
          mainAxisAlignment: alignEnd
              ? MainAxisAlignment.end
              : MainAxisAlignment.start,
          children: [
            Icon(icon, color: cs.primary, size: 24),
            const SizedBox(width: 12),
            Flexible(
              child: Text(
                label,
                style: TextStyle(
                  color: cs.primary,
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                ),
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _createGroupCall() async {
    final controller = CallController.instance;
    if (controller.isBusy) {
      showCustomNotification(context, 'Звонок уже идёт');
      return;
    }

    final navigator = Navigator.of(context);
    ({CallSession session, String? joinLink}) created;
    try {
      created = await controller.createGroupCall();
    } catch (e) {
      if (mounted) {
        showCustomNotification(context, 'Не удалось создать звонок: $e');
      }
      return;
    }
    if (!mounted) return;

    final link = created.joinLink;
    if (link != null) {
      await Clipboard.setData(ClipboardData(text: link));
      if (!mounted) return;
      showCustomNotification(context, 'Ссылка на звонок скопирована');
    }

    await navigator.push(
      MaterialPageRoute(
        builder: (_) => CallScreen(
          name: 'Групповой звонок',
          session: created.session,
          isGroup: true,
        ),
      ),
    );
  }

  Future<void> _joinGroupCall() async {
    if (CallController.instance.isBusy) {
      showCustomNotification(context, 'Звонок уже идёт');
      return;
    }

    final url = await showTextInputDialog(
      context,
      title: 'Присоединиться к звонку',
      description: 'Вставьте ссылку-приглашение',
      hint: 'https://max.ru/joincall/...',
      confirmLabel: 'Присоединиться',
      keyboardType: TextInputType.url,
    );
    if (url == null || url.trim().isEmpty || !mounted) return;

    final handled = await tryHandleCallLink(context, url.trim());
    if (!handled && mounted) {
      showCustomNotification(context, 'Это не ссылка на звонок');
    }
  }

  Widget _buildTabItem(String label, int index, ColorScheme cs) {
    final isSelected = _selectedTabIndex == index;
    return GestureDetector(
      onTap: () {
        setState(() {
          _selectedTabIndex = index;
        });
      },
      child: Container(
        padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
        decoration: BoxDecoration(
          border: Border(
            bottom: BorderSide(
              color: isSelected ? cs.primary : Colors.transparent,
              width: 2,
            ),
          ),
        ),
        child: Text(
          label,
          style: TextStyle(
            color: isSelected ? cs.primary : cs.onSurfaceVariant,
            fontSize: 16,
            fontWeight: FontWeight.w500,
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    final filteredCalls = _selectedTabIndex == 1
        ? _calls.where((c) => c.status == CallStatus.missed).toList()
        : _calls;

    return Scaffold(
      backgroundColor: spectrumSurfaceColor(cs),
      body: SafeArea(
        bottom: false,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(20, 16, 20, 8),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    'Звонки',
                    style: TextStyle(
                      color: cs.onSurface,
                      fontSize: 24,
                      fontWeight: FontWeight.w700,
                      fontFamily: 'Outfit',
                    ),
                  ),
                  const ConnectionStatusLine(),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 8),
              child: Row(
                children: [
                  Expanded(
                    child: _buildLinkAction(
                      cs,
                      icon: Symbols.link,
                      label: 'Создать звонок',
                      onTap: _createGroupCall,
                    ),
                  ),
                  Expanded(
                    child: _buildLinkAction(
                      cs,
                      icon: Symbols.group_add,
                      label: 'Присоединиться',
                      onTap: _joinGroupCall,
                      alignEnd: true,
                    ),
                  ),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 4),
              child: Row(
                children: [
                  _buildTabItem('Все', 0, cs),
                  const SizedBox(width: 8),
                  _buildTabItem('Пропущенные', 1, cs),
                ],
              ),
            ),
            Expanded(
              child: _isLoading
                  ? const Center(child: SmallSpinner(size: 36))
                  : filteredCalls.isEmpty
                  ? Center(
                      child: Text(
                        'Нет звонков',
                        style: TextStyle(
                          color: cs.onSurfaceVariant,
                          fontSize: 16,
                        ),
                      ),
                    )
                  : ListView.builder(
                      physics: const BouncingScrollPhysics(),
                      padding: const EdgeInsets.only(bottom: 120),
                      itemCount: filteredCalls.length,
                      itemBuilder: (context, index) {
                        final call = filteredCalls[index];
                        return _RemovableCallEntry(
                          key: ValueKey(call.id),
                          removing: _removing.contains(call.id),
                          onDismissed: () => _onRemovalComplete(call.id),
                          child: _buildCallItem(context, cs, call),
                        );
                      },
                    ),
            ),
          ],
        ),
      ),
    );
  }
}

class _RemovableCallEntry extends StatefulWidget {
  final bool removing;
  final VoidCallback onDismissed;
  final Widget child;

  const _RemovableCallEntry({
    required Key key,
    required this.removing,
    required this.onDismissed,
    required this.child,
  }) : super(key: key);

  @override
  State<_RemovableCallEntry> createState() => _RemovableCallEntryState();
}

class _RemovableCallEntryState extends State<_RemovableCallEntry>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller = AnimationController(
    vsync: this,
    duration: const Duration(milliseconds: 260),
    value: 1.0,
  );
  late final Animation<double> _animation = CurvedAnimation(
    parent: _controller,
    curve: Curves.easeOutCubic,
  );

  @override
  void initState() {
    super.initState();
    _controller.addStatusListener(_onStatus);
  }

  void _onStatus(AnimationStatus status) {
    if (status == AnimationStatus.dismissed) widget.onDismissed();
  }

  @override
  void didUpdateWidget(covariant _RemovableCallEntry oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.removing && !oldWidget.removing) _controller.reverse();
  }

  @override
  void dispose() {
    _controller.removeStatusListener(_onStatus);
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizeTransition(
      sizeFactor: _animation,
      alignment: Alignment.topCenter,
      child: FadeTransition(opacity: _animation, child: widget.child),
    );
  }
}
