const axios = require('axios');
const cheerio = require('cheerio');
const { getCache, setCache } = require('./db');

const BASE_URL = 'https://www.cineby.at';
const CACHE_TTL = 3600000; // 1 hour

// Helper to fetch and parse with cheerio
const fetchPage = async (url) => {
  const { data } = await axios.get(url, {
    headers: {
      'User-Agent': 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
    },
    timeout: 15000
  });
  return cheerio.load(data);
};

const withCache = async (cacheKey, fetchFn) => {
  const cached = getCache(cacheKey, CACHE_TTL);
  if (cached) {
    console.log("[CACHE HIT] " + cacheKey);
    return cached;
  }
  console.log("[CACHE MISS] " + cacheKey);
  try {
    const data = await fetchFn();
    setCache(cacheKey, data);
    return data;
  } catch (err) {
    console.error("[SOURCE ERROR] Failed to fetch " + cacheKey + ":", err.message);
    const stale = getCache(cacheKey, CACHE_TTL * 100);
    if (stale) {
      console.log("[STALE CACHE HIT] " + cacheKey);
      return stale;
    }
    return [];
  }
};

const extractRealUrl = (url) => {
  if (!url) return null;
  if (url.includes('wsrv.nl/?url=')) {
    try {
      // Keep the proxy, just replace the resolution inside the encoded URL
      if (url.includes('w342') || url.includes('w780')) {
        return url.replace('w342', 'original').replace('w780', 'original');
      }
      return url;
    } catch (e) {
      return url;
    }
  }
  return url;
};

