import { type Video, type InsertVideo } from "@shared/schema";

interface BunnyVideo {
  guid: string;
  title: string;
  description?: string;
  length: number;
  status: number;
  dateUploaded: string;
  views: number;
  thumbnailFileName?: string;
  category?: string;
  metaTags?: Array<{
    property: string;
    value: string;
  }>;
  moments?: Array<{
    type: string; // "preroll", "midroll", "postroll"  
    position?: number; // seconds for midroll
    vastTag?: string;
    duration?: number;
    network?: string;
    title?: string;
  }>;
}

interface BunnyVideoDetails extends BunnyVideo {
  description?: string;
  customMetadata?: Record<string, any>;
}

interface BunnyLibraryResponse {
  items: BunnyVideo[];
  currentPage: number;
  itemsPerPage: number;
  totalItems: number;
}

export class BunnyService {
  private apiKey: string;
  private libraryId: string;
  private hostname: string;

  constructor() {
    this.apiKey = process.env.BUNNY_API_KEY!;
    this.libraryId = process.env.BUNNY_LIBRARY_ID!;
    this.hostname = process.env.BUNNY_HOSTNAME!;

    if (!this.apiKey || !this.libraryId || !this.hostname) {
      throw new Error("Missing Bunny.net configuration");
    }
  }

