import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../config/api_config.dart';
import '../models/member_model.dart';
import './api_service.dart';
import './event_bus.dart';

class MemberService with ChangeNotifier {
  List<Member> _members = [];
  bool _isLoading = false;
  String? _token;
  String? _clubId;
  final ApiService _apiService;
  StreamSubscription? _eventSubscription;
  String? _lastError;
  DateTime? _lastLoadedAt;
  bool _disposed = false;
  
  // 기본 생성자
  MemberService() : _apiService = ApiService();
  
  // 테스트용 생성자
  MemberService.forTest(this._apiService);

  List<Member> get members => [..._members];
  bool get isLoading => _isLoading;
  String? get lastError => _lastError;
  DateTime? get lastLoadedAt => _lastLoadedAt;

  // 초기화 함수
  void initialize(String token) {
    _token = token;
    _apiService.setToken(token);
    
    // 이벤트 구독 - 기존 구독이 있으면 취소 후 다시 구독
    _eventSubscription?.cancel();
    _eventSubscription = EventBus().on<ClubChangedEvent>().listen((event) {
      if (_disposed) return; // dispose 이후 방어
      if (event.clubId.isNotEmpty) {
        setClubId(event.clubId);
      }
    });
  }
  
  // (개발 중 로깅 유틸 제거됨)
  
  @override
  void dispose() {
    // dispose 시작 상태 로깅
    if (kDebugMode) {
      debugPrint('MemberService: dispose 시작');
    }
    // 비동기 상태 로깅은 테스트/런타임 안정성을 위해 동기 경로로 축소
    // (필요 시 개발 중 수동 호출)

    // 이벤트 구독 취소: 동기 dispose 규약을 지키기 위해 unawaited로 처리
    _disposed = true; // 이후 작업 차단
    if (_eventSubscription != null) {
      try {
        if (kDebugMode) {
          debugPrint('MemberService: 구독 취소 시작');
        }
        unawaited(_eventSubscription!.cancel());
        _eventSubscription = null;
        if (kDebugMode) {
          debugPrint('MemberService: 구독 취소 요청');
        }
      } catch (e) {
        if (kDebugMode) {
          debugPrint('MemberService: 구독 취소 중 오류 - $e');
        }
      }
    }

    if (kDebugMode) {
      debugPrint('MemberService: dispose 종료');
    }
    super.dispose();
  }

  // 클럽 ID 설정
  Future<void> setClubId(String clubId) async {
    if (_disposed) return; // dispose 이후 무시
    // 클럽 ID가 변경된 경우에만 처리
    if (_clubId != clubId) {
      _clubId = clubId;
      
      // SharedPreferences에 저장
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString(ApiConfig.clubIdKey, clubId);
      
      notifyListeners();
      
      // 새 클럽의 회원 목록 가져오기
      if (_token != null) {
        await fetchClubMembers();
      }
    }
  }

  // 클럽의 모든 회원 가져오기
  Future<void> fetchClubMembers() async {
    if (_disposed) return; // dispose 이후 무시
    final sw = Stopwatch()..start();
    if (kDebugMode) {
      debugPrint('MemberService.fetchClubMembers: 시작 (token=${_token != null}, clubId=$_clubId)');
    }

    _isLoading = true;
    _lastError = null;
    notifyListeners();

    try {
      // 클럽 ID 가져오기 - 메모리에 저장된 값을 우선 사용
      String? clubId = _clubId;
      
      // 메모리에 없으면 SharedPreferences에서 가져오기
      if (clubId == null) {
        final prefs = await SharedPreferences.getInstance();
        clubId = prefs.getString(ApiConfig.clubIdKey);
      }

      if (clubId == null) {
        if (kDebugMode) {
          debugPrint('MemberService.fetchClubMembers: clubId 없음 - SharedPreferences에도 없음');
        }
        throw Exception('선택된 클럽이 없습니다');
      }

      final data = await _apiService.post(
        '${ApiConfig.clubs}/members',
        data: {'clubId': clubId},
      );

      if (kDebugMode) {
        debugPrint('MemberService.fetchClubMembers: 응답 수신 (elapsed=${sw.elapsedMilliseconds}ms)');
      }

      // 응답 데이터가 리스트 형태로 직접 왔으므로 그대로 사용
      if (data is List) {
        final List<dynamic> membersData = data;
        _members = membersData
            .map((memberData) => Member.fromJson(memberData))
            .toList();
        if (kDebugMode) {
          debugPrint('MemberService.fetchClubMembers: 리스트 파싱 완료 (count=${_members.length})');
          if (_members.isEmpty) {
            debugPrint('MemberService.fetchClubMembers: 회원 목록이 비어있음');
          }
        }
      } else {
        // 응답 데이터가 객체 형태로 왔을 경우 members 키를 통해 접근
        final List<dynamic> membersData = data['members'] ?? [];
        _members = membersData
            .map((memberData) => Member.fromJson(memberData))
            .toList();
        if (kDebugMode) {
          debugPrint('MemberService.fetchClubMembers: 객체 파싱 완료 (count=${_members.length})');
          if (_members.isEmpty) {
            debugPrint('MemberService.fetchClubMembers: 회원 목록이 비어있음');
          }
        }
      }

      _isLoading = false;
      _lastLoadedAt = DateTime.now();
      notifyListeners();
      if (kDebugMode) {
        debugPrint('MemberService.fetchClubMembers: 성공 (total=${_members.length}, elapsed=${sw.elapsedMilliseconds}ms, loadedAt=${_lastLoadedAt?.toIso8601String()})');
      }
    } catch (e, st) {
      _isLoading = false;
      _lastError = e.toString();
      notifyListeners();
      if (kDebugMode) {
        debugPrint('MemberService.fetchClubMembers: 실패 (${e.toString()})');
        debugPrint('MemberService.fetchClubMembers: stacktrace -> $st');
      }
      throw Exception('회원 목록을 불러오는데 실패했습니다: $e');
    }
  }

