// Native fetch available in Node 20+
import { getDb } from '../database/database';
import { getTimezone, formatLocalDateTime } from '../utils/time';

export interface RankingItem {
  keyword: string;
  searchCount: number;
  updatedAt: string;
  rating?: number;
}

export interface CategorizedRanking {
  category: string;
  label: string;
  hot: RankingItem[];
  newest: RankingItem[];
}

export interface CategorizedResponse {
  fetchedAt: string;
  categories: CategorizedRanking[];
}

// ===== Bilibili PGC 排行榜配置 =====
interface BiliPgcDef {
  category: string;
  label: string;
  season_type: number;  // 1=番剧, 2=电影, 3=纪录片, 4=国创, 5=电视剧, 7=综艺
}

const BILI_PGC_CATEGORIES: BiliPgcDef[] = [
  // 国创：凡人修仙传、灵笼、斗破苍穹等官方国产动画
  { category: 'donghua', label: '国产动漫', season_type: 4 },
  // 番剧：日漫等全球动画
  { category: 'global_anime', label: '热门动漫', season_type: 1 },
];

// ===== 百度热搜榜配置 =====
interface BaiduBoardDef {
  category: string;
  label: string;
  tab: string;  // movie=电影热搜, teleplay=电视剧热搜
}

const BAIDU_BOARDS: BaiduBoardDef[] = [
  // 百度电影热搜：实时反映国内电影热度
  { category: 'movie', label: '国内电影', tab: 'movie' },
  // 百度电视剧热搜：国内剧集热度
  { category: 'tv', label: '热门剧集', tab: 'teleplay' },
];

// ===== TMDB 分类配置（保留欧美和冷门内容）=====
interface TmdbCategoryDef {
  category: string;
  label: string;
  hotUrl: string;
  newestUrl: string;
}

const TMDB_CATEGORIES: TmdbCategoryDef[] = [
  {
    category: 'western_movie', label: '欧美电影',
    hotUrl: 'https://api.themoviedb.org/3/discover/movie?with_origin_country=US&sort_by=vote_average.desc&vote_count.gte=10',
    newestUrl: 'https://api.themoviedb.org/3/discover/movie?with_origin_country=US&sort_by=release_date.desc&vote_count.gte=1',
  },
  {
    category: 'western_tv', label: '欧美剧集',
    hotUrl: 'https://api.themoviedb.org/3/discover/tv?with_origin_country=US&sort_by=vote_average.desc&vote_count.gte=10',
    newestUrl: 'https://api.themoviedb.org/3/discover/tv?with_origin_country=US&sort_by=first_air_date.desc&vote_count.gte=10',
  },
  {
    category: 'niche', label: '冷门佳片',
    hotUrl: 'https://api.themoviedb.org/3/discover/movie?sort_by=vote_average.desc&vote_count.gte=10&vote_count.lte=500',
    newestUrl: 'https://api.themoviedb.org/3/discover/movie?sort_by=release_date.desc&vote_count.gte=1&vote_count.lte=500',
  },
];

// ===== 显示顺序 =====
const CATEGORY_ORDER: Record<string, number> = {
  donghua: 1,
  movie: 2,
  tv: 3,
  global_anime: 4,
  western_movie: 5,
  western_tv: 6,
  niche: 7,
  hotsite: 8,
};

// ===== 12小时缓存 =====
let cache: { data: CategorizedResponse; time: number } | null = null;
const CACHE_TTL = 12 * 60 * 60 * 1000;

function isCacheValid(): boolean {
  return cache !== null && (Date.now() - cache.time) < CACHE_TTL;
}

// ===== Bilibili PGC API =====

/**
 * 抓取 Bilibili PGC 排行榜（番剧/国创）
 */