class SourceAdapter {
  static async getTrending() {
    return withCache('trending', async () => {
      const TMDB_KEY = "15d2ea6d0dc1d476efbca3eba2b9bbfb";
      const { data } = await axios.get(`https://api.themoviedb.org/3/trending/all/day?api_key=${TMDB_KEY}`);
      return data.results.filter(m => m.poster_path).map(m => ({
        id: String(m.id),
        type: m.media_type || (m.title ? 'movie' : 'tv'),
        title: m.title || m.name || "Unknown",
        posterUrl: `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w342${m.poster_path}&output=webp&q=50&n=-1`,
        backdropUrl: m.backdrop_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w780${m.backdrop_path}&output=webp&q=70&n=-1` : null,
        rating: m.vote_average || 0,
        year: (m.release_date || m.first_air_date || '').split('-')[0] || new Date().getFullYear(),
        overview: m.overview || "No description available."
      }));
    });
  }

  static async getTop10() {
    return withCache('top10', async () => {
      const trending = await this.getTrending();
      return trending.slice(0, 10);
    });
  }

  static async getHomeSections() {
    return withCache('home_sections_tmdb', async () => {
      const TMDB_KEY = "15d2ea6d0dc1d476efbca3eba2b9bbfb";
      
      const [trendingRes, moviesRes, tvRes] = await Promise.all([
        axios.get(`https://api.themoviedb.org/3/trending/all/day?api_key=${TMDB_KEY}`),
        axios.get(`https://api.themoviedb.org/3/movie/popular?api_key=${TMDB_KEY}`),
        axios.get(`https://api.themoviedb.org/3/tv/popular?api_key=${TMDB_KEY}`)
      ]);

      const mapTmdbItem = (m, typeOverride) => ({
        id: String(m.id),
        type: typeOverride || m.media_type || (m.title ? 'movie' : 'tv'),
        title: m.title || m.name || "Unknown",
        posterUrl: m.poster_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w342${m.poster_path}&output=webp&q=50&n=-1` : null,
        backdropUrl: m.backdrop_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w780${m.backdrop_path}&output=webp&q=70&n=-1` : null,
        rating: m.vote_average || 0,
        year: (m.release_date || m.first_air_date || '').split('-')[0] || new Date().getFullYear(),
        overview: m.overview || "No description available."
      });

      const trending = trendingRes.data.results.filter(m => m.poster_path && m.backdrop_path).map(m => mapTmdbItem(m));
      const movies = moviesRes.data.results.filter(m => m.poster_path).map(m => mapTmdbItem(m, 'movie'));
      const tv = tvRes.data.results.filter(m => m.poster_path).map(m => mapTmdbItem(m, 'tv'));
      
      return [
        { title: 'Trending on Bingeverse', items: trending },
        { title: 'Latest Movies', items: movies },
        { title: 'Latest TV Shows', items: tv },
      ];
    });
  }

  static async getPopularMovies(page = 1) {
    return withCache('popular_movies_' + page, async () => {
      const TMDB_KEY = "15d2ea6d0dc1d476efbca3eba2b9bbfb";
      const { data } = await axios.get(`https://api.themoviedb.org/3/movie/popular?api_key=${TMDB_KEY}&page=${page}`);
      return data.results.filter(m => m.poster_path).map(m => ({
        id: String(m.id),
        type: 'movie',
        title: m.title || "Unknown",
        posterUrl: `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w342${m.poster_path}&output=webp&q=50&n=-1`,
        rating: m.vote_average || 0,
        year: (m.release_date || '').split('-')[0] || new Date().getFullYear()
      }));
    });
  }

  static async getPopularTV(page = 1) {
    return withCache('popular_tv_' + page, async () => {
      const TMDB_KEY = "15d2ea6d0dc1d476efbca3eba2b9bbfb";
      const { data } = await axios.get(`https://api.themoviedb.org/3/tv/popular?api_key=${TMDB_KEY}&page=${page}`);
      return data.results.filter(m => m.poster_path).map(m => ({
        id: String(m.id),
        type: 'tv',
        title: m.name || "Unknown",
        posterUrl: `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w342${m.poster_path}&output=webp&q=50&n=-1`,
        rating: m.vote_average || 0,
        year: (m.first_air_date || '').split('-')[0] || new Date().getFullYear()
      }));
    });
  }

  static async searchTitles(query, page = 1) {
    if (!query) return [];
    return withCache("search_" + query + "_" + page, async () => {
      try {
        const TMDB_KEY = "15d2ea6d0dc1d476efbca3eba2b9bbfb";
        const { data } = await axios.get(`https://api.themoviedb.org/3/search/multi?api_key=${TMDB_KEY}&query=${encodeURIComponent(query)}&page=${page}`);
        
        const items = [];
        if (data && data.results) {
          for (const m of data.results) {
            // Only include movies and tv shows that have a poster
            if ((m.media_type === 'movie' || m.media_type === 'tv') && m.poster_path) {
              items.push({
                id: String(m.id),
                type: m.media_type,
                title: m.title || m.name || "Unknown Title",
                posterUrl: `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w342${m.poster_path}&output=webp&q=50&n=-1`,
                year: m.release_date?.split('-')[0] || m.first_air_date?.split('-')[0] || new Date().getFullYear()
              });
            }
          }
        }
        return items;
      } catch (err) {
        console.error("Search API error:", err.message);
        return [];
      }
    });
  }

  static async getMovie(id) {
    return withCache("movie_" + id, async () => {
      try {
        const TMDB_KEY = "15d2ea6d0dc1d476efbca3eba2b9bbfb";
        const { data } = await axios.get(`https://api.themoviedb.org/3/movie/${id}?api_key=${TMDB_KEY}&append_to_response=credits,similar`);
        
        return {
          id: String(data.id),
          sourceId: String(data.id),
          type: 'movie',
          title: data.title || "Unknown Movie",
          overview: data.overview || "No description available.",
          posterUrl: data.poster_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w780${data.poster_path}&output=webp&q=70&n=-1` : "https://images.unsplash.com/photo-1536440136628-849c177e76a1?w=500&h=750&fit=crop",
          backdropUrl: data.backdrop_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/original${data.backdrop_path}&output=webp&q=80&n=-1` : "https://images.unsplash.com/photo-1440404653325-ab127d49abc1?w=1280&h=720&fit=crop",
          rating: data.vote_average || 0,
          year: data.release_date ? data.release_date.split('-')[0] : null,
          runtime: data.runtime,
          genres: data.genres?.map(g => g.name) || [],
          cast: data.credits?.cast?.slice(0, 10).map(c => ({
            id: c.id,
            name: c.name,
            character: c.character,
            profileUrl: c.profile_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w185${c.profile_path}&output=webp&q=50&n=-1` : null
          })) || [],
          similar: data.similar?.results?.filter(m => m.poster_path).slice(0, 10).map(m => ({
            id: String(m.id),
            type: 'movie',
            title: m.title,
            posterUrl: `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w342${m.poster_path}&output=webp&q=50&n=-1`,
            rating: m.vote_average
          })) || [],
          sourceUrl: BASE_URL + '/movie/' + id
        };
      } catch (err) {
        console.error("TMDB API error for movie", id, err.message);
        throw err;
      }
    });
  }

  static async getTVShow(id) {
    return withCache("tv_" + id, async () => {
      try {
        const TMDB_KEY = "15d2ea6d0dc1d476efbca3eba2b9bbfb";
        const { data } = await axios.get(`https://api.themoviedb.org/3/tv/${id}?api_key=${TMDB_KEY}&append_to_response=credits,similar`);
        
        return {
          id: String(data.id),
          sourceId: String(data.id),
          type: 'tv',
          title: data.name || "Unknown TV Show",
          overview: data.overview || "No description available.",
          posterUrl: data.poster_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w780${data.poster_path}&output=webp&q=70&n=-1` : "https://images.unsplash.com/photo-1536440136628-849c177e76a1?w=500&h=750&fit=crop",
          backdropUrl: data.backdrop_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/original${data.backdrop_path}&output=webp&q=80&n=-1` : "https://images.unsplash.com/photo-1440404653325-ab127d49abc1?w=1280&h=720&fit=crop",
          rating: data.vote_average || 0,
          year: data.first_air_date ? data.first_air_date.split('-')[0] : null,
          genres: data.genres?.map(g => g.name) || [],
          cast: data.credits?.cast?.slice(0, 10).map(c => ({
            id: c.id,
            name: c.name,
            character: c.character,
            profileUrl: c.profile_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w185${c.profile_path}&output=webp&q=50&n=-1` : null
          })) || [],
          seasons: data.seasons?.filter(s => s.season_number > 0).map(s => ({
            id: s.id,
            name: s.name,
            seasonNumber: s.season_number,
            episodeCount: s.episode_count,
            posterUrl: s.poster_path ? `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w342${s.poster_path}&output=webp&q=50&n=-1` : null
          })) || [],
          similar: data.similar?.results?.filter(m => m.poster_path).slice(0, 10).map(m => ({
            id: String(m.id),
            type: 'tv',
            title: m.name,
            posterUrl: `https://wsrv.nl/?url=https://image.tmdb.org/t/p/w342${m.poster_path}&output=webp&q=50&n=-1`,
            rating: m.vote_average
          })) || [],
          sourceUrl: BASE_URL + '/tv/' + id
        };
      } catch (err) {
        console.error("TMDB API error for tv", id, err.message);
        throw err;
      }
    });
  }
}

module.exports = SourceAdapter;
