import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:superport/core/constants/api_endpoints.dart';
import 'package:superport/data/datasources/remote/api_client.dart';
import 'package:superport/data/models/model_dto.dart';

abstract class ModelRepository {
  Future<List<ModelDto>> getModels({int? vendorId});
  Future<ModelDto> getModelById(int id);
  Future<ModelDto> createModel(ModelRequestDto request);
  Future<ModelDto> updateModel(int id, ModelUpdateRequestDto request);
  Future<void> deleteModel(int id);
  Future<List<ModelDto>> searchModels(String query);
}

@Injectable(as: ModelRepository)
class ModelRepositoryImpl implements ModelRepository {
  final ApiClient _apiClient;

  ModelRepositoryImpl(this._apiClient);

  @override
  Future<List<ModelDto>> getModels({int? vendorId}) async {
    try {
      final queryParams = <String, dynamic>{};
      if (vendorId != null) {
        queryParams['vendor_id'] = vendorId;
      }

      final response = await _apiClient.dio.get(
        ApiEndpoints.models,
        queryParameters: queryParams,
      );

      if (response.statusCode == 200) {
        final data = response.data;
        
        // Handle both array and object responses
        if (data is List) {
          return data.map((json) => ModelDto.fromJson(json)).toList();
        } else if (data is Map && data['data'] != null) {
          return (data['data'] as List)
              .map((json) => ModelDto.fromJson(json))
              .toList();
        }
        
        return [];
      } else {
        throw DioException(
          requestOptions: response.requestOptions,
          response: response,
          message: 'Failed to load models',
        );
      }
    } catch (e) {
      rethrow;
    }
  }

  @override
  Future<ModelDto> getModelById(int id) async {
    try {
      final response = await _apiClient.dio.get('${ApiEndpoints.models}/$id');

      if (response.statusCode == 200) {
        return ModelDto.fromJson(response.data);
      } else {
        throw DioException(
          requestOptions: response.requestOptions,
          response: response,
          message: 'Failed to load model',
        );
      }
    } catch (e) {
      rethrow;
    }
  }

  @override
  Future<ModelDto> createModel(ModelRequestDto request) async {
    try {
      final response = await _apiClient.dio.post(
        ApiEndpoints.models,
        data: request.toJson(),
      );

      if (response.statusCode == 201 || response.statusCode == 200) {
        return ModelDto.fromJson(response.data);
      } else {
        throw DioException(
          requestOptions: response.requestOptions,
          response: response,
          message: 'Failed to create model',
        );
      }
    } catch (e) {
      rethrow;
    }
  }

  @override
  Future<ModelDto> updateModel(int id, ModelUpdateRequestDto request) async {
    try {
      final response = await _apiClient.dio.put(
        '${ApiEndpoints.models}/$id',
        data: request.toJson(),
      );

      if (response.statusCode == 200) {
        return ModelDto.fromJson(response.data);
      } else {
        throw DioException(
          requestOptions: response.requestOptions,
          response: response,
          message: 'Failed to update model',
        );
      }
    } catch (e) {
      rethrow;
    }
  }

  @override
  Future<void> deleteModel(int id) async {
    try {
      final response = await _apiClient.dio.delete('${ApiEndpoints.models}/$id');

      if (response.statusCode != 200 && response.statusCode != 204) {
        throw DioException(
          requestOptions: response.requestOptions,
          response: response,
          message: 'Failed to delete model',
        );
      }
    } catch (e) {
      rethrow;
    }
  }

  @override
  Future<List<ModelDto>> searchModels(String query) async {
    try {
      final response = await _apiClient.dio.get(
        ApiEndpoints.models,
        queryParameters: {'search': query},
      );

      if (response.statusCode == 200) {
        final data = response.data;
        
        if (data is List) {
          return data.map((json) => ModelDto.fromJson(json)).toList();
        } else if (data is Map && data['data'] != null) {
          return (data['data'] as List)
              .map((json) => ModelDto.fromJson(json))
              .toList();
        }
        
        return [];
      } else {
        throw DioException(
          requestOptions: response.requestOptions,
          response: response,
          message: 'Failed to search models',
        );
      }
    } catch (e) {
      rethrow;
    }
  }
}