async function fetchFromBiliPgc(season_type: number): Promise<RankingItem[]> {
  try {
    const url = `https://api.bilibili.com/pgc/web/rank/list?season_type=${season_type}&day=7`;
    const resp = await fetch(url, {
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Referer': 'https://www.bilibili.com/',
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.9',
      },
      signal: AbortSignal.timeout(8000),
    });
    if (!resp.ok) {
      console.error(`[BiliPGC] HTTP ${resp.status} for season_type=${season_type}`);
      return [];
    }
    const json = await resp.json() as any;
    if (json.code !== 0 || !json.result?.list) {
      console.error(`[BiliPGC] API error code=${json.code} for season_type=${season_type}`);
      return [];
    }
    return json.result.list.slice(0, 20).map((item: any) => {
      const stat = item.stat || {};
      const viewCount = stat.view || 0;
      const followCount = stat.follow || 0;
      const searchCount = viewCount > 0 ? viewCount : followCount;

      let rating = 0;
      if (item.rating) {
        const m = String(item.rating).match(/([\d.]+)/);
        if (m) rating = parseFloat(m[1]);
      }

      return {
        keyword: item.title || '',
        searchCount,
        updatedAt: item.new_ep?.index_show || item.new_ep?.cover || '',
        rating,
      };
    });
  } catch (err) {
    console.error(`[BiliPGC] Fetch error for season_type=${season_type}:`, (err as Error).message);
    return [];
  }
}

// ===== 百度热搜榜 API =====

/**
 * 抓取百度热搜榜
 * tab: movie=电影, teleplay=电视剧
 */
async function fetchFromBaidu(tab: string): Promise<RankingItem[]> {
  try {
    const url = `https://top.baidu.com/api/board?tab=${tab}`;
    const resp = await fetch(url, {
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Referer': 'https://top.baidu.com/board',
      },
      signal: AbortSignal.timeout(8000),
    });
    if (!resp.ok) {
      console.error(`[Baidu] HTTP ${resp.status} for tab=${tab}`);
      return [];
    }
    const json = await resp.json() as any;
    if (!json.success || !json.data?.cards) {
      console.error(`[Baidu] API error for tab=${tab}`);
      return [];
    }

    const results: RankingItem[] = [];
    for (const card of json.data.cards) {
      for (const item of (card.content || [])) {
        results.push({
          keyword: item.word || '',
          // hotScore can be like "96438", parse as number
          searchCount: parseInt(item.hotScore || '0', 10) || 0,
          updatedAt: item.desc || '',
          rating: 0,
        });
      }
    }

    return results.slice(0, 20);
  } catch (err) {
    console.error(`[Baidu] Fetch error for tab=${tab}:`, (err as Error).message);
    return [];
  }
}

// ===== TMDB =====

function getTmdbToken(): string {
  const db = getDb();
  return (db.prepare('SELECT value FROM system_configs WHERE key = ?').get('tmdb_api_token') as any)?.value || '';
}

function tmdbResultToRanking(item: any): RankingItem {
  const title = item.title || item.name || '';
  const date = item.release_date || item.first_air_date || '';
  const rating = item.vote_average ? Math.round(item.vote_average * 10) / 10 : 0;
  return {
    keyword: title,
    searchCount: item.vote_count || 0,
    updatedAt: date,
    rating,
  };
}

async function tmdbFetch(url: string, token: string): Promise<any[]> {
  const fullUrl = `${url}${url.includes('?') ? '&' : '?'}language=zh-CN`;
  try {
    const resp = await fetch(fullUrl, {
      headers: { 'Authorization': `Bearer ${token}` },
      signal: AbortSignal.timeout(10000),
    });
    if (!resp.ok) {
      console.error(`[TMDB] HTTP ${resp.status} for ${url}`);
      return [];
    }
    const data = await resp.json() as any;
    return (data.results || []).slice(0, 20);
  } catch (err) {
    console.error(`[TMDB] Fetch error for ${url}:`, err);
    return [];
  }
}

// ===== 主流程 =====

