import { json } from '@/lib/json';
import { getFileUrl } from '@/lib/minio';
import { prisma } from '@/lib/prisma'; // 你的 Prisma 客户端实例
import { NextResponse } from 'next/server';

export async function GET(req: Request) {
  const { searchParams } = new URL(req.url);
  const q = (searchParams.get('q') || '').trim();
  const page = Math.max(1, Number(searchParams.get('page') || 1));
  const limit = Math.min(50, Math.max(1, Number(searchParams.get('limit') || 20)));
  const offset = (page - 1) * limit;

  if (!q) {
    return NextResponse.json({ results: [], total: 0 });
  }

  try {
    // 核心查询：Postgres 中文全文检索（视频转写 + 视频desc + 图文desc）+ 相关度排序 + 摘要高亮
    // 说明：
    // - 合并搜索来源：VideoTranscript.transcript_zh_tsv、Video.desc 与 ImagePost.desc
    // - 使用 UNION ALL 合并视频和图文的搜索结果
    // - rank 取两者匹配得分的最大值，snippet 优先展示转写匹配，否则展示 desc 匹配
    const rows = await prisma.$queryRaw<
      {
        id: string;
        awemeId: string;
        type: 'video' | 'image';
        rank: number;
        snippet: string;
      }[]
    >`
      WITH tsq AS (
        SELECT websearch_to_tsquery('zhcfg', ${q}) AS query
      )
      -- 视频搜索结果
      SELECT
        COALESCE(vt.id, 'desc:' || v.aweme_id) AS id,
        v.aweme_id AS "awemeId",
        'video'::text AS type,
        GREATEST(
          COALESCE(ts_rank(vt.transcript_zh_tsv, tsq.query), 0),
          COALESCE(ts_rank(to_tsvector('zhcfg', v.desc), tsq.query), 0)
        ) AS rank,
        CASE
          WHEN vt.transcript_zh_tsv @@ tsq.query THEN
            ts_headline(
              'zhcfg',
              array_to_string(vt.transcript, ' '),
              tsq.query,
              'StartSel=<mark>,StopSel=</mark>,MaxFragments=2,MinWords=2,MaxWords=20'
            )
          ELSE
            ts_headline(
              'zhcfg',
              v.desc,
              tsq.query,
              'StartSel=<mark>,StopSel=</mark>,MaxFragments=2,MinWords=2,MaxWords=20'
            )
        END AS snippet
      FROM "Video" v
      LEFT JOIN "VideoTranscript" vt ON vt."videoId" = v.aweme_id,
           tsq
      WHERE
        (vt.transcript_zh_tsv @@ tsq.query OR to_tsvector('zhcfg', v.desc) @@ tsq.query)
      
      UNION ALL
      
      -- 图文搜索结果
      SELECT
        'img_desc:' || ip.aweme_id AS id,
        ip.aweme_id AS "awemeId",
        'image'::text AS type,
        ts_rank(to_tsvector('zhcfg', ip.desc), tsq.query) AS rank,
        ts_headline(
          'zhcfg',
          ip.desc,
          tsq.query,
          'StartSel=<mark>,StopSel=</mark>,MaxFragments=2,MinWords=2,MaxWords=20'
        ) AS snippet
      FROM "ImagePost" ip, tsq
      WHERE to_tsvector('zhcfg', ip.desc) @@ tsq.query
      
      ORDER BY rank DESC
      OFFSET ${offset}
      LIMIT ${limit};
    `;

    // 查询总数（参数化，避免注入）
    const totalRows = await prisma.$queryRaw<{
      count: number;
    }[]>`
      WITH tsq AS (
        SELECT websearch_to_tsquery('zhcfg', ${q}) AS query
      )
      SELECT (
        (SELECT COUNT(*)::int FROM "Video" v
         LEFT JOIN "VideoTranscript" vt ON vt."videoId" = v.aweme_id
         WHERE (vt.transcript_zh_tsv @@ tsq.query OR to_tsvector('zhcfg', v.desc) @@ tsq.query))
        +
        (SELECT COUNT(*)::int FROM "ImagePost" ip
         WHERE to_tsvector('zhcfg', ip.desc) @@ tsq.query)
      ) AS count
      FROM tsq;
    `;

    // 分离视频和图文ID
    const videoIds = rows.filter(r => r.type === 'video').map(r => r.awemeId);
    const imagePostIds = rows.filter(r => r.type === 'image').map(r => r.awemeId);

    // 批量查询视频元信息
    const videos = videoIds.length > 0 ? (await prisma.video.findMany({
      where: { aweme_id: { in: videoIds } },
      select: {
        aweme_id: true,
        desc: true,
        cover_url: true,
        video_url: true,
        duration_ms: true,
        author: true
      },
    })).map(v => (
      { ...v, cover_url: getFileUrl(v.cover_url || ''), 
        author: { ...v.author, avatar_url: getFileUrl(v.author.avatar_url || '') },
        video_url: getFileUrl(v.video_url || '') })
    ) : [];

    // 批量查询图文元信息
    const imagePosts = imagePostIds.length > 0 ? (await prisma.imagePost.findMany({
      where: { aweme_id: { in: imagePostIds } },
      select: {
        aweme_id: true,
        desc: true,
        author: true,
        images: {
          orderBy: { order: 'asc' },
          take: 1,
          select: {
            url: true,
            width: true,
            height: true,
          }
        }
      },
    })).map(ip => ({
      ...ip,
      author: { ...ip.author, avatar_url: getFileUrl(ip.author.avatar_url || '') },
      cover_url: ip.images[0] ? getFileUrl(ip.images[0].url) : null,
    })) : [];

    return json({
      results: rows.map(r => ({
        ...r,
        video: r.type === 'video' ? videos.find(v => v.aweme_id === r.awemeId) : undefined,
        imagePost: r.type === 'image' ? imagePosts.find(ip => ip.aweme_id === r.awemeId) : undefined,
      })),
      total: totalRows?.[0]?.count ?? 0,
      page,
      limit,
    });
  } catch (err) {
    console.error('Search error:', err);
    return NextResponse.json({ error: 'Search failed' }, { status: 500 });
  }
}
