import { NextRequest, NextResponse } from 'next/server';
import axios from 'axios';

const IPTV_DNS = 'http://lotvservices.net:2095';

// Simple in-memory cache for IPTV lists (10 minutes TTL)
interface CacheEntry {
  data: any;
  timestamp: number;
}
const ipTvCache = new Map<string, CacheEntry>();
const CACHE_TTL = 10 * 60 * 1000;

async function getCachedData(dnsUrl: string, username: string, password: string, action: string, fetchFn: () => Promise<any>) {
  const key = `${dnsUrl}:${username}:${password}:${action}`;
  const now = Date.now();
  const cached = ipTvCache.get(key);

  if (cached && (now - cached.timestamp < CACHE_TTL)) {
    console.log(`⚡ Cache HIT para IPTV: ${action}`);
    return cached.data;
  }

  console.log(`🌐 Cache MISS para IPTV: ${action}. Descargando del servidor...`);
  const data = await fetchFn();
  ipTvCache.set(key, { data, timestamp: now });
  return data;
}

// Helper to decode credentials from Authorization header
function getCredentials(req: NextRequest) {
  const authHeader = req.headers.get('Authorization');
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return null;
  }
  const token = authHeader.substring(7);
  try {
    const decoded = Buffer.from(token, 'base64').toString('utf8');
    const parts = decoded.split(':');
    const username = parts[0];
    const password = parts[1];
    if (!username || !password) return null;
    
    // Extract DNS and fallback if not present (backward compatibility)
    let dnsUrl = parts[2] ? parts.slice(2).join(':') : process.env.IPTV_DNS || 'http://lotvservices.net:2095';
    
    // Sanitize
    if (!dnsUrl.startsWith('http://') && !dnsUrl.startsWith('https://')) {
      dnsUrl = 'http://' + dnsUrl;
    }
    if (dnsUrl.endsWith('/')) {
      dnsUrl = dnsUrl.slice(0, -1);
    }
    
    return { username, password, dnsUrl };
  } catch {
    return null;
  }
}

export async function POST(req: NextRequest, { params }: { params: { slug: string[] } }) {
  const path = params.slug.join('/');

  if (path === 'auth/login') {
    try {
      const body = await req.json();
      const username = body.email || body.username;
      const password = body.password;

      if (!username || !password) {
        return NextResponse.json({ success: false, message: 'Usuario y contraseña requeridos' }, { status: 400 });
      }

      // Preconfigured IPTV DNS list to scan automatically
      const IPTV_SERVERS = [
        'https://lotvservices.net:2096',
        'http://lotvservices.net:2095',
        'http://flashtv.mx:80',
        'https://zona593movie.com:8443'
      ];

      let authenticatedDns = null;
      let userInfo = null;

      console.log(`🔑 Escaneando servidores para el usuario "${username}"...`);

      // Sequentially try to authenticate credentials on each server
      for (const dnsUrl of IPTV_SERVERS) {
        try {
          const url = `${dnsUrl}/player_api.php?username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`;
          const response = await axios.get(url, { timeout: 6000 }); // Fast 6 seconds timeout per server check
          const data = response.data;

          const isAuthSuccess = data && data.user_info && (
            data.user_info.auth === 1 || 
            data.user_info.auth === '1' || 
            data.user_info.auth === true ||
            data.user_info.status?.toLowerCase() === 'active'
          );

          if (isAuthSuccess) {
            console.log(`✅ Autenticación exitosa en servidor: ${dnsUrl}`);
            authenticatedDns = dnsUrl;
            userInfo = data.user_info;
            break;
          }
        } catch (err: any) {
          console.warn(`⚠️ Servidor ${dnsUrl} rechazado o inalcanzable: ${err.message}`);
        }
      }

      if (authenticatedDns && userInfo) {
        // Expiration date conversion (timestamp to ISO String)
        const expDate = userInfo.exp_date ? new Date(parseInt(userInfo.exp_date) * 1000).toISOString() : undefined;
        
        // Generate stateless token containing the successfully authenticated DNS
        const token = Buffer.from(`${username}:${password}:${authenticatedDns}`).toString('base64');

        console.log('✅ Login completado con token dinámico.');

        return NextResponse.json({
          success: true,
          data: {
            accessToken: token,
            refreshToken: token,
            user: {
              id: username,
              username: username,
              email: `${username}@iptv.com`,
              role: 'user',
              status: 'active',
              maxDevices: parseInt(userInfo.max_connections) || 1,
              connectedDevices: parseInt(userInfo.active_cons) || 0,
              createdAt: new Date().toISOString(),
              expiresAt: expDate
            }
          }
        });
      }

      console.warn('❌ Credenciales inválidas en todos los servidores escaneados.');
      return NextResponse.json({ success: false, message: 'Usuario o contraseña incorrectos' }, { status: 401 });
    } catch (err: any) {
      console.error('❌ Error general en login:', err.message);
      return NextResponse.json({ success: false, message: 'Error interno en el servidor de streaming' }, { status: 500 });
    }
  }

  if (path === 'auth/refresh') {
    try {
      const body = await req.json();
      const refreshToken = body.refreshToken;
      if (!refreshToken) {
        return NextResponse.json({ success: false, message: 'Refresh token requerido' }, { status: 400 });
      }

      // Decode and check format
      const decoded = Buffer.from(refreshToken, 'base64').toString('utf8');
      const parts = decoded.split(':');
      if (parts.length < 2) {
        return NextResponse.json({ success: false, message: 'Token inválido' }, { status: 401 });
      }

      return NextResponse.json({
        success: true,
        data: {
          accessToken: refreshToken,
          refreshToken: refreshToken
        }
      });
    } catch (err: any) {
      return NextResponse.json({ success: false, message: 'Token inválido' }, { status: 401 });
    }
  }

  return NextResponse.json({ error: 'Ruta no encontrada' }, { status: 404 });
}

