// lib/remote/remote_client.dart
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;

import 'remote_models.dart';
import 'auth_client.dart';

class RemoteJsonClient {
  final Uri indexUri;
  final RemoteAuth? auth;

  RemoteJsonClient(
    String baseUrl,
    String indexPath, {
    this.auth,
  }) : indexUri = Uri.parse(
          baseUrl.endsWith('/') ? baseUrl : '$baseUrl/',
        ).resolve(indexPath);

  // 🔥 PING SUPER LEGGERO → usa /ping
  Future<void> ping() async {
    final client = HttpClient();
    client.connectionTimeout = const Duration(seconds: 2);

    // Costruisce l’URL /ping a partire dalla baseUrl
    final pingUri = Uri.parse('${indexUri.origin}/ping');

    try {
      final req = await client.getUrl(pingUri);
      req.followRedirects = false;

      final res = await req.close().timeout(const Duration(seconds: 2));

      print('[remote-client] PING url=$pingUri status=${res.statusCode}');

      // 5xx → errore server
      if (res.statusCode >= 500) {
        throw HttpException('HTTP ${res.statusCode}', uri: pingUri);
      }

      // 200, 401, 403, 404 → server raggiungibile
    } on TimeoutException {
      throw TimeoutException('Ping timeout');
    } on SocketException catch (e) {
      throw SocketException('Network error: ${e.message}');
    } on HttpException {
      rethrow;
    } catch (e) {
      rethrow;
    } finally {
      client.close();
    }
  }

  // FETCH ALL (come prima)
  Future<List<RemotePhotoItem>> fetchAll() async {
    Map<String, String> headers = {};
    if (auth != null) {
      headers = await auth!.authHeaders();
    }

    print('[remote-client] GET $indexUri');

    http.Response res;
    try {
      res = await http
          .get(indexUri, headers: headers)
          .timeout(const Duration(seconds: 20));
    } catch (e) {
      throw Exception('Errore rete su $indexUri: $e');
    }

    if (res.statusCode == 401 && auth != null) {
      headers = await auth!.refreshAndHeaders();
      res = await http
          .get(indexUri, headers: headers)
          .timeout(const Duration(seconds: 20));
    }

    if ({301, 302, 307, 308}.contains(res.statusCode) &&
        res.headers['location'] != null) {
      final loc = res.headers['location']!;
      final redirectUri = indexUri.resolve(loc);
      res = await http
          .get(redirectUri, headers: headers)
          .timeout(const Duration(seconds: 20));
    }

    if (res.statusCode != 200) {
      final snippet = utf8.decode(res.bodyBytes.take(200).toList());
      throw HttpException(
        'HTTP ${res.statusCode} ${res.reasonPhrase}. Body: $snippet',
        uri: indexUri,
      );
    }

    final body = utf8.decode(res.bodyBytes);
    final dynamic decoded = json.decode(body);

    if (decoded is! List) {
      throw Exception(
        'JSON inatteso: atteso array top-level, ricevuto ${decoded.runtimeType}',
      );
    }

    final rawList = decoded;

    return rawList.map<RemotePhotoItem>((e) {
      if (e is! Map<String, dynamic>) {
        throw Exception('Elemento JSON non è una mappa: ${e.runtimeType} -> $e');
      }
      return RemotePhotoItem.fromJson(e);
    }).toList();
  }
}