  // ID로 회원 정보 가져오기
  Future<Member> fetchMemberById(String memberId) async {
    if (_token == null || _clubId == null) {
      throw Exception('인증 또는 클럽 정보가 필요합니다');
    }

    try {
      final data = await _apiService.post(
        '${ApiConfig.clubs}/members/detail',
        data: {'memberId': memberId},
      );

      if (data['statusCode'] == 200) {
        final memberData = data['member'];
        return Member.fromJson(memberData);
      } else {
        throw Exception('회원 정보를 불러오는데 실패했습니다');
      }
    } catch (e) {
      throw Exception('회원 정보를 불러오는데 실패했습니다: $e');
    }
  }

  // 회원 추가
  Future<Member> addMember(Map<String, dynamic> memberData) async {
    if (_token == null || _clubId == null) {
      throw Exception('인증 또는 클럽 정보가 필요합니다');
    }

    _isLoading = true;
    notifyListeners();

    try {
      final payload = {
        'clubId': _clubId,
        ...memberData,
      };
      final data = await _apiService.post(
        '${ApiConfig.clubs}/members/add',
        data: payload,
      );

      // 백엔드 응답 처리: 직접 회원 객체가 반환되거나 {member: {...}} 형태로 반환될 수 있음
      final newMember = data is Map && data.containsKey('member')
          ? Member.fromJson(data['member'])
          : Member.fromJson(data);

      _members.add(newMember);

      _isLoading = false;
      notifyListeners();

      return newMember;
    } catch (e) {
      _isLoading = false;
      notifyListeners();
      throw Exception('회원 추가에 실패했습니다: $e');
    }
  }

  // 회원 정보 업데이트
  Future<Member> updateMember(
    String memberId,
    Map<String, dynamic> updates,
  ) async {
    if (_token == null || _clubId == null) {
      throw Exception('인증 또는 클럽 정보가 필요합니다');
    }

    _isLoading = true;
    notifyListeners();

    try {
      final data = await _apiService.post(
        '${ApiConfig.clubs}/members/update',
        data: {'clubId': _clubId, 'memberId': memberId, ...updates},
      );

      // 응답 데이터가 { member: {...} } 형태인지 또는 직접 회원 객체인지 확인
      final Map<String, dynamic> memberData = data['member'] != null
          ? data['member'] as Map<String, dynamic>
          : data as Map<String, dynamic>;

      final updatedMember = Member.fromJson(memberData);

      // 회원 목록 업데이트
      final index = _members.indexWhere((member) => member.id == memberId);
      if (index >= 0) {
        _members[index] = updatedMember;
      }

      _isLoading = false;
      notifyListeners();

      return updatedMember;
    } catch (e) {
      _isLoading = false;
      notifyListeners();
      throw Exception('회원 정보 업데이트에 실패했습니다: $e');
    }
  }

  // 회원 삭제 (또는 비활성화)
  Future<bool> deleteMember(String memberId) async {
    if (_token == null || _clubId == null) {
      throw Exception('인증 또는 클럽 정보가 필요합니다');
    }

    _isLoading = true;
    notifyListeners();

    try {
      await _apiService.post(
        '${ApiConfig.clubs}/members/delete',
        data: {'memberId': memberId, 'clubId': _clubId},
      );

      // 회원 목록에서 제거
      _members.removeWhere((member) => member.id == memberId);

      _isLoading = false;
      notifyListeners();

      return true;
    } catch (e) {
      _isLoading = false;
      notifyListeners();
      throw Exception('회원 삭제에 실패했습니다: $e');
    }
  }
  
  // 여러 회원 ID로 회원 정보 가져오기
  Future<List<Member>> fetchMembersByIds(String clubId, List<String> memberIds) async {
    if (_token == null) {
      throw Exception('인증이 필요합니다');
    }
    
    if (memberIds.isEmpty) {
      return [];
    }

    try {
      // 이미 로드된 회원 정보 중에서 필터링
      if (_members.isNotEmpty && _clubId == clubId) {
        final cachedMembers = _members.where((member) => memberIds.contains(member.id)).toList();
        
        // 모든 회원 정보가 캐시에 있는 경우
        if (cachedMembers.length == memberIds.length) {
          return cachedMembers;
        }
      }
      
      // API로 회원 정보 요청
      final data = await _apiService.post(
        '${ApiConfig.clubs}/members/batch',
        data: {
          'clubId': clubId,
          'memberIds': memberIds,
        },
      );

      if (data is List) {
        return data.map((memberData) => Member.fromJson(memberData)).toList();
      } else if (data['members'] != null && data['members'] is List) {
        return (data['members'] as List).map((memberData) => Member.fromJson(memberData)).toList();
      } else {
        throw Exception('회원 정보 형식이 올바르지 않습니다');
      }
    } catch (e) {
      throw Exception('회원 정보를 불러오는데 실패했습니다: $e');
    }
  }
}
