import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
import 'package:mime/mime.dart';
import '../config/api_config.dart';

class VanguardApi {
  static Map<String, String> authHeaders(String token) => {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Authorization': 'Bearer $token',
  };

  static Future<String> login({
    required String username,
    required String password,
  }) async {
    final url = Uri.parse('${ApiConfig.laravelApiBase}/login');

    final res = await http.post(
      url,
      headers: const {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: jsonEncode({
        'username': username,
        'password': password,
        'device_name': ApiConfig.deviceName,
      }),
    );

    if (res.statusCode != 200) {
      throw Exception('Login failed (${res.statusCode}): ${res.body}');
    }

    final data = jsonDecode(res.body) as Map<String, dynamic>;
    final token = data['token'];
    if (token == null || token.toString().isEmpty) {
      throw Exception('Missing token in login response.');
    }
    return token.toString();
  }

  static Future<void> requestPasswordResetEmail({required String email}) async {
    final url = Uri.parse('${ApiConfig.laravelApiBase}/password/remind');

    final res = await http.post(
      url,
      headers: const {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: jsonEncode({'email': email}),
    );

    if (res.statusCode != 200) {
      throw Exception(
        'Password remind failed (${res.statusCode}): ${res.body}',
      );
    }
  }

  // ---------- Your custom APIs ----------

  static Future<Map<String, dynamic>> getUserSchools({
    required String token,
  }) async {
    final url = Uri.parse('${ApiConfig.phpApiBase}/api_user_schools.php');

    final res = await http.get(
      url,
      headers: {'Accept': 'application/json', 'Authorization': 'Bearer $token'},
    );

    if (res.statusCode != 200) {
      throw Exception('User schools failed (${res.statusCode}): ${res.body}');
    }

    final data = jsonDecode(res.body) as Map<String, dynamic>;
    if (data['success'] != true) {
      throw Exception(data['message'] ?? 'Unknown error (user schools).');
    }
    return data;
  }

  static Future<Map<String, dynamic>> getMyLessons({
    required String token,
    required int schoolId,
    required String month, // YYYY-MM
  }) async {
    final url = Uri.parse(
      '${ApiConfig.phpApiBase}/api_my_lessons.php',
    ).replace(queryParameters: {'school_id': '$schoolId', 'month': month});

    final res = await http.get(
      url,
      headers: {'Accept': 'application/json', 'Authorization': 'Bearer $token'},
    );

    if (res.statusCode != 200) {
      throw Exception('My lessons failed (${res.statusCode}): ${res.body}');
    }

    final data = jsonDecode(res.body) as Map<String, dynamic>;
    if (data['success'] != true) {
      throw Exception(data['message'] ?? 'Unknown error (my lessons).');
    }
    return data;
  }

  static Future<void> logout({required String token}) async {
    // Vanguard / Laravel: quasi sempre POST /logout con Bearer token (Sanctum)
    final url = Uri.parse('${ApiConfig.laravelApiBase}/logout');

    final res = await http.post(url, headers: authHeaders(token));

    // 200 o 204 ok. Alcuni backend rispondono 401 se token già scaduto:
    // in app lo consideriamo comunque "logout riuscito".
    if (res.statusCode == 200 ||
        res.statusCode == 204 ||
        res.statusCode == 401) {
      return;
    }

    throw Exception('Logout failed (${res.statusCode}): ${res.body}');
  }

  // ---------- Profilo (Vanguard native) ----------

  /// GET /me — dati profilo. Ritorna il contenuto di "data".
  static Future<Map<String, dynamic>> getMe({required String token}) async {
    final url = Uri.parse('${ApiConfig.laravelApiBase}/me');

    final res = await http.get(url, headers: authHeaders(token));

    if (res.statusCode != 200) {
      throw Exception('Get profile failed (${res.statusCode}): ${res.body}');
    }

    final body = jsonDecode(res.body) as Map<String, dynamic>;
    final data = body['data'];
    if (data is! Map<String, dynamic>) {
      throw Exception('Formato risposta /me non valido.');
    }
    return data;
  }

  /// PATCH /me/details — aggiorna nome e cognome.
  static Future<Map<String, dynamic>> updateDetails({
    required String token,
    String? firstName,
    String? lastName,
  }) async {
    final url = Uri.parse('${ApiConfig.laravelApiBase}/me/details');

    final payload = <String, dynamic>{};
    if (firstName != null) payload['first_name'] = firstName;
    if (lastName != null) payload['last_name'] = lastName;

    final res = await http.patch(
      url,
      headers: authHeaders(token),
      body: jsonEncode(payload),
    );

    if (res.statusCode != 200) {
      throw Exception('Update details failed (${res.statusCode}): ${res.body}');
    }

    final body = jsonDecode(res.body) as Map<String, dynamic>;
    return (body['data'] as Map<String, dynamic>?) ?? {};
  }

  /// PATCH /me/details/auth — aggiorna la password (nuova + conferma).
  static Future<void> updatePassword({
    required String token,
    required String password,
    required String passwordConfirmation,
  }) async {
    final url = Uri.parse('${ApiConfig.laravelApiBase}/me/details/auth');

    final res = await http.patch(
      url,
      headers: authHeaders(token),
      body: jsonEncode({
        'password': password,
        'password_confirmation': passwordConfirmation,
      }),
    );

    if (res.statusCode != 200) {
      throw Exception(
        'Update password failed (${res.statusCode}): ${res.body}',
      );
    }
  }

  /// POST /me/avatar — upload avatar (multipart). Ritorna l'URL avatar aggiornato.
  static Future<String?> uploadAvatar({
    required String token,
    required String filePath,
  }) async {
    final url = Uri.parse('${ApiConfig.laravelApiBase}/me/avatar');

    final mimeType = lookupMimeType(filePath) ?? 'image/jpeg';
    final parts = mimeType.split('/');

    final request = http.MultipartRequest('POST', url)
      ..headers['Accept'] = 'application/json'
      ..headers['Authorization'] = 'Bearer $token'
      ..files.add(
        await http.MultipartFile.fromPath(
          'file',
          filePath,
          contentType: MediaType(parts[0], parts[1]),
        ),
      );

    final streamed = await request.send();
    final res = await http.Response.fromStream(streamed);

    if (res.statusCode != 200) {
      throw Exception('Upload avatar failed (${res.statusCode}): ${res.body}');
    }

    final body = jsonDecode(res.body) as Map<String, dynamic>;
    final data = body['data'] as Map<String, dynamic>?;
    return data?['avatar']?.toString();
  }
}