export async function GET(req: NextRequest, { params }: { params: { slug: string[] } }) {
  const path = params.slug.join('/');
  const credentials = getCredentials(req);

  if (!credentials) {
    return NextResponse.json({ success: false, message: 'No autorizado' }, { status: 401 });
  }

  const { username, password, dnsUrl } = credentials;
  const baseUrl = `${dnsUrl}/player_api.php?username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`;

  try {
    // --- CHANNELS ---
    if (path === 'channels') {
      const categoryId = req.nextUrl.searchParams.get('category');
      
      let streams = await getCachedData(dnsUrl, username, password, 'get_live_streams', async () => {
        const response = await axios.get(`${baseUrl}&action=get_live_streams`, { timeout: 45000 });
        return response.data;
      });
      if (!Array.isArray(streams)) streams = [];

      // Filter by category if requested
      if (categoryId && categoryId !== 'all') {
        streams = streams.filter((s: any) => String(s.category_id) === String(categoryId));
      }

      const mappedChannels = streams.map((s: any) => ({
        id: String(s.stream_id),
        name: s.name,
        number: parseInt(s.num) || undefined,
        logoUrl: s.stream_icon || '',
        streamUrl: `${dnsUrl}/live/${encodeURIComponent(username)}/${encodeURIComponent(password)}/${s.stream_id}.m3u8`,
        categoryId: String(s.category_id),
        isLive: true,
        currentProgram: s.epg_channel_id || '',
        viewers: 0
      }));

      return NextResponse.json({ success: true, data: mappedChannels });
    }

    // --- CHANNEL EPG GUIDE ---
    if (path === 'channels/epg') {
      const streamId = req.nextUrl.searchParams.get('streamId');
      if (!streamId) {
        return NextResponse.json({ success: false, message: 'ID del canal requerido' }, { status: 400 });
      }

      const epgData = await getCachedData(dnsUrl, username, password, `get_short_epg:${streamId}`, async () => {
        const response = await axios.get(`${baseUrl}&action=get_short_epg&stream_id=${streamId}`, { timeout: 15000 });
        return response.data;
      });

      let listings: any[] = [];
      if (epgData && Array.isArray(epgData.epg_listings)) {
        listings = epgData.epg_listings.map((item: any) => {
          // Helper to safely decode base64
          const decodeB64 = (str: string) => {
            if (!str) return '';
            try {
              return Buffer.from(str, 'base64').toString('utf8');
            } catch {
              return str;
            }
          };

          return {
            id: item.id || '',
            title: decodeB64(item.title),
            description: decodeB64(item.description),
            start: item.start || '',
            end: item.end || '',
            startTimestamp: parseInt(item.start_timestamp) || 0,
            endTimestamp: parseInt(item.end_timestamp) || 0,
            nowPlaying: parseInt(item.now_playing) === 1
          };
        });
      }

      return NextResponse.json({ success: true, data: listings });
    }

    // --- CHANNEL CATEGORIES ---
    if (path === 'channels/categories') {
      let categories = await getCachedData(dnsUrl, username, password, 'get_live_categories', async () => {
        const response = await axios.get(`${baseUrl}&action=get_live_categories`, { timeout: 15000 });
        return response.data;
      });
      if (!Array.isArray(categories)) categories = [];

      const mappedCategories = categories.map((c: any) => ({
        id: String(c.category_id),
        name: c.category_name,
        slug: String(c.category_id)
      }));

      return NextResponse.json({ success: true, data: mappedCategories });
    }

    // --- MOVIES ---
    if (path === 'movies') {
      const categoryId = req.nextUrl.searchParams.get('genre');
      let streams = await getCachedData(dnsUrl, username, password, 'get_vod_streams', async () => {
        const response = await axios.get(`${baseUrl}&action=get_vod_streams`, { timeout: 45000 });
        return response.data;
      });
      if (!Array.isArray(streams)) streams = [];

      if (categoryId && categoryId !== 'all') {
        streams = streams.filter((s: any) => String(s.category_id) === String(categoryId));
      }

      const mappedMovies = streams.slice(0, 100).map((s: any) => ({
        id: String(s.stream_id),
        title: s.name,
        synopsis: s.plot || 'Sin sinopsis disponible',
        year: parseInt(s.year) || 2024,
        duration: parseInt(s.duration) || 120,
        rating: parseFloat(s.rating) || 7.0,
        posterUrl: s.stream_icon || '',
        backdropUrl: s.stream_icon || '',
        streamUrl: `${dnsUrl}/movie/${encodeURIComponent(username)}/${encodeURIComponent(password)}/${s.stream_id}.${s.container_extension || 'mp4'}`,
        genres: s.genre ? s.genre.split(',') : [],
        categoryId: String(s.category_id),
        quality: '1080p',
        addedAt: s.added || new Date().toISOString()
      }));

      return NextResponse.json({
        success: true,
        data: mappedMovies,
        pagination: { page: 1, limit: 100, total: streams.length, totalPages: 1, hasNext: false, hasPrev: false }
      });
    }

    // --- MOVIE DETAIL ---
    if (path.startsWith('movies/') && !path.endsWith('/categories') && !path.endsWith('/genres') && !path.endsWith('/popular') && !path.endsWith('/recent')) {
      const parts = path.split('/');
      const movieId = parts[1];

      if (movieId) {
        const info = await getCachedData(dnsUrl, username, password, `get_vod_info_${movieId}`, async () => {
          const response = await axios.get(`${baseUrl}&action=get_vod_info&vod_id=${movieId}`, { timeout: 15000 });
          return response.data;
        });

        if (info && info.info) {
          const movieInfo = info.info;
          const movieData = info.movie_data || {};

          const mappedMovieDetail = {
            id: String(movieId),
            title: movieInfo.name || 'Película',
            synopsis: movieInfo.plot || 'Sin sinopsis disponible',
            year: parseInt(movieInfo.year) || 2024,
            duration: parseInt(movieInfo.duration) || 120,
            rating: parseFloat(movieInfo.rating) || 7.0,
            posterUrl: movieInfo.movie_image || '',
            backdropUrl: movieInfo.backdrop_path?.[0] || movieInfo.movie_image || '',
            streamUrl: `${dnsUrl}/movie/${encodeURIComponent(username)}/${encodeURIComponent(password)}/${movieId}.${movieData.container_extension || 'mp4'}`,
            genres: movieInfo.genre ? movieInfo.genre.split(',') : [],
            categoryId: String(movieInfo.category_id),
            category: { id: String(movieInfo.category_id), name: 'Categoría', slug: String(movieInfo.category_id) },
            quality: '1080p',
            director: movieInfo.director || '',
            cast: movieInfo.cast ? movieInfo.cast.split(',') : [],
            addedAt: movieInfo.releasedate || new Date().toISOString()
          };

          return NextResponse.json({ success: true, data: mappedMovieDetail });
        }
      }
    }

    // --- MOVIES CATEGORIES (mapped to genres endpoint in frontend logic) ---
    if (path === 'movies/categories' || path === 'movies/genres') {
      let categories = await getCachedData(dnsUrl, username, password, 'get_vod_categories', async () => {
        const response = await axios.get(`${baseUrl}&action=get_vod_categories`, { timeout: 15000 });
        return response.data;
      });
      if (!Array.isArray(categories)) categories = [];

      const mappedCategories = categories.map((c: any) => ({
        id: String(c.category_id),
        name: c.category_name,
        slug: String(c.category_id)
      }));

      return NextResponse.json({ success: true, data: mappedCategories });
    }

    // --- SERIES ---
    if (path === 'series') {
      const categoryId = req.nextUrl.searchParams.get('genre');
      let series = await getCachedData(dnsUrl, username, password, 'get_series', async () => {
        const response = await axios.get(`${baseUrl}&action=get_series`, { timeout: 45000 });
        return response.data;
      });
      if (!Array.isArray(series)) series = [];

      if (categoryId && categoryId !== 'all') {
        series = series.filter((s: any) => String(s.category_id) === String(categoryId));
      }

      const mappedSeries = series.slice(0, 100).map((s: any) => ({
        id: String(s.series_id),
        title: s.name,
        synopsis: s.plot || 'Sin sinopsis disponible',
        year: parseInt(s.releaseDate) || 2024,
        rating: parseFloat(s.rating) || 7.0,
        posterUrl: s.cover || '',
        backdropUrl: s.cover || '',
        genres: s.genre ? s.genre.split(',') : [],
        categoryId: String(s.category_id),
        totalSeasons: 1,
        totalEpisodes: 10,
        status: 'ongoing',
        addedAt: s.last_modified || new Date().toISOString()
      }));

      return NextResponse.json({
        success: true,
        data: mappedSeries,
        pagination: { page: 1, limit: 100, total: series.length, totalPages: 1, hasNext: false, hasPrev: false }
      });
    }

    // --- SERIES CATEGORIES ---
    if (path === 'series/categories') {
      let categories = await getCachedData(dnsUrl, username, password, 'get_series_categories', async () => {
        const response = await axios.get(`${baseUrl}&action=get_series_categories`, { timeout: 15000 });
        return response.data;
      });
      if (!Array.isArray(categories)) categories = [];

      const mappedCategories = categories.map((c: any) => ({
        id: String(c.category_id),
        name: c.category_name,
        slug: String(c.category_id)
      }));

      return NextResponse.json({ success: true, data: mappedCategories });
    }

    // --- SERIES DETAIL & EPISODES ---
    if (path.startsWith('series/')) {
      const parts = path.split('/');
      const seriesId = parts[1];

      if (seriesId) {
        // Fetch series detail (seasons and episodes)
        const info = await getCachedData(dnsUrl, username, password, `get_series_info_${seriesId}`, async () => {
          const response = await axios.get(`${baseUrl}&action=get_series_info&series_id=${seriesId}`, { timeout: 15000 });
          return response.data;
        });

        if (info) {
          const seasons = Array.isArray(info.seasons) ? info.seasons : [];
          const episodesObj = info.episodes || {};

          // Map seasons
          const mappedSeasons = seasons.map((season: any) => {
            const seasonNum = parseInt(season.season_number) || 1;
            const rawEpisodes = episodesObj[String(seasonNum)] || [];
            
            const mappedEpisodes = rawEpisodes.map((ep: any) => ({
              id: String(ep.id),
              seasonId: String(seasonNum),
              seriesId: String(seriesId),
              number: parseInt(ep.episode_num) || 1,
              title: ep.title || `Episodio ${ep.episode_num}`,
              synopsis: ep.info?.plot || '',
              duration: parseInt(ep.info?.duration) || 45,
              thumbnailUrl: ep.info?.movie_image || '',
              streamUrl: `${dnsUrl}/series/${encodeURIComponent(username)}/${encodeURIComponent(password)}/${ep.id}.${ep.container_extension || 'mp4'}`
            }));

            return {
              id: String(seasonNum),
              seriesId: String(seriesId),
              number: seasonNum,
              title: season.name || `Temporada ${seasonNum}`,
              episodes: mappedEpisodes,
              episodeCount: mappedEpisodes.length
            };
          });

          const mappedSeriesDetail = {
            id: String(seriesId),
            title: info.info?.name || 'Serie',
            synopsis: info.info?.plot || '',
            posterUrl: info.info?.cover || '',
            backdropUrl: info.info?.cover || '',
            rating: parseFloat(info.info?.rating) || 7.0,
            year: parseInt(info.info?.releaseDate) || 2024,
            genres: info.info?.genre ? info.info.genre.split(',') : [],
            seasons: mappedSeasons,
            totalSeasons: mappedSeasons.length,
            totalEpisodes: seasons.reduce((acc: number, s: any) => acc + (episodesObj[String(s.season_number)]?.length || 0), 0),
            status: 'ongoing'
          };

          return NextResponse.json({ success: true, data: mappedSeriesDetail });
        }
      }
    }

    // --- SEARCH ---
    if (path === 'search') {
      const query = (req.nextUrl.searchParams.get('q') || '').toLowerCase();
      const filter = req.nextUrl.searchParams.get('filter') || 'all';

      let channels: any[] = [];
      let movies: any[] = [];
      let series: any[] = [];

      const promises = [];

      if (filter === 'all' || filter === 'channels') {
        promises.push(
          getCachedData(dnsUrl, username, password, 'get_live_streams', async () => {
            const response = await axios.get(`${baseUrl}&action=get_live_streams`, { timeout: 15000 });
            return response.data;
          })
            .then(streams => {
              if (Array.isArray(streams)) {
                const filtered = streams.filter((s: any) => s.name?.toLowerCase().includes(query)).slice(0, 30);
                channels = filtered.map((s: any) => ({
                  id: String(s.stream_id),
                  name: s.name,
                  logoUrl: s.stream_icon || '',
                  streamUrl: `${dnsUrl}/live/${encodeURIComponent(username)}/${encodeURIComponent(password)}/${s.stream_id}.m3u8`,
                  categoryId: String(s.category_id),
                  isLive: true
                }));
              }
            }).catch(err => console.error('Search channels error:', err.message))
        );
      }

      if (filter === 'all' || filter === 'movies') {
        promises.push(
          getCachedData(dnsUrl, username, password, 'get_vod_streams', async () => {
            const response = await axios.get(`${baseUrl}&action=get_vod_streams`, { timeout: 15000 });
            return response.data;
          })
            .then(streams => {
              if (Array.isArray(streams)) {
                const filtered = streams.filter((s: any) => s.name?.toLowerCase().includes(query)).slice(0, 30);
                movies = filtered.map((s: any) => ({
                  id: String(s.stream_id),
                  title: s.name,
                  synopsis: s.plot || 'Sin sinopsis disponible',
                  year: parseInt(s.year) || 2024,
                  duration: parseInt(s.duration) || 120,
                  rating: parseFloat(s.rating) || 7.0,
                  posterUrl: s.stream_icon || '',
                  backdropUrl: s.stream_icon || '',
                  streamUrl: `${dnsUrl}/movie/${encodeURIComponent(username)}/${encodeURIComponent(password)}/${s.stream_id}.${s.container_extension || 'mp4'}`,
                  genres: s.genre ? s.genre.split(',') : [],
                  categoryId: String(s.category_id),
                  quality: '1080p'
                }));
              }
            }).catch(err => console.error('Search movies error:', err.message))
        );
      }

      if (filter === 'all' || filter === 'series') {
        promises.push(
          getCachedData(dnsUrl, username, password, 'get_series', async () => {
            const response = await axios.get(`${baseUrl}&action=get_series`, { timeout: 15000 });
            return response.data;
          })
            .then(seriesData => {
              if (Array.isArray(seriesData)) {
                const filtered = seriesData.filter((s: any) => s.name?.toLowerCase().includes(query)).slice(0, 30);
                series = filtered.map((s: any) => ({
                  id: String(s.series_id),
                  title: s.name,
                  synopsis: s.plot || 'Sin sinopsis disponible',
                  year: parseInt(s.releaseDate) || 2024,
                  rating: parseFloat(s.rating) || 7.0,
                  posterUrl: s.cover || '',
                  backdropUrl: s.cover || '',
                  genres: s.genre ? s.genre.split(',') : [],
                  categoryId: String(s.category_id),
                  totalSeasons: 1,
                  totalEpisodes: 10,
                  status: 'ongoing'
                }));
              }
            }).catch(err => console.error('Search series error:', err.message))
        );
      }

      await Promise.all(promises);

      const total = channels.length + movies.length + series.length;

      return NextResponse.json({
        success: true,
        data: {
          channels,
          movies,
          series,
          total
        }
      });
    }

    // --- USER PROFILE ---
    if (path === 'auth/profile') {
      const response = await axios.get(baseUrl, { timeout: 10000 });
      const data = response.data;
      if (data && data.user_info) {
        const userInfo = data.user_info;
        const expDate = userInfo.exp_date ? new Date(parseInt(userInfo.exp_date) * 1000).toISOString() : undefined;
        return NextResponse.json({
          success: true,
          data: {
            id: username,
            username: username,
            email: `${username}@iptv.com`,
            role: 'user',
            status: 'active',
            maxDevices: parseInt(userInfo.max_connections) || 1,
            connectedDevices: parseInt(userInfo.active_cons) || 0,
            createdAt: new Date().toISOString(),
            expiresAt: expDate
          }
        });
      }
    }

    // --- MOCK FAVORITES & HISTORY (Stateless fallbacks) ---
    if (path === 'favorites') {
      return NextResponse.json({ success: true, data: [] });
    }
    if (path === 'history') {
      return NextResponse.json({ success: true, data: [] });
    }

    return NextResponse.json({ error: 'Acción de IPTV no soportada' }, { status: 404 });
  } catch (err: any) {
    console.error(`Error fetching Xtream Codes path ${path}:`, err.message);
    return NextResponse.json({ success: false, message: 'Error al conectar con el servidor IPTV' }, { status: 500 });
  }
}