async function fetchRankings(): Promise<CategorizedResponse> {
  const fetchedAt = formatLocalDateTime();

  // 1. 并行抓取 Bilibili PGC 数据（国漫、番剧）
  const biliPromises = BILI_PGC_CATEGORIES.map(async (cat) => {
    const results = await fetchFromBiliPgc(cat.season_type);
    const mid = Math.ceil(results.length / 2);
    return {
      category: cat.category,
      label: cat.label,
      hot: results.slice(0, mid),
      newest: results.slice(mid),
    };
  });

  // 2. 并行抓取百度热搜数据（电影、电视剧）
  // 百度只有热榜没有最新榜，全部放 hot
  const baiduPromises = BAIDU_BOARDS.map(async (board) => {
    const results = await fetchFromBaidu(board.tab);
    return {
      category: board.category,
      label: board.label,
      hot: results,
      newest: [],
    };
  });

  // 3. 并行抓取 TMDB 数据（欧美观影、剧集、冷门）
  const token = getTmdbToken();
  let tmdbResults: CategorizedRanking[] = [];
  if (token) {
    const tmdbPromises = TMDB_CATEGORIES.map(async (cat) => {
      const [hotResults, newestResults] = await Promise.all([
        tmdbFetch(cat.hotUrl, token),
        tmdbFetch(cat.newestUrl, token),
      ]);
      return {
        category: cat.category,
        label: cat.label,
        hot: hotResults.map(tmdbResultToRanking),
        newest: newestResults.map(tmdbResultToRanking),
      };
    });
    tmdbResults = await Promise.all(tmdbPromises);
  }

  // 4. 本站热搜
  const db = getDb();
  const rows = db.prepare(
    'SELECT keyword, search_count as searchCount, updated_at as updatedAt FROM hot_keywords ORDER BY search_count DESC LIMIT 20'
  ).all() as RankingItem[];
  const newestRows = db.prepare(
    'SELECT keyword, search_count as searchCount, updated_at as updatedAt FROM hot_keywords ORDER BY updated_at DESC LIMIT 20'
  ).all() as RankingItem[];

  const hotsiteCategory: CategorizedRanking = {
    category: 'hotsite',
    label: '本站热搜',
    hot: rows,
    newest: newestRows,
  };

  // 5. 合并所有结果
  const [biliResults, baiduResults] = await Promise.all([
    Promise.all(biliPromises),
    Promise.all(baiduPromises),
  ]);
  const allCategories = [...biliResults, ...baiduResults, ...tmdbResults, hotsiteCategory];

  // 按 CATEGORY_ORDER 排序
  allCategories.sort((a, b) => (CATEGORY_ORDER[a.category] || 99) - (CATEGORY_ORDER[b.category] || 99));

  return { fetchedAt, categories: allCategories };
}

export async function getCategorizedRankings(): Promise<CategorizedResponse> {
  if (isCacheValid()) {
    return cache!.data;
  }

  try {
    const data = await fetchRankings();
    cache = { data, time: Date.now() };
    return data;
  } catch (err) {
    console.error('[Rankings] Fetch error:', err);
    if (cache) return cache.data;
    const db = getDb();
    const rows = db.prepare(
      'SELECT keyword, search_count as searchCount, updated_at as updatedAt FROM hot_keywords ORDER BY search_count DESC LIMIT 20'
    ).all() as RankingItem[];
    return {
      fetchedAt: formatLocalDateTime(),
      categories: [{
        category: 'hotsite', label: '本站热搜',
        hot: rows,
        newest: [...rows].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)).slice(0, 20),
      }],
    };
  }
}

export async function getRankings(): Promise<RankingItem[]> {
  const db = getDb();
  const rows = db.prepare(
    'SELECT keyword, search_count as searchCount, updated_at as updatedAt FROM hot_keywords ORDER BY search_count DESC LIMIT 20'
  ).all() as RankingItem[];
  return rows;
}

export async function getHotKeywords(): Promise<string[]> {
  const db = getDb();
  const rows = db.prepare(
    'SELECT keyword FROM hot_keywords ORDER BY search_count DESC LIMIT 20'
  ).all() as { keyword: string }[];
  return rows.map(r => r.keyword);
}
