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

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

class ClubService with ChangeNotifier {
  List<Club> _clubs = [];
  Club? _currentClub;
  bool _isLoading = false;
  String? _token;
  ApiService _apiService;
  bool _disposed = false;
  
  // 기본 생성자
  ClubService() : _apiService = ApiService();
  
  // 테스트용 생성자
  ClubService.forTest(this._apiService);

  List<Club> get clubs => [..._clubs];
  Club? get currentClub => _currentClub;
  bool get isLoading => _isLoading;

  // 초기화 함수
  Future<void> initialize(String token) async {
    if (_disposed) return;
    _token = token;
    _apiService.setToken(token);
    
    // 저장된 현재 클럽 ID 가져오기
    final prefs = await SharedPreferences.getInstance();
    final clubId = prefs.getString(ApiConfig.clubIdKey);
    
    if (clubId != null) {
      if (_disposed) return;
      await fetchClubById(clubId);
    }
  }

  // 사용자의 모든 클럽 가져오기
  Future<void> fetchUserClubs() async {
    if (_disposed || _token == null) return;
    
    _isLoading = true;
    if (!_disposed) notifyListeners();
    
    try {
      final data = await _apiService.post('${ApiConfig.clubs}/user');

      final List<dynamic> clubsData = data;
      
      _clubs = clubsData.map((clubData) => Club.fromJson(clubData)).toList();
      
      _isLoading = false;
      if (!_disposed) notifyListeners();
    } catch (e) {
      _isLoading = false;
      if (!_disposed) notifyListeners();
      throw Exception('클럽 목록을 불러오는데 실패했습니다: $e');
    }
  }

  // ID로 클럽 정보 가져오기
  Future<void> fetchClubById(String clubId) async {
    if (_disposed || _token == null) return;
    
    _isLoading = true;
    if (!_disposed) notifyListeners();
    
    try {
      final data = await _apiService.post(
        ApiConfig.clubs,
        data: {'clubId': clubId},
      );

      // 백엔드에서는 club 키로 감싸지 않고 직접 클럽 객체를 반환합니다
      _currentClub = Club.fromJson(data);
      
      // 현재 클럽 ID 저장
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString(ApiConfig.clubIdKey, clubId);
      
      _isLoading = false;
      if (!_disposed) notifyListeners();
    } catch (e) {
      _isLoading = false;
      if (!_disposed) notifyListeners();
      throw Exception('클럽 정보를 불러오는데 실패했습니다: $e');
    }
  }

  // 현재 클럽 설정
  Future<void> setCurrentClub(String clubId) async {
    await fetchClubById(clubId);
  }
  
  // 백엔드에 클럽 선택 요청 (세션에 clubId 저장)
  Future<void> selectClub(String clubId) async {
    if (_disposed || _token == null) return;
    
    _isLoading = true;
    if (!_disposed) notifyListeners();
    
    try {
      await _apiService.post(
        '${ApiConfig.clubs}/select-club',
        data: {'clubId': clubId},
      );

      // 클럽 선택 성공 후 클럽 정보 가져오기
      if (_disposed) return;
      await fetchClubById(clubId);
      
      // 클럽 ID를 로컬에 저장
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString(ApiConfig.clubIdKey, clubId);
      
      // 클럽 데이터도 함께 저장
      if (_currentClub != null) {
        await prefs.setString('${ApiConfig.clubIdKey}_data', jsonEncode(_currentClub!.toJson()));
      }
      
      // 클럽 변경 이벤트 발생 - 다른 서비스들에게 알림
      if (!_disposed) {
        EventBus().fire(ClubChangedEvent(clubId));
      }
      
      _isLoading = false;
      if (!_disposed) notifyListeners();
    } catch (e) {
      _isLoading = false;
      if (!_disposed) notifyListeners();
      throw Exception('클럽 선택에 실패했습니다: $e');
    }
  }

  // 클럽 생성
  Future<Club> createClub(Club club) async {
    if (_token == null) {
      throw Exception('인증이 필요합니다');
    }
    
    _isLoading = true;
    if (!_disposed) notifyListeners();
    
    try {
      final data = await _apiService.post(
        ApiConfig.clubs,
        data: club.toJson(),
      );

      final newClub = Club.fromJson(data['club']);
      
      _clubs.add(newClub);
      _currentClub = newClub;
      
      // 현재 클럽 ID 저장
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString(ApiConfig.clubIdKey, newClub.id);
      
      _isLoading = false;
      if (!_disposed) notifyListeners();
      
      return newClub;
    } catch (e) {
      _isLoading = false;
      if (!_disposed) notifyListeners();
      throw Exception('클럽 생성에 실패했습니다: $e');
    }
  }

  // 클럽 정보 업데이트
  Future<Club> updateClub(String clubId, Map<String, dynamic> updates) async {
    if (_disposed || _token == null) {
      throw Exception('인증이 필요합니다');
    }
    
    _isLoading = true;
    if (!_disposed) notifyListeners();
    
    try {
      final data = await _apiService.put(
        ApiConfig.clubs,
        data: {
          'clubId': clubId,
          ...updates,
        },
      );

      // 백엔드 응답 처리: 직접 클럽 객체가 반환되거나 {club: {...}} 형태로 반환될 수 있음
      final updatedClub = data is Map && data.containsKey('club') 
          ? Club.fromJson(data['club']) 
          : Club.fromJson(data);
      
      // 클럽 목록 업데이트
      final index = _clubs.indexWhere((club) => club.id == clubId);
      if (index >= 0) {
        _clubs[index] = updatedClub;
      }
      
      // 현재 클럽이 업데이트된 클럽인 경우 업데이트
      if (_currentClub?.id == clubId) {
        _currentClub = updatedClub;
      }
      
      _isLoading = false;
      if (!_disposed) notifyListeners();
      
      return updatedClub;
    } catch (e) {
      _isLoading = false;
      if (!_disposed) notifyListeners();
      throw Exception('클럽 정보 업데이트에 실패했습니다: $e');
    }
  }
  
  // 클럽 정보 가져오기 (ID로)
  Future<Club> fetchClub(String clubId) async {
    if (_disposed || _token == null) {
      throw Exception('인증이 필요합니다');
    }
    
    try {
      // 현재 클럽이 요청한 클럽과 동일한 경우 캐시된 데이터 반환
      if (_currentClub != null && _currentClub!.id == clubId) {
        return _currentClub!;
      }
      
      final data = await _apiService.post(
        ApiConfig.clubs,
        data: {'clubId': clubId},
      );

      final club = Club.fromJson(data);
      return club;
    } catch (e) {
      throw Exception('클럽 정보를 불러오는데 실패했습니다: $e');
    }
  }

  @override
  void dispose() {
    _disposed = true;
    super.dispose();
  }
}
