import NodeCache from 'node-cache';
import { MongoClient } from 'mongodb';
import crypto from 'crypto';
import dotenv from 'dotenv';

dotenv.config();

const cache = new NodeCache({ stdTTL: parseInt(process.env.STD_TTL || '3600') });
const mongoClient = new MongoClient(process.env.MONGODB_URI || 'mongodb://localhost:27017');
const dbName = 'pageCache';
const collectionName = 'pages';

const connectToMongo = async () => {
  await mongoClient.connect();
  return mongoClient.db(dbName);
};

const createTTLIndex = async () => {
  try {
    const db = await connectToMongo();
    await db
      .collection(collectionName)
      .createIndex(
        { updatedAt: 1 },
        { expireAfterSeconds: parseInt(process.env.EXPIRE_AFTER_SECONDS || '9000') }
      );
    console.log('TTL index created successfully');
  } catch (error) {
    console.error('Error creating TTL index:', error);
  }
};

const getPageHash = (content: string) => {
  return crypto.createHash('md5').update(content).digest('hex');
};

export const getCachedPage = async (url: string) => {
  const cachedPage = cache.get(url);
  if (cachedPage) return cachedPage;

  try {
    const db = await connectToMongo();
    const page = await db.collection(collectionName).findOne({ url });
    if (page) cache.set(url, page);
    return page;
  } catch (error) {
    console.error('Error getting cached page:', error);
    throw error;
  }
};

const savePageToCache = async (url: string, content: string) => {
  const hash = getPageHash(content);
  const page = { url, content, hash, updatedAt: new Date() };

  cache.set(url, page); // 更新内存缓存

  try {
    const db = await connectToMongo();
    await db.collection(collectionName).updateOne({ url }, { $set: page }, { upsert: true }); // 更新持久化缓存
  } catch (error) {
    console.error('Error saving page to cache:', error);
    throw error;
  }
};

export const updateCacheAsync = async (url: string, content: string) => {
  await savePageToCache(url, content);
};

process.on('SIGINT', async () => {
  await mongoClient.close();
  process.exit(0);
});

// 在应用启动时创建 TTL 索引
createTTLIndex();
