import 'dart:convert';

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

import '../services/im_service.dart';
import '../theme.dart';
import '../widgets/avatar.dart';
import '../widgets/search_box.dart';
import 'add_friend_screen.dart';
import 'chat_screen.dart';
import 'group_list_screen.dart';
import 'new_friends_screen.dart';

/// 同事扩展信息（friendInfo 的 ex 字段，JSON 格式）
class _ContactEx {
  final String department;
  final String title;

  _ContactEx(this.department, this.title);

  /// 解析 ex 字段；解析不到归「同事」组、无职务
  static _ContactEx parse(String? ex) {
    if (ex == null || ex.isEmpty) return _ContactEx('同事', '');
    try {
      final map = jsonDecode(ex);
      if (map is Map<String, dynamic>) {
        return _ContactEx(
          map['department']?.toString() ?? '同事',
          map['title']?.toString() ?? '',
        );
      }
    } catch (_) {
      // 不是 JSON 按默认组处理
    }
    return _ContactEx('同事', '');
  }
}

/// 通讯录页（效果图 m3）：
/// 标题 + 添加人图标、搜索框、「新的同事」「我的群聊」两行入口、按部门分组的联系人列表。
/// 数据源：OpenIM 好友列表，部门/职务取自好友 ex 字段（JSON）。
class ContactsScreen extends StatefulWidget {
  const ContactsScreen({super.key});

  @override
  State<ContactsScreen> createState() => _ContactsScreenState();
}

class _ContactsScreenState extends State<ContactsScreen> {
  List<FriendInfo> _friends = [];
  int _pendingRequests = 0;
  bool _loading = true;
  bool _failed = false;
  String _keyword = '';

  @override
  void initState() {
    super.initState();
    _load();
    // 好友变更时刷新（IMService 会 notifyListeners）
    IMService.instance.addListener(_onImChanged);
  }

  @override
  void dispose() {
    IMService.instance.removeListener(_onImChanged);
    super.dispose();
  }

  void _onImChanged() => _load();

