import 'dart:convert';

import 'package:cinema/common/video_downloader.dart';
import 'package:injectable/injectable.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';

part 'video.service.g.dart';

@injectable
class VideoService {
  final VideoDownloader _videoDownloader;

  VideoService(this._videoDownloader);

  @Route.get('/<videoId>')
  Future<Response> downloadVideo(Request request, String videoId) async {
    // Validate video ID (YouTube IDs are 11 characters, alphanumeric with - and _)
    if (!RegExp(r'^[a-zA-Z0-9_-]{11}$').hasMatch(videoId)) {
      return Response(
        400,
        body: jsonEncode({'error': 'Invalid YouTube video ID'}),
        headers: {'Content-Type': 'application/json'},
      );
    }

    // Check if already cached
    if (await _videoDownloader.isCached(videoId)) {
      return Response.ok(
        jsonEncode({
          'status': 'cached',
          'videoId': videoId,
          'path': '${VideoDownloader.cacheDir}/$videoId/video.mp4',
        }),
        headers: {'Content-Type': 'application/json'},
      );
    }

    // Download and resize
    final path = await _videoDownloader.downloadAndResize(videoId);

    if (path == null) {
      return Response(
        500,
        body: jsonEncode({
          'error': 'Failed to download or resize video',
          'videoId': videoId,
        }),
        headers: {'Content-Type': 'application/json'},
      );
    }

    return Response.ok(
      jsonEncode({
        'status': 'downloaded',
        'videoId': videoId,
        'path': path,
        'size': '${VideoDownloader.maxWidth}x${VideoDownloader.maxHeight} (max)',
      }),
      headers: {'Content-Type': 'application/json'},
    );
  }

  @Route.get('/')
  Future<Response> listVideos(Request request) async {
    final videos = await _videoDownloader.getCachedVideos();

    return Response.ok(
      jsonEncode({'videos': videos}),
      headers: {'Content-Type': 'application/json'},
    );
  }

  Router get router => _$VideoServiceRouter(this);
}
