import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:image_picker/image_picker.dart';

class PenugasanApi {
static const String baseUrl = 'https://ta.myhost.id/E31230906/api';

  static final PenugasanApi _instance = PenugasanApi._internal();
  factory PenugasanApi() => _instance;
  PenugasanApi._internal();

  // ─────────────────────────────────────────
  // PRIVATE HELPERS
  // ─────────────────────────────────────────
 
  Future<String?> _getToken() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getString('access_token'); // ← ganti ini
}

  Future<int?> _getIdTeknisi() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getInt('id_teknisi');
  }

  Future<Map<String, String>> _getHeaders() async {
    final token = await _getToken();
    return {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      if (token != null) 'Authorization': 'Bearer $token',
    };
  }

  Map<String, dynamic> _handleResponse(http.Response response) {
    // Log response di mode debug
    if (const bool.fromEnvironment('dart.vm.product') == false) {
      print('[PenugasanApi] ${response.request?.method} ${response.request?.url}');
      print('[PenugasanApi] Status: ${response.statusCode}');
      if (response.statusCode >= 400) {
        print('[PenugasanApi] Error Body: ${response.body}');
      }
    }

    final data = json.decode(response.body);
    if (response.statusCode >= 200 && response.statusCode < 300) {
      return data;
    }
    throw PenugasanApiException(
      message: data['message'] ?? 'Terjadi kesalahan',
      statusCode: response.statusCode,
      errors: data['errors'],
    );
  }

  // ─────────────────────────────────────────
  // GET - Daftar Penugasan
  // ─────────────────────────────────────────
  /// [status] filter: 'belum_mulai' | 'dalam_proses' | 'selesai' | 'dibatalkan'
  ///
  /// Untuk tab "Progres Aktif"   → kirim status: 'dalam_proses'
  /// Untuk tab "Riwayat Selesai" → kirim status: 'selesai'
  /// Tanpa status                → ambil semua
  Future<Map<String, dynamic>> getPenugasanList({
    String? status,
    String? jenisPekerjaan,
    String? tanggalMulai,
    String? tanggalAkhir,
    int page = 1,
  }) async {
    final idTeknisi = await _getIdTeknisi();

    final queryParams = <String, String>{
      'page': page.toString(),
      if (idTeknisi != null) 'id_teknisi': idTeknisi.toString(),
    };

    if (status != null)         queryParams['status']          = status;
    if (jenisPekerjaan != null) queryParams['jenis_pekerjaan'] = jenisPekerjaan;
    if (tanggalMulai != null)   queryParams['tanggal_mulai']   = tanggalMulai;
    if (tanggalAkhir != null)   queryParams['tanggal_akhir']   = tanggalAkhir;

    final uri = Uri.parse('$baseUrl/penugasan')
        .replace(queryParameters: queryParams);

    final response = await http.get(uri, headers: await _getHeaders());
    return _handleResponse(response);
  }

  // ─────────────────────────────────────────
  // GET - Helper: Progres Aktif
  // ─────────────────────────────────────────
  /// Shortcut untuk mengambil penugasan dengan status 'dalam_proses'
  Future<Map<String, dynamic>> getPenugasanProgresAktif({int page = 1}) async {
    return getPenugasanList(status: 'dalam_proses', page: page);
  }

  // ─────────────────────────────────────────
  // GET - Helper: Riwayat Selesai
  // ─────────────────────────────────────────
  /// Shortcut untuk mengambil penugasan dengan status 'selesai'
  Future<Map<String, dynamic>> getPenugasanRiwayatSelesai({int page = 1}) async {
    return getPenugasanList(status: 'selesai', page: page);
  }

  // ─────────────────────────────────────────
  // GET - Detail Penugasan
  // ─────────────────────────────────────────
  Future<Map<String, dynamic>> getPenugasanDetail(int id) async {
    final response = await http.get(
      Uri.parse('$baseUrl/penugasan/$id'),
      headers: await _getHeaders(),
    );
    return _handleResponse(response);
  }

  // ─────────────────────────────────────────
  // GET - Statistik
  // ─────────────────────────────────────────
  Future<Map<String, dynamic>> getStatistik() async {
    final idTeknisi = await _getIdTeknisi();

    final uri = Uri.parse('$baseUrl/penugasan/statistik').replace(
      queryParameters: {
        if (idTeknisi != null) 'id_teknisi': idTeknisi.toString(),
      },
    );

    final response = await http.get(uri, headers: await _getHeaders());
    return _handleResponse(response);
  }

  // ─────────────────────────────────────────
  // POST - Lengkapi Detail (pertama kali)
  // ─────────────────────────────────────────
  Future<Map<String, dynamic>> lengkapiDetail({
    required int idPenugasan,
    required List<Map<String, dynamic>> items,
    required String tanggalMulai,
    String? detailPekerjaan,
    List<int>? timTeknisi,
    XFile? fotoSebelum,
    XFile? fotoSesudah,
  }) async {
    final token = await _getToken();
    var request = http.MultipartRequest(
      'POST',
      Uri.parse('$baseUrl/penugasan/$idPenugasan/lengkapi-detail'),
    );

    request.headers.addAll({
      'Accept': 'application/json',
      if (token != null) 'Authorization': 'Bearer $token',
    });

    request.fields['tanggal_mulai'] = tanggalMulai;

    // Selalu kirim detail_pekerjaan (meski kosong)
    // agar Laravel menyimpan nilai terbaru via $request->has()
    request.fields['detail_pekerjaan'] = detailPekerjaan ?? '';

    for (int i = 0; i < items.length; i++) {
      final item = items[i];
      request.fields['items[$i][jenis_pekerjaan]'] =
          item['jenis_pekerjaan']?.toString() ?? '';

      if (item['dimensi_pipa'] != null)
        request.fields['items[$i][dimensi_pipa]'] =
            item['dimensi_pipa'].toString();

      if (item['jarak_meter'] != null)
        request.fields['items[$i][jarak_meter]'] =
            item['jarak_meter'].toString();

      if (item['jumlah_unit'] != null)
        request.fields['items[$i][jumlah_unit]'] =
            item['jumlah_unit'].toString();

      if (item['jumlah_titik'] != null)
        request.fields['items[$i][jumlah_titik]'] =
            item['jumlah_titik'].toString();

      if (item['pakai_pipa_besi'] != null)
        request.fields['items[$i][pakai_pipa_besi]'] =
            item['pakai_pipa_besi'] ? '1' : '0';

      if (item['jenis_pengangkatan'] != null)
        request.fields['items[$i][jenis_pengangkatan]'] =
            item['jenis_pengangkatan'].toString();
    }

    if (timTeknisi != null) {
      for (int i = 0; i < timTeknisi.length; i++) {
        request.fields['tim_teknisi[$i]'] = timTeknisi[i].toString();
      }
    }

    // ✅ Upload foto sebelum (jika ada)
    if (fotoSebelum != null) {
      final bytes = await fotoSebelum.readAsBytes();
      request.fields['foto_sebelum_base64'] =
          'data:image/jpeg;base64,' + base64Encode(bytes);
    }

    // ✅ Upload foto sesudah (jika ada)
    if (fotoSesudah != null) {
      final bytes = await fotoSesudah.readAsBytes();
      request.fields['foto_sesudah_base64'] =
          'data:image/jpeg;base64,' + base64Encode(bytes);
    }

    final streamed  = await request.send();
    final response  = await http.Response.fromStream(streamed);
    return _handleResponse(response);
  }

  // ─────────────────────────────────────────
  // PUT - Update Detail (edit yang sudah ada)
  // ─────────────────────────────────────────
  Future<Map<String, dynamic>> updateDetail({
    required int idPenugasan,
    required int idTeknisi,
    required List<Map<String, dynamic>> items,
    // Selalu kirim detail_pekerjaan (default string kosong, bukan null)
    String detailPekerjaan = '',
    String? tanggalMulai,
    List<int>? timTeknisi,
  }) async {
    // Bersihkan nilai null di dalam setiap item sebelum encode JSON
    final cleanedItems = items.map((item) {
      final cleaned = <String, dynamic>{};
      item.forEach((key, value) {
        // id_penugasan_item & jenis_pekerjaan selalu dikirim meski null
        if (key == 'id_penugasan_item' || key == 'jenis_pekerjaan') {
          cleaned[key] = value;
        } else if (value != null) {
          cleaned[key] = value;
        }
      });
      return cleaned;
    }).toList();

    final body = <String, dynamic>{
      'id_teknisi':       idTeknisi,
      'items':            cleanedItems,
      // Selalu kirim detail_pekerjaan agar backend menyimpan nilai terbaru
      'detail_pekerjaan': detailPekerjaan,
      if (tanggalMulai != null) 'tanggal_mulai': tanggalMulai,
      if (timTeknisi != null)   'tim_teknisi':   timTeknisi,
    };

    final response = await http.put(
      Uri.parse('$baseUrl/penugasan/$idPenugasan/update-detail'),
      headers: await _getHeaders(),
      body: json.encode(body),
    );
    return _handleResponse(response);
  }

  // ─────────────────────────────────────────
  // POST - Tambah Item Progres
  // ─────────────────────────────────────────
  Future<Map<String, dynamic>> addItem({
    required int idPenugasan,
    required Map<String, dynamic> item,
  }) async {
    final response = await http.post(
      Uri.parse('$baseUrl/penugasan/$idPenugasan/add-item'),
      headers: await _getHeaders(),
      body: json.encode(item),
    );
    return _handleResponse(response);
  }

  // ─────────────────────────────────────────
  // PUT - Update Status
  // ─────────────────────────────────────────
  Future<Map<String, dynamic>> updateStatus({
    required int idPenugasan,
    required String statusPekerjaan,
    String? tanggalDiselesaikan,
  }) async {
    final response = await http.put(
      Uri.parse('$baseUrl/penugasan/$idPenugasan/update-status'),
      headers: await _getHeaders(),
      body: json.encode({
        'status_pekerjaan': statusPekerjaan,
        if (tanggalDiselesaikan != null)
          'tanggal_diselesaikan': tanggalDiselesaikan,
      }),
    );
    return _handleResponse(response);
  }

  // ─────────────────────────────────────────
  // POST - Upload Foto Sebelum / Sesudah
  // ─────────────────────────────────────────
  /// [tipeFoto] : 'sebelum' atau 'sesudah'
  ///
  /// Field yang dikirim ke backend:
  ///   - tipe_foto        : 'sebelum' | 'sesudah'   ← wajib (required di Laravel)
  ///   - sebelum_base64   : base64 string            ← jika tipeFoto == 'sebelum'
  ///   - sesudah_base64   : base64 string            ← jika tipeFoto == 'sesudah'
  Future<Map<String, dynamic>> uploadFoto({
    required int idPenugasan,
    required String tipeFoto,  // 'sebelum' atau 'sesudah'
    required XFile foto,
  }) async {
    assert(
      tipeFoto == 'sebelum' || tipeFoto == 'sesudah',
      'tipeFoto harus "sebelum" atau "sesudah"',
    );

    final token = await _getToken();
    var request = http.MultipartRequest(
      'POST',
      Uri.parse('$baseUrl/penugasan/$idPenugasan/upload-foto'),
    );

    request.headers.addAll({
      'Accept': 'application/json',
      if (token != null) 'Authorization': 'Bearer $token',
    });

    // ✅ Field wajib: tipe_foto — dipakai backend untuk validasi & routing
    request.fields['tipe_foto'] = tipeFoto;

    // ✅ Field base64 dinamis sesuai tipe:
    //    tipeFoto='sebelum' → key: 'sebelum_base64'
    //    tipeFoto='sesudah' → key: 'sesudah_base64'
    final bytes = await foto.readAsBytes();
    request.fields['${tipeFoto}_base64'] =
        'data:image/jpeg;base64,' + base64Encode(bytes);

    final streamed  = await request.send();
    final response  = await http.Response.fromStream(streamed);
    return _handleResponse(response);
  }

  // ─────────────────────────────────────────
  // GET - Tarif by Jenis Pekerjaan
  // ─────────────────────────────────────────
  Future<Map<String, dynamic>> getTarifByJenis(String jenisPekerjaan) async {
    final response = await http.get(
      Uri.parse(
          '$baseUrl/penugasan/master/tarif-by-jenis?jenis_pekerjaan=$jenisPekerjaan'),
      headers: await _getHeaders(),
    );
    return _handleResponse(response);
  }

  // ─────────────────────────────────────────
  // GET - List Teknisi
  // ─────────────────────────────────────────
  Future<Map<String, dynamic>> getTeknisiList() async {
    final response = await http.get(
      Uri.parse('$baseUrl/penugasan/master/teknisi-list'),
      headers: await _getHeaders(),
    );
    return _handleResponse(response);
  }
}

// ===================================
// EXCEPTION
// ===================================
class PenugasanApiException implements Exception {
  final String message;
  final int? statusCode;
  final Map<String, dynamic>? errors;

  PenugasanApiException({
    required this.message,
    this.statusCode,
    this.errors,
  });

  @override
  String toString() =>
      'PenugasanApiException: $message (Status: $statusCode)';

  /// Ambil pesan error pertama dari field validation errors
  String? getFirstError() {
    if (errors == null) return null;
    for (var key in errors!.keys) {
      final val = errors![key];
      if (val is List && val.isNotEmpty) return val.first.toString();
    }
    return null;
  }
}