import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'package:share_plus/share_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../models/ticket_model.dart';
import '../models/ticket_category_model.dart';
import '../models/ticket_priority_model.dart';
import '../models/ticket_status_model.dart';
import '../constants.dart';

class CustomerSupportProvider with ChangeNotifier {
  List<CustomerSupport> _items = [];
  List<TicketCategoryModel> _categories = [];
  List<TicketStatusModel> _statuses = [];
  List<TicketPriorityModel> _priorities = [];
  bool _isLoading = false;

  List<CustomerSupport> get items => [..._items];
  List<TicketCategoryModel> get categories => [..._categories];
  List<TicketStatusModel> get statuses => [..._statuses];
  List<TicketPriorityModel> get priorities => [..._priorities];
  bool get isLoading => _isLoading;

  Future<void> fetchCustomerSupport() async {
    _isLoading = true;
    notifyListeners();

    final prefs = await SharedPreferences.getInstance();
    final authToken = prefs.getString('access_token') ?? '';

    var url = '$baseUrl/api/support_ticket';

    try {
      final response = await http.get(
        Uri.parse(url),
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
          'Authorization': 'Bearer $authToken',
        },
      );

      final responseData = json.decode(response.body);

      if (responseData['code'] != 200) {
        throw Exception("Failed to load tickets");
      }

      final List extractedData = responseData['data'];

      final List<CustomerSupport> loadedData = [];

      for (var supData in extractedData) {
        loadedData.add(
          CustomerSupport(
            id: supData['id'],
            subject: supData['subject'],
            code: supData['code'].toString(),
            status: supData['status'],
            priority: supData['priority'],
            category: supData['category'],
            createdAt: supData['created_at'],
          ),
        );
      }

      _items = loadedData;
    } catch (error) {
      rethrow;
    }

    _isLoading = false;
    notifyListeners();
  }

  Future<void> fetchTicketCategories() async {
    _isLoading = true;
    notifyListeners();

    var url = '$baseUrl/api/ticket_categories';

    try {
      final response = await http.get(Uri.parse(url));

      final responseData = json.decode(response.body);

      if (responseData['code'] != 200) {
        throw Exception("Failed to load categories");
      }

      final List extractedData = responseData['data'];

      final List<TicketCategoryModel> loadedData = [];

      for (var catData in extractedData) {
        loadedData.add(
          TicketCategoryModel(id: catData['id'], title: catData['title']),
        );
      }

      _categories = loadedData;
    } catch (error) {
      rethrow;
    }

    _isLoading = false;
    notifyListeners();
  }

  Future<void> fetchTicketStatuses() async {
    _isLoading = true;
    notifyListeners();

    try {
      final url = '$baseUrl/api/ticket_status';

      final response = await http.get(
        Uri.parse(url),
        headers: {'Accept': 'application/json'},
      );

      if (response.statusCode != 200) {
        throw Exception("Failed to load ticket status");
      }

      final responseData = json.decode(response.body);

      final List extractedData = responseData['data'];

      _statuses = extractedData
          .map((sta) => TicketStatusModel(id: sta['id'], title: sta['title']))
          .toList();
    } catch (error) {
      debugPrint(error.toString());
      rethrow;
    }

    _isLoading = false;
    notifyListeners();
  }

  Future<void> fetchTicketPriorities() async {
    _isLoading = true;
    notifyListeners();

    try {
      final url = '$baseUrl/api/ticket_priorities';

      final response = await http.get(
        Uri.parse(url),
        headers: {'Accept': 'application/json'},
      );

      if (response.statusCode != 200) {
        throw Exception("Failed to load ticket priorities");
      }

      final responseData = json.decode(response.body);

      final List extractedData = responseData['data'];

      _priorities = extractedData
          .map((pri) => TicketPriorityModel(id: pri['id'], title: pri['title']))
          .toList();
    } catch (error) {
      debugPrint(error.toString());
      rethrow;
    }

    _isLoading = false;
    notifyListeners();
  }

  Future<Map<String, dynamic>> fetchTicketDetails(String code) async {
    final prefs = await SharedPreferences.getInstance();
    final token = prefs.getString('access_token') ?? '';

    final response = await http.get(
      Uri.parse('$baseUrl/api/support_ticket_message/$code'),
      headers: {'Accept': 'application/json', 'Authorization': 'Bearer $token'},
    );

    final data = json.decode(response.body);

    if (data['code'] != 200) {
      throw Exception("Failed to load ticket details");
    }

    return data;
  }

  Future<void> sendMessage({
    required String ticketCode,
    required String message,
    required List<XFile> files,
  }) async {
    _isLoading = true;
    notifyListeners();

    try {
      final prefs = await SharedPreferences.getInstance();
      final token = prefs.getString('access_token') ?? '';

      final uri = Uri.parse('$baseUrl/api/support_ticket_message_store');
      final request = http.MultipartRequest('POST', uri);

      // Add headers
      request.headers['Authorization'] = 'Bearer $token';
      request.headers['Accept'] = 'application/json';

      // Add fields
      request.fields['ticket_thread_code'] = ticketCode;
      request.fields['message'] = message;

      // Add files if any
      for (var file in files) {
        final bytes = await file.readAsBytes();
        final multipartFile = http.MultipartFile.fromBytes(
          'file[]', // note the array syntax to match Laravel
          bytes,
          filename: file.name,
        );
        request.files.add(multipartFile);
      }

      final streamedResponse = await request.send();
      final response = await http.Response.fromStream(streamedResponse);

      final responseData = json.decode(response.body);

      if (responseData['code'] != 200) {
        throw Exception(responseData['message'] ?? 'Failed to send message');
      }

      // Optionally, you can update your local _items or notify UI
    } catch (error) {
      debugPrint('Send message error: $error');
      rethrow;
    }

    _isLoading = false;
    notifyListeners();
  }
}