  Future<void> _load() async {
    if (!IMService.instance.loggedIn) return;
    try {
      final friends = await OpenIM.iMManager.friendshipManager.getFriendList();
      final applications = await OpenIM.iMManager.friendshipManager.getFriendApplicationListAsRecipient();
      if (!mounted) return;
      setState(() {
        _friends = friends;
        _pendingRequests = applications.where((a) => a.handleResult == 0).length;
        _loading = false;
        _failed = false;
      });
    } catch (_) {
      if (!mounted) return;
      setState(() {
        _loading = false;
        _failed = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('通讯录'),
        actions: [
          IconButton(
            icon: const Icon(Icons.person_add_alt, size: 24),
            onPressed: () {
              Navigator.of(context)
                  .push(MaterialPageRoute(builder: (_) => const AddFriendScreen()))
                  .then((_) => _load());
            },
          ),
        ],
      ),
      body: Column(
        children: [
          SearchBox(onChanged: (v) => setState(() => _keyword = v)),
          Expanded(child: _buildBody()),
        ],
      ),
    );
  }

  Widget _buildBody() {
    if (_loading) {
      return const Center(child: CircularProgressIndicator(color: AppColors.primary));
    }
    if (_failed) {
      return Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Text('通讯录没加载出来', style: TextStyle(fontSize: AppFont.body, color: AppColors.textPrimary)),
            const SizedBox(height: AppGap.x2),
            const Text('检查一下网络，再点重试', style: TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary)),
            const SizedBox(height: AppGap.x4),
            OutlinedButton(onPressed: _load, child: const Text('重试')),
          ],
        ),
      );
    }

    // 搜索时只过滤联系人，隐藏两行功能入口与分组
    if (_keyword.isNotEmpty) {
      final matched = _friends.where((f) => _displayName(f).toLowerCase().contains(_keyword.toLowerCase())).toList();
      if (matched.isEmpty) {
        return const Center(
          child: Text('没有找到相关同事', style: TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary)),
        );
      }
      return ListView.separated(
        itemCount: matched.length,
        separatorBuilder: (_, __) => const Divider(indent: 76),
        itemBuilder: (_, i) => _contactTile(matched[i]),
      );
    }

    // 按部门分组
    final groups = <String, List<FriendInfo>>{};
    for (final f in _friends) {
      final ex = _ContactEx.parse(f.ex);
      groups.putIfAbsent(ex.department, () => []).add(f);
    }
    final departments = groups.keys.toList()..sort((a, b) => a == '同事' ? 1 : b == '同事' ? -1 : a.compareTo(b));

    return ListView(
      children: [
        _entryTile(),
        const SizedBox(height: AppGap.x2),
        for (final dept in departments) ...[
          _groupHeader(dept, groups[dept]!.length),
          for (var i = 0; i < groups[dept]!.length; i++) ...[
            _contactTile(groups[dept]![i]),
            if (i < groups[dept]!.length - 1) const Divider(indent: 76),
          ],
        ],
      ],
    );
  }

  /// 「新的同事」「我的群聊」两行功能入口
  Widget _entryTile() {
    return Column(
      children: [
        ListTile(
          leading: _entryIcon(Icons.person_add_alt),
          title: const Text('新的同事', style: TextStyle(fontSize: AppFont.body)),
          trailing: _pendingRequests > 0
              ? Container(
                  constraints: const BoxConstraints(minWidth: 20),
                  height: 20,
                  padding: const EdgeInsets.symmetric(horizontal: 5),
                  alignment: Alignment.center,
                  decoration: BoxDecoration(color: AppColors.danger, borderRadius: BorderRadius.circular(10)),
                  child: Text(
                    _pendingRequests > 99 ? '99+' : '$_pendingRequests',
                    style: const TextStyle(fontSize: AppFont.small, color: Colors.white),
                  ),
                )
              : const Icon(Icons.chevron_right, color: AppColors.textSecondary),
          onTap: () {
            Navigator.of(context)
                .push(MaterialPageRoute(builder: (_) => const NewFriendsScreen()))
                .then((_) => _load());
          },
        ),
        const Divider(indent: 76),
        ListTile(
          leading: _entryIcon(Icons.people_outline),
          title: const Text('我的群聊', style: TextStyle(fontSize: AppFont.body)),
          trailing: const Icon(Icons.chevron_right, color: AppColors.textSecondary),
          onTap: () {
            Navigator.of(context).push(MaterialPageRoute(builder: (_) => const GroupListScreen()));
          },
        ),
      ],
    );
  }

  Widget _entryIcon(IconData icon) {
    return Container(
      width: 48,
      height: 48,
      decoration: BoxDecoration(
        color: AppColors.bubbleMine,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Icon(icon, color: AppColors.primary),
    );
  }

  Widget _groupHeader(String department, int count) {
    return Container(
      width: double.infinity,
      color: AppColors.pinnedBg,
      padding: const EdgeInsets.symmetric(horizontal: AppGap.x4, vertical: AppGap.x2),
      child: Text(
        '$department（$count 人）',
        style: const TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary),
      ),
    );
  }

  String _displayName(FriendInfo f) {
    if (f.remark?.isNotEmpty == true) return f.remark!;
    return f.nickname ?? f.userID ?? f.friendUserID ?? '';
  }

  Widget _contactTile(FriendInfo f) {
    final name = _displayName(f);
    final ex = _ContactEx.parse(f.ex);
    return ListTile(
      leading: NameAvatar(name: name, faceURL: f.faceURL),
      title: Text(name, style: const TextStyle(fontSize: AppFont.body, color: AppColors.textPrimary)),
      trailing: ex.title.isNotEmpty
          ? Text(ex.title, style: const TextStyle(fontSize: AppFont.sub, color: AppColors.textSecondary))
          : null,
      onTap: () => _openChat(f, name),
    );
  }

  /// 点联系人直接进单聊。
  /// 注意：OpenIM 好友接口返回的字段是 `userID`（`friendUserID` 恒为空），
  /// 必须用 `userID` 作为会话源，否则会建出「空对方」会话导致所有消息发不出去。
  Future<void> _openChat(FriendInfo f, String name) async {
    final peerID = f.userID ?? f.friendUserID ?? '';
    if (peerID.isEmpty) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('对方信息不完整，无法打开会话'), duration: Duration(seconds: 2)),
      );
      return;
    }
    try {
      final conversation = await OpenIM.iMManager.conversationManager.getOneConversation(
        sourceID: peerID,
        sessionType: ConversationType.single,
      );
      conversation.showName = name;
      if (!mounted) return;
      Navigator.of(context).push(MaterialPageRoute(builder: (_) => ChatScreen(conversation: conversation)));
    } catch (_) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('打开会话失败，请检查网络'), duration: Duration(seconds: 2)),
      );
    }
  }
}
