import fp from 'fastify-plugin';
import { fetchRecentVideos, fetchAllVideos, getUploadsPlaylistId } from './api.js';
import bots from '../../config/bots.js';
import { CATEGORY_IDS } from '../../config/index.js';

const YOUTUBE_CATEGORY_ID = CATEGORY_IDS.YOUTUBE;
const PLAYLIST_CACHE_PREFIX = 'yt_uploads:';

async function youtubeBotPlugin(fastify, opts) {
  /**
   * uploads playlist ID 조회 (Redis 캐싱)
   */
  async function getCachedUploadsPlaylistId(channelId) {
    const cacheKey = `${PLAYLIST_CACHE_PREFIX}${channelId}`;

    // Redis 캐시 확인
    const cached = await fastify.redis.get(cacheKey);
    if (cached) {
      return cached;
    }

    // API 호출 후 캐싱 (영구 저장 - 값이 변하지 않음)
    const playlistId = await getUploadsPlaylistId(channelId);
    await fastify.redis.set(cacheKey, playlistId);

    return playlistId;
  }

  /**
   * 멤버 이름 맵 조회
   */
  async function getMemberNameMap() {
    const [rows] = await fastify.db.query('SELECT id, name FROM members');
    const map = {};
    for (const r of rows) {
      map[r.name] = r.id;
    }
    return map;
  }

  /**
   * description에서 멤버 추출
   */
  function extractMemberIds(description, memberNameMap) {
    if (!description) return [];
    const ids = [];
    for (const [name, id] of Object.entries(memberNameMap)) {
      if (description.includes(name)) {
        ids.push(id);
      }
    }
    return ids;
  }

  /**
   * 영상을 DB에 저장
   */
  async function saveVideo(video, bot) {
    // 중복 체크 (video_id로)
    const [existing] = await fastify.db.query(
      'SELECT id FROM schedule_youtube WHERE video_id = ?',
      [video.videoId]
    );
    if (existing.length > 0) {
      return null;
    }

    // 커스텀 설정 적용
    if (bot.titleFilter && !video.title.includes(bot.titleFilter)) {
      return null;
    }

    // schedules 테이블에 저장
    const [result] = await fastify.db.query(
      'INSERT INTO schedules (category_id, title, date, time) VALUES (?, ?, ?, ?)',
      [YOUTUBE_CATEGORY_ID, video.title, video.date, video.time]
    );
    const scheduleId = result.insertId;

    // schedule_youtube 테이블에 저장
    await fastify.db.query(
      'INSERT INTO schedule_youtube (schedule_id, video_id, video_type, channel_id, channel_name) VALUES (?, ?, ?, ?, ?)',
      [scheduleId, video.videoId, video.videoType, video.channelId, bot.channelName]
    );

    // 멤버 연결 (커스텀 설정)
    if (bot.defaultMemberId || bot.extractMembersFromDesc) {
      const memberIds = [];
      if (bot.defaultMemberId) {
        memberIds.push(bot.defaultMemberId);
      }
      if (bot.extractMembersFromDesc) {
        const nameMap = await getMemberNameMap();
        memberIds.push(...extractMemberIds(video.description, nameMap));
      }
      if (memberIds.length > 0) {
        const uniqueIds = [...new Set(memberIds)];
        const values = uniqueIds.map(id => [scheduleId, id]);
        await fastify.db.query(
          'INSERT INTO schedule_members (schedule_id, member_id) VALUES ?',
          [values]
        );
      }
    }

    return scheduleId;
  }

  /**
   * 최근 영상 동기화 (정기 실행)
   */
  async function syncNewVideos(bot) {
    const uploadsPlaylistId = await getCachedUploadsPlaylistId(bot.channelId);
    const videos = await fetchRecentVideos(bot.channelId, 10, uploadsPlaylistId);
    let addedCount = 0;

    for (const video of videos) {
      const scheduleId = await saveVideo(video, bot);
      if (scheduleId) {
        addedCount++;
      }
    }

    return { addedCount, total: videos.length };
  }

  /**
   * 전체 영상 동기화 (초기화)
   */
  async function syncAllVideos(bot) {
    const uploadsPlaylistId = await getCachedUploadsPlaylistId(bot.channelId);
    const videos = await fetchAllVideos(bot.channelId, uploadsPlaylistId);
    let addedCount = 0;

    for (const video of videos) {
      const scheduleId = await saveVideo(video, bot);
      if (scheduleId) {
        addedCount++;
      }
    }

    return { addedCount, total: videos.length };
  }

  /**
   * 관리 중인 채널 ID 목록
   */
  function getManagedChannelIds() {
    return bots
      .filter(b => b.type === 'youtube')
      .map(b => b.channelId);
  }

  fastify.decorate('youtubeBot', {
    syncNewVideos,
    syncAllVideos,
    getManagedChannelIds,
  });
}

export default fp(youtubeBotPlugin, {
  name: 'youtubeBot',
  dependencies: ['db', 'redis'],
});
