import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:dio/dio.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter/material.dart';
import '../main.dart';
import '../screens/welcome_screen.dart';
import '../utils/log_manager.dart';

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  // Google Sign-In 설정 (Backend와 통신하기 위해 serverClientId 지정)
  final GoogleSignIn _googleSignIn = GoogleSignIn(
    serverClientId:
        '379988243470-g6490l8gucc3ljras93i28c3l4qlroi4.apps.googleusercontent.com',
  );
  final Dio _dio = Dio();
  final FlutterSecureStorage _storage = const FlutterSecureStorage();

  // Backend Base URL
  final String _baseUrl = 'http://10.0.2.2:3000/auth';

  AuthService() {
    // Dio Options 설정 (Timeout 추가)
    _dio.options.connectTimeout = const Duration(seconds: 5); // 5초 연결 타임아웃
    _dio.options.receiveTimeout = const Duration(seconds: 5); // 5초 응답 타임아웃

    // Dio Interceptor 설정
    _dio.interceptors.add(
      InterceptorsWrapper(
        onRequest: (options, handler) async {
          // 모든 요청 헤더에 Access Token 추가
          final accessToken = await _storage.read(key: 'accessToken');
          if (accessToken != null) {
            options.headers['Authorization'] = 'Bearer $accessToken';
          }
          return handler.next(options);
        },
        onError: (DioException error, handler) async {
          // 401 에러 발생 시 (Access Token 만료)
          if (error.response?.statusCode == 401) {
            String msg1 = '[Auth] Access Token expired. Attempting refresh...';
            print(msg1);
            LogManager().addLog(msg1); // LOG

            final isRefreshed = await _refreshToken();
            if (isRefreshed) {
              // 토큰 갱신 성공 -> 원래 요청 재시도
              final newAccessToken = await _storage.read(key: 'accessToken');

              // 헤더 업데이트
              error.requestOptions.headers['Authorization'] =
                  'Bearer $newAccessToken';

              // 재요청
              try {
                final response = await _dio.fetch(error.requestOptions);
                return handler.resolve(response);
              } catch (e) {
                return handler.reject(error);
              }
            } else {
              // 토큰 갱신 실패 (리프레시 토큰도 만료됨) -> 로그아웃 & 화면 이동
              String msg2 = '[Auth] Refresh Token expired. Logging out...';
              print(msg2);
              LogManager().addLog(msg2); // LOG
              await signOut();

              // Force Navigation to Welcome Screen
              navigatorKey.currentState?.pushAndRemoveUntil(
                MaterialPageRoute(builder: (context) => const WelcomeScreen()),
                (route) => false,
              );
            }
          } else {
            // Log other errors
            LogManager().addLog(
              '[DioError] ${error.message} (Status: ${error.response?.statusCode})',
            );
          }
          return handler.next(error);
        },
      ),
    );
  }

  // 토큰 갱신 로직
  Future<bool> _refreshToken() async {
    try {
      final refreshToken = await _storage.read(key: 'refreshToken');
      if (refreshToken == null) return false;

      final response = await _dio.post(
        '$_baseUrl/refresh',
        data: {'refreshToken': refreshToken},
      );

      if (response.statusCode == 200 && response.data['success'] == true) {
        final newAccessToken = response.data['accessToken'];
        await _storage.write(key: 'accessToken', value: newAccessToken);
        String msg = '[Auth] Token refreshed successfully.';
        print(msg);
        LogManager().addLog(msg);
        return true;
      }
      return false;
    } catch (e) {
      String msg = '[Auth] Token refresh failed: $e';
      print(msg);
      LogManager().addLog(msg);
      return false;
    }
  }

  // 구글 로그인 (Check or Login)
  Future<Map<String, dynamic>?> signInWithGoogle() async {
    try {
      LogManager().addLog('[DEBUG] Google Sign-In: Starting signIn()');
      final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();

      if (googleUser == null) {
        LogManager().addLog('[DEBUG] Google Sign-In: User canceled');
        return null;
      }

      final GoogleSignInAuthentication googleAuth =
          await googleUser.authentication;

      if (googleAuth.idToken != null) {
        try {
          // 1. 서버에 토큰 전송 (Login Check)
          final response = await _dio.post(
            '$_baseUrl/google',
            data: {'idToken': googleAuth.idToken},
          );

          if (response.statusCode == 200 && response.data['success'] == true) {
            final isNewUser = response.data['isNewUser'] ?? false;

            if (isNewUser) {
              // 신규 유저: 토큰 저장하지 않고 idToken 반환 (약관 동의 화면으로 전달)
              return {
                'isNewUser': true,
                'idToken': googleAuth.idToken,
                'email': response.data['email'],
                'nickname': response.data['nickname'],
              };
            } else {
              // 기존 유저: 토큰 저장 및 로그인 처리
              final accessToken = response.data['accessToken'];
              final refreshToken = response.data['refreshToken'];

              await _storage.write(key: 'accessToken', value: accessToken);
              await _storage.write(key: 'refreshToken', value: refreshToken);

              // Firebase 로그인 (선택 사항, 필요하다면 유지)
              final OAuthCredential credential = GoogleAuthProvider.credential(
                accessToken: googleAuth.accessToken,
                idToken: googleAuth.idToken,
              );
              await _auth.signInWithCredential(credential);

              return {'isNewUser': false};
            }
          }
        } catch (e) {
          String msg = '[ERROR] Backend Auth API Error: $e';
          print(msg);
          LogManager().addLog(msg);
        }
      }
      return null;
    } catch (e) {
      String msg = '[ERROR] Google Sign-In Error: $e';
      print(msg);
      LogManager().addLog(msg);
      return null;
    }
  }

  // 구글 회원가입 (Register - 약관 동의 후 호출)
  Future<bool> registerWithGoogle(String idToken) async {
    try {
      final response = await _dio.post(
        '$_baseUrl/google/register',
        data: {'idToken': idToken},
      );

      if (response.statusCode == 200 && response.data['success'] == true) {
        final accessToken = response.data['accessToken'];
        final refreshToken = response.data['refreshToken'];

        await _storage.write(key: 'accessToken', value: accessToken);
        await _storage.write(key: 'refreshToken', value: refreshToken);

        // Firebase 로그인 처리
        // idToken으로 Credential 생성하여 로그인
        final OAuthCredential credential = GoogleAuthProvider.credential(
          idToken: idToken,
          accessToken: null, // accessToken은 필수가 아님 (idToken만으로 가능)
        );
        await _auth.signInWithCredential(credential);

        return true;
      }
      return false;
    } catch (e) {
      LogManager().addLog('[Auth] Register Failed: $e');
      return false;
    }
  }

  // 로그아웃
  Future<void> signOut() async {
    await _googleSignIn.signOut();
    await _auth.signOut();
    await _storage.deleteAll(); // 토큰 삭제
    print('[DEBUG] User signed out and tokens cleared.');
  }

  // Access Token 가져오기
  Future<String?> getAccessToken() async {
    return await _storage.read(key: 'accessToken');
  }

  // 유저 정보 가져오기
  Future<Map<String, dynamic>?> getUserInfo() async {
    try {
      final response = await _dio.get('$_baseUrl/me');
      if (response.statusCode == 200 && response.data['success'] == true) {
        return response.data['user'];
      }
      return null;
    } catch (e) {
      LogManager().addLog('[Auth] Get User Info Failed: $e');
      return null;
    }
  }

  // 회원 탈퇴
  Future<bool> withdrawAccount() async {
    try {
      final response = await _dio.delete('$_baseUrl/withdraw');
      if (response.statusCode == 200 && response.data['success'] == true) {
        await _googleSignIn.signOut();
        await _auth.signOut();
        await _storage.deleteAll();
        return true;
      }
      return false;
    } catch (e) {
      LogManager().addLog('[Auth] Withdraw Account Failed: $e');
      return false;
    }
  }

  Dio get dio => _dio;
}