  private async makeRequest(endpoint: string): Promise<any> {
    const url = `https://video.bunnycdn.com/library/${this.libraryId}/${endpoint}`;
    
    const response = await fetch(url, {
      headers: {
        'AccessKey': this.apiKey,
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      // Add timeout and connection optimizations
      signal: AbortSignal.timeout(10000), // 10 second timeout
    });

    if (!response.ok) {
      throw new Error(`Bunny API error: ${response.status} ${response.statusText}`);
    }

    return response.json();
  }

  private bunnyVideoToVideo(bunnyVideo: BunnyVideo | BunnyVideoDetails): Video {
    // Generate optimized thumbnail URL from Bunny CDN with WebP format for better performance
    const thumbnailUrl = bunnyVideo.thumbnailFileName 
      ? `https://${this.hostname}/${bunnyVideo.guid}/${bunnyVideo.thumbnailFileName}?width=400&height=225&format=webp`
      : `https://${this.hostname}/${bunnyVideo.guid}/thumbnail.jpg?width=400&height=225&format=webp`;

    // Generate signed HLS URL for private video access
    const hlsUrl = this.generateSignedUrl(bunnyVideo.guid);
    const iframeUrl = `https://iframe.mediadelivery.net/embed/${this.libraryId}/${bunnyVideo.guid}?preroll=false&postroll=false&ads=false&controls=false`;

    // Extract description from BunnyVideoDetails if available
    let description = 'description' in bunnyVideo ? bunnyVideo.description || "" : "";
    
    // Extract artist from metaTags if available
    let artist = null;
    
    // Always check metaTags for description and artist since Bunny.net stores it there
    if (bunnyVideo.metaTags && bunnyVideo.metaTags.length > 0) {
      const descriptionTag = bunnyVideo.metaTags.find((tag: any) => 
        tag.property?.toLowerCase() === 'description'
      );
      if (descriptionTag && descriptionTag.value) {
        description = descriptionTag.value;
      }
      
      // Look for artist in metaTags
      const artistTag = bunnyVideo.metaTags.find((tag: any) => 
        tag.property?.toLowerCase() === 'artist' || tag.property?.toLowerCase() === 'performer'
      );
      if (artistTag && artistTag.value) {
        artist = artistTag.value;
      }
    }

    // Clean title - remove .mpg4, .mp4, .MPG4, .MP4 extensions
    let cleanTitle = bunnyVideo.title || 'Untitled Video';
    cleanTitle = cleanTitle.replace(/\.(mpg4|mp4|MPG4|MP4)$/i, '');
    
    // Clean artist - remove .mpg4, .mp4, .MPG4, .MP4 extensions if artist exists
    if (artist) {
      artist = artist.replace(/\.(mpg4|mp4|MPG4|MP4)$/i, '');
    }

    // No category from Bunny.net - keeping category empty
    const category = "";

    // No tags from Bunny.net - keeping tags empty
    const tags: string[] = [];

    return {
      id: bunnyVideo.guid,
      title: cleanTitle,
      artist: artist,
      description: description,
      filename: null,
      episodeNumber: null,
      episodeTitle: null,
      thumbnailUrl,
      customThumbnailUrl: null,
      faceCenterPosition: null,
      facesDetected: null,
      faceConfidence: null,
      videoUrl: hlsUrl, // Signed HLS URL
      videoUrlMp4: hlsUrl, // Use signed HLS URL for preview as well
      videoUrlIframe: iframeUrl, // iframe fallback
      duration: Math.floor(bunnyVideo.length || 0),
      views: bunnyVideo.views || 0,
      category: category,
      contentType: 'video' as const,
      genre: 'other' as const,
      tags: tags,
      isPublic: true,
      uploadStatus: "completed",
      originalFileName: null,
      fileSize: null,
      bitrate: null,
      resolution: null,
      format: null,
      encoding: null,
      createdAt: new Date(bunnyVideo.dateUploaded),
      updatedAt: new Date(bunnyVideo.dateUploaded)
    };
  }

  async getVideos(page: number = 1, itemsPerPage: number = 20, search?: string): Promise<{ videos: Video[], total: number }> {
    try {
      let endpoint = `videos?page=${page}&itemsPerPage=${itemsPerPage}&orderBy=date`;
      
      if (search) {
        endpoint += `&search=${encodeURIComponent(search)}`;
      }

      const response: BunnyLibraryResponse = await this.makeRequest(endpoint);
      
      // Filter only successfully processed videos (status 4 = finished)
      const processedVideos = response.items.filter(video => video.status === 4);
      

      
      const videos = processedVideos.map(video => this.bunnyVideoToVideo(video));
      
      return {
        videos,
        total: response.totalItems
      };
    } catch (error) {
      console.error('Error fetching videos from Bunny:', error);
      throw error;
    }
  }

  async getVideo(guid: string): Promise<Video | null> {
    try {
      console.log(`Fetching video with description from Bunny: ${guid}`);
      const bunnyVideo: BunnyVideoDetails = await this.makeRequest(`videos/${guid}`);
      console.log(`Fetching video: ${bunnyVideo.title} - Description available: ${!!bunnyVideo.description}`);
      return this.bunnyVideoToVideo(bunnyVideo);
    } catch (error) {
      console.error(`Error fetching video ${guid} from Bunny:`, error);
      return null;
    }
  }

  async getVideoDetails(videoId: string): Promise<BunnyVideoDetails | null> {
    try {
      console.log(`Fetching detailed video data for: ${videoId}`);
      const videoDetails: BunnyVideoDetails = await this.makeRequest(`videos/${videoId}`);
      console.log(`Retrieved video details with ${videoDetails.moments?.length || 0} ad spots`);
      return videoDetails;
    } catch (error) {
      console.error(`Error fetching video details for ${videoId}:`, error);
      return null;
    }
  }

  async getVideoAds(videoId: string): Promise<Array<{
    adType: string;
    adUrl?: string;
    adTitle?: string;
    adDuration?: number;
    position?: number;
    vastTag?: string;
    adNetwork?: string;
    priority: number;
  }>> {
    try {
      const videoDetails = await this.getVideoDetails(videoId);
      if (!videoDetails || !videoDetails.moments) {
        console.log(`No ad moments found for video ${videoId}`);
        return [];
      }

      console.log(`Found ${videoDetails.moments.length} ad moments for video ${videoId}`);
      return videoDetails.moments.map((moment, index) => ({
        adType: moment.type,
        adUrl: moment.vastTag || '',
        adTitle: moment.title || `${moment.type} Ad`,
        adDuration: moment.duration || 30,
        position: moment.position || 0,
        vastTag: moment.vastTag,
        adNetwork: moment.network || 'Unknown',
        priority: index + 1,
      }));
    } catch (error) {
      console.error(`Error fetching video ads for ${videoId}:`, error);
      return [];
    }
  }

  async getCategories(): Promise<string[]> {
    try {
      // Get all videos and extract unique categories
      const { videos } = await this.getVideos(1, 1000);
      const categories = Array.from(new Set(videos.map(v => v.category).filter(Boolean) as string[]));
      return categories;
    } catch (error) {
      console.error('Error fetching categories from Bunny:', error);
      return [];
    }
  }

  // Generate signed URL for private video access
  generateSignedUrl(videoId: string, expirationTime: number = 3600): string {
    const baseUrl = `https://${this.hostname}/${videoId}/playlist.m3u8`;
    const expires = Math.floor(Date.now() / 1000) + expirationTime;
    
    // Simple token generation (in production, use proper HMAC signing)
    const token = Buffer.from(`${videoId}:${expires}:${this.apiKey.substring(0, 8)}`).toString('base64');
    
    return `${baseUrl}?token=${token}&expires=${expires}`;
  }
}