import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
import 'package:image/image.dart' as img;
import 'package:intl/intl.dart';

import '../models/air_installation_data.dart';
import '../models/air_collection_data.dart';
import 'api_service.dart';
import 'local_storage_service.dart';

/// A dedicated service to handle all business logic for the Air Manual Sampling feature.
class AirSamplingService {
  final ApiService _apiService = ApiService();
  final LocalStorageService _localStorageService = LocalStorageService();

  /// Picks an image from the specified source, adds a timestamp watermark,
  /// and saves it to a temporary directory with a standardized name.
  Future<File?> pickAndProcessImage(
      ImageSource source, {
        required String stationCode,
        required String imageInfo,
        String processType = 'INSTALL', // Defaults to INSTALL for backward compatibility
      }) async {
    final picker = ImagePicker();
    final XFile? photo = await picker.pickImage(
        source: source, imageQuality: 85, maxWidth: 1024);
    if (photo == null) return null;

    final bytes = await photo.readAsBytes();
    img.Image? originalImage = img.decodeImage(bytes);
    if (originalImage == null) return null;

    final String watermarkTimestamp =
    DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
    final font = img.arial24;

    final textWidth = watermarkTimestamp.length * 12;
    img.fillRect(originalImage,
        x1: 5,
        y1: 5,
        x2: textWidth + 15,
        y2: 35,
        color: img.ColorRgb8(255, 255, 255));
    img.drawString(originalImage, watermarkTimestamp,
        font: font, x: 10, y: 10, color: img.ColorRgb8(0, 0, 0));

    final tempDir = await getTemporaryDirectory();
    final fileTimestamp = watermarkTimestamp.replaceAll(':', '-').replaceAll(' ', '_');

    final newFileName =
        "${stationCode}_${fileTimestamp}_${processType.toUpperCase()}_${imageInfo.replaceAll(' ', '')}.jpg";

    final filePath = path.join(tempDir.path, newFileName);

    return File(filePath)..writeAsBytesSync(img.encodeJpg(originalImage));
  }

  /// Orchestrates a two-step submission process for air installation samples.
  Future<Map<String, dynamic>> submitInstallation(AirInstallationData data) async {
    // --- OFFLINE-FIRST HELPER ---
    Future<Map<String, dynamic>> saveLocally() async {
      debugPrint("Saving installation locally...");
      data.status = 'L1'; // Mark as Locally Saved, Pending Submission
      await _localStorageService.saveAirSamplingRecord(data.toMap(), data.refID!);
      return {
        'status': 'L1',
        'message': 'No connection or server error. Installation data saved locally.',
      };
    }

    // --- STEP 1: SUBMIT TEXT DATA ---
    debugPrint("Step 1: Submitting installation text data...");
    final textDataResult = await _apiService.post('air/manual/installation', data.toJsonForApi());

    if (textDataResult['success'] != true) {
      debugPrint("Failed to submit text data. Reason: ${textDataResult['message']}");
      return await saveLocally();
    }

    // --- NECESSARY FIX: Safely parse the record ID from the server response ---
    final dynamic recordIdFromServer = textDataResult['data']?['air_man_id'];
    if (recordIdFromServer == null) {
      debugPrint("Text data submitted, but did not receive a record ID.");
      return await saveLocally();
    }

    debugPrint("Text data submitted successfully. Received record ID: $recordIdFromServer");

    // The ID from JSON can be a String or int, but our model needs an int.
    // Use int.tryParse for safe conversion.
    final int? parsedRecordId = int.tryParse(recordIdFromServer.toString());

    if (parsedRecordId == null) {
      debugPrint("Could not parse the received record ID: $recordIdFromServer");
      return await saveLocally(); // Treat as a failure if ID is invalid
    }

    data.airManId = parsedRecordId; // Assign the correctly typed integer ID

    // --- STEP 2: UPLOAD IMAGE FILES ---
    final filesToUpload = data.getImagesForUpload();
    if (filesToUpload.isEmpty) {
      debugPrint("No images to upload. Submission complete.");
      data.status = 'S1'; // Server Pending (no images needed)
      await _localStorageService.saveAirSamplingRecord(data.toMap(), data.refID!);
      return {'status': 'S1', 'message': 'Installation data submitted successfully.'};
    }

    debugPrint("Step 2: Uploading ${filesToUpload.length} images for record ID $parsedRecordId...");
    final imageUploadResult = await _apiService.air.uploadInstallationImages(
      airManId: parsedRecordId.toString(), // The API itself needs a string
      files: filesToUpload,
    );

    if (imageUploadResult['success'] != true) {
      debugPrint("Image upload failed. Reason: ${imageUploadResult['message']}");
      return await saveLocally();
    }

    debugPrint("Images uploaded successfully.");
    data.status = 'S2'; // Server Pending (images uploaded)
    await _localStorageService.saveAirSamplingRecord(data.toMap(), data.refID!);
    return {
      'status': 'S2',
      'message': 'Installation data and images submitted successfully.',
    };
  }


