import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'services/platform_service.dart';
import 'models/product.dart';

class ApiService with ChangeNotifier implements PlatformService {
  String? _baseUrl; 
  String? _consumerKey;
  String? _consumerSecret;
  bool _isLoading = false;
  String? _error;

  bool get isLoading => _isLoading;
  String? get error => _error;
  bool get isLoggedIn => _baseUrl != null && _consumerKey != null && _consumerSecret != null;

  ApiService();

  void connect(String url, String key, String secret) {
    _baseUrl = url;
    _consumerKey = key;
    _consumerSecret = secret;
    notifyListeners();
  }

  Future<void> verifyCredentials(String url, String key, String secret) async {
    _isLoading = true;
    _error = null;
    notifyListeners();

    try {
      // Normalize URL
      String baseUrl = url.trim();
      if (!baseUrl.startsWith('http')) baseUrl = 'https://$baseUrl';
      if (baseUrl.endsWith('/')) baseUrl = baseUrl.substring(0, baseUrl.length - 1);

      // Construct WC API URL
      final apiUri = Uri.parse('$baseUrl/wp-json/wc/v3/system_status');

      final response = await http.get(
        apiUri,
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Basic ${base64Encode(utf8.encode('$key:$secret'))}',
        },
      );

      if (response.statusCode != 200) {
        String msg = 'Connection failed: ${response.statusCode}';
        try {
            final body = jsonDecode(response.body);
            msg = body['message'] ?? msg;
        } catch (_) {}
        throw Exception(msg);
      }
    } catch (e) {
      _error = e.toString().contains('FormatException') 
          ? 'Invalid Response. Is this a WooCommerce site?' 
          : e.toString().replaceAll('Exception: ', '');
      rethrow;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  void disconnect() {
    _baseUrl = null;
    _consumerKey = null;
    _consumerSecret = null;
    notifyListeners();
  }
  
  Future<void> logout() async {
    disconnect();
  }

  // --- Products ---

  Map<String, String> get _headers => {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ${base64Encode(utf8.encode('$_consumerKey:$_consumerSecret'))}',
  };

  // Helper to build WC API URIs
  Uri _getUri(String path, [Map<String, String>? queryParams]) {
      // Ensuring path starts with /wp-json/wc/v3
      // We assume _baseUrl is just the domain e.g. https://site.com
      // We append the internal implementation path
      return Uri.parse('$_baseUrl/wp-json/wc/v3$path').replace(queryParameters: queryParams);
  }

  // PlatformService Implementation
  @override
  Future<List<Product>> fetchProducts({int page = 1, String search = ''}) async {
    if (!isLoggedIn) throw Exception('Not logged in');

    final uri = _getUri('/products', {
      'page': page.toString(),
      'per_page': '20',
      'search': search,
    });

    final response = await http.get(uri, headers: _headers);
    if (response.statusCode == 200) {
      final List<dynamic> body = jsonDecode(response.body);
      return body.map((json) => Product.fromJson(json)).toList();
    } else {
      throw Exception('Failed to load products');
    }
  }

  // Legacy/Alias
  Future<List<Product>> getProducts({int page = 1, String search = ''}) => fetchProducts(page: page, search: search);

  @override
  Future<Product> fetchProduct(int id) async {
       if (!isLoggedIn) throw Exception('Not logged in');
       final uri = _getUri('/products/$id');
       final response = await http.get(uri, headers: _headers);
       if (response.statusCode == 200) {
           return Product.fromJson(jsonDecode(response.body));
       } else {
           throw Exception('Failed to load product');
       }
  }
  




  Future<Product> getProduct(dynamic id) async {
    if (!isLoggedIn) throw Exception('Not logged in');
    
    final uri = _getUri('/products/$id');
    final response = await http.get(uri, headers: _headers);

    if (response.statusCode == 200) {
      return Product.fromJson(jsonDecode(response.body));
    } else {
      throw Exception('Failed to load product');
    }
  }

  Future<void> createProduct(Map<String, dynamic> productData) async {
    if (!isLoggedIn) throw Exception('Not logged in');
    
    final uri = _getUri('/products');
    final response = await http.post(
      uri,
      headers: _headers,
      body: jsonEncode(productData),
    );

    if (response.statusCode != 200 && response.statusCode != 201) {
      throw Exception('Failed to create product: ${response.body}');
    }
  }

  @override
  Future<Product> updateProduct(int id, Map<String, dynamic> productData) async {
    if (!isLoggedIn) throw Exception('Not logged in');

    final uri = _getUri('/products/$id');
    final response = await http.put(
      uri,
      headers: _headers,
      body: jsonEncode(productData),
    );

    if (response.statusCode == 200) {
      return Product.fromJson(jsonDecode(response.body));
    } else {
      throw Exception('Failed to update product: ${response.body}');
    }
  }

  @override
  Future<dynamic> deleteProduct(int id) async {
    if (!isLoggedIn) throw Exception('Not logged in');

    final uri = _getUri('/products/$id', {'force': 'true'});
    final response = await http.delete(uri, headers: _headers);

    if (response.statusCode == 200) {
      return jsonDecode(response.body);
    } else {
      throw Exception('Failed to delete product');
    }
  }
  Future<Map<String, dynamic>> uploadImage(List<int> bytes, String filename) async {
    if (!isLoggedIn) throw Exception('Not logged in');

    // POST /wp-json/wp/v2/media
    final uri = Uri.parse('$_baseUrl/wp-json/wp/v2/media');
    
    final request = http.MultipartRequest('POST', uri);
    // Add Auth Header manually because MultipartRequest doesn't use the map
    request.headers['Authorization'] = 'Basic ${base64Encode(utf8.encode('$_consumerKey:$_consumerSecret'))}';
    request.headers['Content-Disposition'] = 'attachment; filename=$filename';
    
    request.files.add(http.MultipartFile.fromBytes(
      'file', 
      bytes, 
      filename: filename
    ));

    final response = await request.send();
    final respStr = await response.stream.bytesToString();
    
    if (response.statusCode == 201) {
       return jsonDecode(respStr);
    } else {
       throw Exception('Failed to upload image: $respStr');
    }
  }

  // --- Variations ---
  Future<List<Variation>> fetchVariations(int productId) async {
    if (!isLoggedIn) throw Exception('Not logged in');

    final uri = _getUri('/products/$productId/variations');
    final response = await http.get(uri, headers: _headers);

    if (response.statusCode == 200) {
      final List<dynamic> body = jsonDecode(response.body);
      return body.map((json) => Variation.fromJson(json)).toList();
    } else {
      throw Exception('Failed to load variations');
    }
  }

  Future<Variation> createVariation(int productId, Map<String, dynamic> data) async {
    if (!isLoggedIn) throw Exception('Not logged in');

    final uri = _getUri('/products/$productId/variations');
    final response = await http.post(uri, headers: _headers, body: jsonEncode(data));

    if (response.statusCode == 200 || response.statusCode == 201) {
      return Variation.fromJson(jsonDecode(response.body));
    } else {
      throw Exception('Failed to create variation: ${response.body}');
    }
  }

  Future<Variation> updateVariation(int productId, int variationId, Map<String, dynamic> data) async {
    if (!isLoggedIn) throw Exception('Not logged in');

    final uri = _getUri('/products/$productId/variations/$variationId');
    final response = await http.put(uri, headers: _headers, body: jsonEncode(data));

    if (response.statusCode == 200) {
      return Variation.fromJson(jsonDecode(response.body));
    } else {
      throw Exception('Failed to update variation: ${response.body}');
    }
  }

  Future<void> deleteVariation(int productId, int variationId) async {
    if (!isLoggedIn) throw Exception('Not logged in');

    final uri = _getUri('/products/$productId/variations/$variationId', {'force': 'true'});
    final response = await http.delete(uri, headers: _headers);

    if (response.statusCode != 200) {
      throw Exception('Failed to delete variation');
    }
  }
}

