import { prisma } from '../../config/database';
import { redis } from '../../config/redis';
import { siteSettingsService } from '../settings/settings.service';

export interface PublicActivityItem {
  type: 'campaign_published' | 'shift_created' | 'media_published' | 'response_approved';
  title: string;
  description: string | null;
  link: string;
  timestamp: string;
}

const CACHE_KEY = 'activity:public';
const CACHE_TTL = 300; // 5 minutes

export async function getPublicActivity(limit = 20): Promise<PublicActivityItem[]> {
  // Check cache
  try {
    const cached = await redis.get(CACHE_KEY);
    if (cached) return JSON.parse(cached);
  } catch { /* cache miss */ }

  const settings = await siteSettingsService.getPublic();
  const items: PublicActivityItem[] = [];
  const since = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); // Last 30 days

  const promises: Array<Promise<PublicActivityItem[]>> = [];

  if (settings.enableInfluence !== false) {
    promises.push(getRecentCampaigns(since, limit));
    promises.push(getRecentResponses(since, limit));
  }
  if (settings.enableMap !== false) {
    promises.push(getRecentShifts(since, limit));
  }
  if (settings.enableMediaFeatures !== false) {
    promises.push(getRecentMedia(since, limit));
  }

  const results = await Promise.allSettled(promises);
  for (const result of results) {
    if (result.status === 'fulfilled') items.push(...result.value);
  }

  // Sort by timestamp descending, limit
  items.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
  const limited = items.slice(0, limit);

  try {
    await redis.setex(CACHE_KEY, CACHE_TTL, JSON.stringify(limited));
  } catch { /* non-critical */ }

  return limited;
}

async function getRecentCampaigns(since: Date, limit: number): Promise<PublicActivityItem[]> {
  const campaigns = await prisma.campaign.findMany({
    where: { status: 'ACTIVE', createdAt: { gte: since } },
    select: { slug: true, title: true, createdAt: true },
    orderBy: { createdAt: 'desc' },
    take: limit,
  });
  return campaigns.map(c => ({
    type: 'campaign_published' as const,
    title: `New campaign: ${c.title}`,
    description: null,
    link: `/campaign/${c.slug}`,
    timestamp: c.createdAt.toISOString(),
  }));
}

async function getRecentShifts(since: Date, limit: number): Promise<PublicActivityItem[]> {
  const shifts = await prisma.shift.findMany({
    where: { status: 'OPEN', createdAt: { gte: since } },
    select: { title: true, date: true, createdAt: true },
    orderBy: { createdAt: 'desc' },
    take: limit,
  });
  return shifts.map(s => ({
    type: 'shift_created' as const,
    title: `New shift: ${s.title}`,
    description: null,
    link: '/shifts',
    timestamp: s.createdAt.toISOString(),
  }));
}

async function getRecentMedia(since: Date, limit: number): Promise<PublicActivityItem[]> {
  try {
    const videos = await prisma.video.findMany({
      where: { isPublished: true, publishedAt: { gte: since } },
      select: { id: true, title: true, publishedAt: true },
      orderBy: { publishedAt: 'desc' },
      take: limit,
    });
    return videos.map((v: { id: number; title: string | null; publishedAt: Date | null }) => ({
      type: 'media_published' as const,
      title: `New video: ${v.title ?? 'Untitled'}`,
      description: null,
      link: `/gallery/watch/${v.id}`,
      timestamp: (v.publishedAt ?? new Date()).toISOString(),
    }));
  } catch {
    return [];
  }
}

async function getRecentResponses(since: Date, limit: number): Promise<PublicActivityItem[]> {
  const responses = await prisma.representativeResponse.findMany({
    where: { status: 'APPROVED', createdAt: { gte: since } },
    select: {
      id: true,
      createdAt: true,
      campaign: { select: { slug: true, title: true } },
    },
    orderBy: { createdAt: 'desc' },
    take: limit,
  });
  return responses.map((r: { id: string; createdAt: Date; campaign: { slug: string; title: string } }) => ({
    type: 'response_approved' as const,
    title: `New response on "${r.campaign.title}"`,
    description: null,
    link: `/campaign/${r.campaign.slug}/responses`,
    timestamp: r.createdAt.toISOString(),
  }));
}
