import 'dart:io';

import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/response_extensions.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/interfaces/file_media.interface.dart';
import 'package:immich_mobile/providers/api.provider.dart';
import 'package:immich_mobile/repositories/file_media.repository.dart';
import 'package:immich_mobile/services/api.service.dart';
import 'package:logging/logging.dart';

import 'package:path_provider/path_provider.dart';

final imageViewerServiceProvider = Provider(
  (ref) => ImageViewerService(
    ref.watch(apiServiceProvider),
    ref.watch(fileMediaRepositoryProvider),
  ),
);

class ImageViewerService {
  final ApiService _apiService;
  final IFileMediaRepository _fileMediaRepository;
  final Logger _log = Logger("ImageViewerService");

  ImageViewerService(this._apiService, this._fileMediaRepository);

  Future<bool> downloadAsset(Asset asset) async {
    File? imageFile;
    File? videoFile;
    try {
      // Download LivePhotos image and motion part
      if (asset.isImage && asset.livePhotoVideoId != null && Platform.isIOS) {
        var imageResponse =
            await _apiService.assetsApi.downloadAssetWithHttpInfo(
          asset.remoteId!,
        );

        var motionResponse =
            await _apiService.assetsApi.downloadAssetWithHttpInfo(
          asset.livePhotoVideoId!,
        );

        if (imageResponse.statusCode != 200 ||
            motionResponse.statusCode != 200) {
          final failedResponse =
              imageResponse.statusCode != 200 ? imageResponse : motionResponse;
          _log.severe(
            "Motion asset download failed",
            failedResponse.toLoggerString(),
          );
          return false;
        }

        Asset? resultAsset;

        final tempDir = await getTemporaryDirectory();
        videoFile = await File('${tempDir.path}/livephoto.mov').create();
        imageFile = await File('${tempDir.path}/livephoto.heic').create();
        videoFile.writeAsBytesSync(motionResponse.bodyBytes);
        imageFile.writeAsBytesSync(imageResponse.bodyBytes);

        resultAsset = await _fileMediaRepository.saveLivePhoto(
          image: imageFile,
          video: videoFile,
          title: asset.fileName,
        );

        if (resultAsset == null) {
          _log.warning(
            "Asset cannot be saved as a live photo. This is most likely a motion photo. Saving only the image file",
          );
          resultAsset = await _fileMediaRepository
              .saveImage(imageResponse.bodyBytes, title: asset.fileName);
        }

        return resultAsset != null;
      } else {
        var res = await _apiService.assetsApi
            .downloadAssetWithHttpInfo(asset.remoteId!);

        if (res.statusCode != 200) {
          _log.severe("Asset download failed", res.toLoggerString());
          return false;
        }

        final Asset? resultAsset;
        final relativePath = Platform.isAndroid ? 'DCIM/Immich' : null;

        if (asset.isImage) {
          resultAsset = await _fileMediaRepository.saveImage(
            res.bodyBytes,
            title: asset.fileName,
            relativePath: relativePath,
          );
        } else {
          final tempDir = await getTemporaryDirectory();
          videoFile = await File('${tempDir.path}/${asset.fileName}').create();
          videoFile.writeAsBytesSync(res.bodyBytes);
          resultAsset = await _fileMediaRepository.saveVideo(
            videoFile,
            title: asset.fileName,
            relativePath: relativePath,
          );
        }
        return resultAsset != null;
      }
    } catch (error, stack) {
      _log.severe("Error saving downloaded asset", error, stack);
      return false;
    } finally {
      // Clear temp files
      imageFile?.delete();
      videoFile?.delete();
    }
  }
}