  /// Submits only the collection data, linked to a previous installation.
  Future<Map<String, dynamic>> submitCollection(AirCollectionData data) async {
    // --- OFFLINE-FIRST HELPER (CORRECTED) ---
    Future<Map<String, dynamic>> updateAndSaveLocally(String newStatus, {String? message}) async {
      debugPrint("Saving collection data locally with status: $newStatus");
      final allLogs = await _localStorageService.getAllAirSamplingLogs();
      final logIndex = allLogs.indexWhere((log) => log['refID'] == data.installationRefID);

      if (logIndex != -1) {
        final installationLog = allLogs[logIndex];
        // FIX: Nest collection data to prevent overwriting installation fields.
        installationLog['collectionData'] = data.toMap();
        installationLog['status'] = newStatus; // Update the overall status
        await _localStorageService.saveAirSamplingRecord(installationLog, data.installationRefID!);
      }
      return {
        'status': newStatus,
        'message': message ?? 'No connection or server error. Data saved locally.',
      };
    }

    // --- STEP 1: SUBMIT TEXT DATA ---
    debugPrint("Step 1: Submitting collection text data...");
    final textDataResult = await _apiService.post('air/manual/collection', data.toJson());

    if (textDataResult['success'] != true) {
      debugPrint("Failed to submit collection text data. Reason: ${textDataResult['message']}");
      return await updateAndSaveLocally('L3', message: 'No connection or server error. Collection data saved locally.');
    }
    debugPrint("Collection text data submitted successfully.");

    // --- STEP 2: UPLOAD IMAGE FILES ---
    final filesToUpload = data.getImagesForUpload();
    if (filesToUpload.isEmpty) {
      debugPrint("No collection images to upload. Submission complete.");
      await updateAndSaveLocally('S3'); // S3 = Server Completed
      return {'status': 'S3', 'message': 'Collection data submitted successfully.'};
    }

    debugPrint("Step 2: Uploading ${filesToUpload.length} collection images...");
    final imageUploadResult = await _apiService.air.uploadCollectionImages(
      airManId: data.airManId.toString(),
      files: filesToUpload,
    );

    if (imageUploadResult['success'] != true) {
      debugPrint("Image upload failed. Reason: ${imageUploadResult['message']}");
      // Use a new status 'L4' to indicate text submitted but images failed
      return await updateAndSaveLocally('L4', message: 'Data submitted, but image upload failed. Saved locally for retry.');
    }

    debugPrint("Images uploaded successfully.");
    await updateAndSaveLocally('S3'); // S3 = Server Completed
    return {
      'status': 'S3',
      'message': 'Collection data and images submitted successfully.',
    };
  }

  /// Fetches installations that are pending collection from local storage.
  Future<List<AirInstallationData>> getPendingInstallations() async {
    debugPrint("Fetching pending installations from local storage...");

    final logs = await _localStorageService.getAllAirSamplingLogs();

    final pendingInstallations = logs
        .where((log) {
      final status = log['status'];
      // --- CORRECTED ---
      // Only show installations that have been synced to the server (S1, S2).
      // 'L1' (Local only) records cannot be collected until they are synced.
      return status == 'S1' || status == 'S2';
    })
        .map((log) => AirInstallationData.fromJson(log))
        .toList();

    return pendingInstallations;
  }

  void dispose() {
    // Clean up any resources if necessary
  }
}