import 'dart:convert';
import 'package:http/http.dart' as http;

import '../config/api_config.dart';
import '../models/lesson.dart';

/// Service per le lezioni della scuola YogaSoul.
/// Chiama `public/api/my_lessons.php` (phpApiBase), stesso pattern di SettingsApi.
class LessonsApi {
  static Map<String, String> _headers(String token) => {
    'Accept': 'application/json',
    'Authorization': 'Bearer $token',
  };

  /// Carica le lezioni del mese indicato.
  /// [month] deve essere nel formato "YYYY-MM". Se null, il server usa il mese corrente.
  static Future<LessonsResponse> fetchMyLessons({
    required String token,
    String? month,
  }) async {
    final query = (month != null && month.isNotEmpty) ? '?month=$month' : '';
    final uri = Uri.parse('${ApiConfig.laravelApiBase}/my_lessons.php$query');

    final res = await http.get(uri, headers: _headers(token));

    Map<String, dynamic> data;
    try {
      data = jsonDecode(res.body) as Map<String, dynamic>;
    } catch (_) {
      throw Exception('RAW(${res.statusCode}): ${res.body}');
    }

    if (res.statusCode != 200 || data['success'] != true) {
      throw Exception(data['error'] ?? data['message'] ?? 'Errore lezioni');
    }

    return LessonsResponse.fromJson(data);
  }

  /// Cancella una prenotazione dell'utente.
  static Future<bool> cancelLesson({
    required String token,
    required int bookingId,
  }) async {
    final uri = Uri.parse('${ApiConfig.laravelApiBase}/cancel_lesson.php');

    final res = await http.post(
      uri,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
      body: jsonEncode({'booking_id': bookingId}),
    );

    Map<String, dynamic> data;
    try {
      data = jsonDecode(res.body) as Map<String, dynamic>;
    } catch (_) {
      throw Exception('Risposta non valida dal server (${res.statusCode})');
    }

    if (res.statusCode == 200 && data['success'] == true) {
      return true;
    }

    throw Exception(data['error'] ?? data['message'] ?? 'Errore cancellazione');
  }

  /// Elenca gli slot disponibili per riprogrammare/prenotare.
  static Future<List<AvailableSlot>> fetchAvailableSlots({
    required String token,
    required int serviceId,
    String? month,
  }) async {
    final monthQuery = (month != null && month.isNotEmpty)
        ? '&month=$month'
        : '';
    final uri = Uri.parse(
      '${ApiConfig.laravelApiBase}/available_slots.php?service_id=$serviceId$monthQuery',
    );

    final res = await http.get(uri, headers: _headers(token));

    Map<String, dynamic> data;
    try {
      data = jsonDecode(res.body) as Map<String, dynamic>;
    } catch (_) {
      throw Exception('Risposta non valida dal server (${res.statusCode})');
    }

    if (res.statusCode != 200 || data['success'] != true) {
      throw Exception(data['error'] ?? data['message'] ?? 'Errore slot');
    }

    final raw = (data['slots'] as List?) ?? const [];
    return raw
        .map((e) => AvailableSlot.fromJson((e as Map).cast<String, dynamic>()))
        .toList();
  }

  /// Esegue la riprogrammazione di una lezione su un nuovo slot.
  static Future<String> reschedule({
    required String token,
    required int bookingId,
    required int newScheduleId,
  }) async {
    final uri = Uri.parse('${ApiConfig.laravelApiBase}/reschedule.php');
    final res = await http.post(
      uri,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
      body: jsonEncode({
        'booking_id': bookingId,
        'new_schedule_id': newScheduleId,
      }),
    );

    Map<String, dynamic> data;
    try {
      data = jsonDecode(res.body) as Map<String, dynamic>;
    } catch (_) {
      throw Exception('Risposta non valida dal server (${res.statusCode})');
    }

    if (res.statusCode == 200 && data['success'] == true) {
      return (data['message'] ?? 'Riprogrammazione richiesta').toString();
    }
    throw Exception(
      data['error'] ?? data['message'] ?? 'Errore riprogrammazione',
    );
  }

  /// Elenca gli ordini/pacchetti dell'utente con residui.
  static Future<List<OrderPackage>> fetchOrders({required String token}) async {
    final uri = Uri.parse('${ApiConfig.laravelApiBase}/orders.php');
    final res = await http.get(uri, headers: _headers(token));

    Map<String, dynamic> data;
    try {
      data = jsonDecode(res.body) as Map<String, dynamic>;
    } catch (_) {
      throw Exception('Risposta non valida dal server (${res.statusCode})');
    }
    if (res.statusCode != 200 || data['success'] != true) {
      throw Exception(data['error'] ?? data['message'] ?? 'Errore ordini');
    }
    final raw = (data['orders'] as List?) ?? const [];
    return raw
        .map((e) => OrderPackage.fromJson((e as Map).cast<String, dynamic>()))
        .toList();
  }

  /// Prenota una nuova lezione da un ticket residuo.
  static Future<String> bookFromTicket({
    required String token,
    required int orderId,
    required int newScheduleId,
  }) async {
    final uri = Uri.parse('${ApiConfig.laravelApiBase}/book_from_ticket.php');
    final res = await http.post(
      uri,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token',
      },
      body: jsonEncode({'order_id': orderId, 'new_schedule_id': newScheduleId}),
    );

    Map<String, dynamic> data;
    try {
      data = jsonDecode(res.body) as Map<String, dynamic>;
    } catch (_) {
      throw Exception('Risposta non valida dal server (${res.statusCode})');
    }
    if (res.statusCode == 200 && data['success'] == true) {
      return (data['message'] ?? 'Prenotazione richiesta').toString();
    }
    throw Exception(data['error'] ?? data['message'] ?? 'Errore prenotazione');
  }

  /// Elenca gli ordini dettagliati (con conteggi e lezioni).
  static Future<List<OrderDetail>> fetchOrdersDetail({
    required String token,
  }) async {
    final uri = Uri.parse('${ApiConfig.laravelApiBase}/orders_detail.php');
    final res = await http.get(uri, headers: _headers(token));

    Map<String, dynamic> data;
    try {
      data = jsonDecode(res.body) as Map<String, dynamic>;
    } catch (_) {
      throw Exception('Risposta non valida dal server (${res.statusCode})');
    }
    if (res.statusCode != 200 || data['success'] != true) {
      throw Exception(data['error'] ?? data['message'] ?? 'Errore ordini');
    }
    final raw = (data['orders'] as List?) ?? const [];
    return raw
        .map((e) => OrderDetail.fromJson((e as Map).cast<String, dynamic>()))
        .toList();
  }
}
