import 'dart:async';
import 'dart:io';

import 'package:cinema/common/env_not_found_exception.dart';
import 'package:cinema/feature/middleware/cors.dart';
import 'package:cinema/feature/poster/data/repositories/image_loader.dart';
import 'package:cinema/feature/poster/data/services/poster.service.dart';
import 'package:cinema/feature/root/data/service/root.service.dart';
import 'package:cinema/feature/version/version.dart';
import 'package:cinema/feature/video/data/repositories/video_loader.dart';
import 'package:cinema/feature/video/data/services/video.service.dart';
import 'package:cinema/injectable.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';

void main(List<String> args) async {
  runZonedGuarded(
    () async {
      final startTime = DateTime.now();

      configureDependencies();

      final router = Router();
      router.mount("/poster", getIt<PosterService>().router.call);
      router.mount("/video", getIt<VideoService>().router.call);
      router.mount("/", getIt<RootService>().router.call);

      /// add middlewares (Logging, CORS)
      final handler = Pipeline().addMiddleware(logRequests()).addMiddleware(cors()).addHandler(router.call);

      // For running in containers, we respect the PORT environment variable.
      final port = int.parse(Platform.environment['PORT'] ?? '3000');
      await io.serve(handler, InternetAddress.anyIPv4, port, poweredByHeader: null).then((server) async {
        final bannerFile = File('assets/banner.txt');
        if (await bannerFile.exists()) {
          final banner = await bannerFile.readAsString();
          print(banner);
        }

        print('Caching current trending images...');
        final ImageLoader imageLoader = getIt();
        final movies = await imageLoader.getMovies();
        for (var movie in movies) {
          await imageLoader.downloadImages(movie);
        }

        // Cache videos in background (non-blocking)
        print('Starting video caching in background...');
        final VideoLoader videoLoader = getIt();
        for (var movie in movies) {
          // Jedes Video läuft in einem eigenen async "Thread" (Future)
          // ohne await, damit der Server-Start nicht blockiert wird
          videoLoader.downloadVideo(movie).then((success) {
            if (success) {
              print('Background video cache complete: ${movie.title}');
            }
          }).catchError((e) {
            print('Background video cache error for ${movie.title}: $e');
          });
        }

        getIt<Version>().printVersion();

        print('Serving at ${server.address.host}:${server.port}\n');

        final time = DateTime.now().difference(startTime);
        print('Server started at: $startTime');
        print('Startup time: $time\n');
      });
    },
    (error, stackTrace) {
      stderr.writeln(error);
      if (error is EnvNotFoundException) {
        exit(1);
      }
    },
  );
}
