import 'package:awesome_dio_interceptor/awesome_dio_interceptor.dart';
import 'package:dio/dio.dart';
import 'package:enaklo_pos/core/constants/variables.dart';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
import 'package:enaklo_pos/data/models/response/auth_response_model.dart';
import 'package:enaklo_pos/presentation/auth/login_page.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class DioClient {
  static final Dio _dio = Dio(BaseOptions(
    connectTimeout: const Duration(minutes: 1),
    receiveTimeout: const Duration(minutes: 1),
    headers: {
      'Accept': 'application/json',
    },
  ))
    ..interceptors.add(AuthInterceptor())
    ..interceptors.add(
      AwesomeDioInterceptor(
        logRequestTimeout: true,
        logRequestHeaders: true,
        logResponseHeaders: true,
      ),
    );

  static Dio get instance => _dio;
}

class AuthInterceptor extends Interceptor {
  static final GlobalKey<NavigatorState> navigatorKey =
      GlobalKey<NavigatorState>();

  @override
  void onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    // Add token to request headers
    final prefs = await SharedPreferences.getInstance();
    final token = prefs.getString('auth_token');

    if (token != null) {
      options.headers['Authorization'] = 'Bearer $token';
    }

    handler.next(options);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    handler.next(response);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) async {
    // Check if error is 401 (Unauthorized) - token expired
    if (err.response?.statusCode == 401) {
      await _handleTokenExpired();
    }

    handler.next(err);
  }

  Future<void> _handleTokenExpired() async {
    // Clear stored token
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove('auth_token');
    await prefs.remove('refresh_token');
    await prefs.clear(); // Optional: clear all user data

    // Navigate to login page
    final context = navigatorKey.currentContext;
    if (context != null) {
      // Option 1: Navigate and remove all previous routes
      context.pushReplacement(LoginPage());

      // Option 2: If using GoRouter, uncomment below:
      // GoRouter.of(context).go('/login');

      // Option 3: If using custom routing, uncomment below:
      // Navigator.of(context).pushAndRemoveUntil(
      //   MaterialPageRoute(builder: (context) => LoginPage()),
      //   (route) => false,
      // );
    }
  }
}

// Alternative: Dengan Refresh Token Logic
class AuthInterceptorWithRefresh extends Interceptor {
  static final GlobalKey<NavigatorState> navigatorKey =
      GlobalKey<NavigatorState>();

  @override
  void onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    final prefs = await SharedPreferences.getInstance();
    final token = prefs.getString('auth_token');

    if (token != null) {
      options.headers['Authorization'] = 'Bearer $token';
    }

    handler.next(options);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) async {
    if (err.response?.statusCode == 401) {
      // Try refresh token first
      final success = await _tryRefreshToken();

      if (success) {
        // Retry the original request
        final response = await _retryRequest(err.requestOptions);
        handler.resolve(response);
        return;
      } else {
        // Refresh failed, redirect to login
        await _handleTokenExpired();
      }
    }

    handler.next(err);
  }

  Future<bool> _tryRefreshToken() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final authData = await AuthLocalDataSource().getAuthData();

      final url = '${Variables.baseUrl}/api/v1/auth/refresh';

      final response = await Dio().post(
        url,
        options: Options(
          headers: {
            'Authorization': 'Bearer ${authData.refreshToken}',
          },
        ),
      );

      if (response.statusCode == 200) {
        final newToken = response.data['access_token'];
        final newRefreshToken = response.data['refresh_token'];

        await prefs.setString('auth_token', newToken);
        await prefs.setString('refresh_token', newRefreshToken);

        AuthResponseModel authResponseModel =
            AuthResponseModel.fromMap(response.data['data']);

        AuthLocalDataSource().saveAuthData(authResponseModel);

        return true;
      }
    } catch (e) {
      print('Refresh token failed: $e');
    }

    return false;
  }

  Future<Response> _retryRequest(RequestOptions options) async {
    final prefs = await SharedPreferences.getInstance();
    final token = prefs.getString('auth_token');

    options.headers['Authorization'] = 'Bearer $token';

    return await DioClient.instance.request(
      options.path,
      options: Options(
        method: options.method,
        headers: options.headers,
      ),
      data: options.data,
      queryParameters: options.queryParameters,
    );
  }

  Future<void> _handleTokenExpired() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.clear();

    final context = navigatorKey.currentContext;
    if (context != null) {
      Navigator.of(context).pushNamedAndRemoveUntil(
        '/login',
        (route) => false,
      );
    }
  }
}
