import { NextResponse } from 'next/server';
import { db, likes, posts, users } from '@/db';
import { and, desc, eq, inArray, lt, not, or, isNotNull } from 'drizzle-orm';
import { discoverNode } from '@/lib/swarm/discovery';
import { getRemoteBaseUrl, mapRemoteProfilePost } from '@/lib/swarm/remote-profile-posts';
import { isSwarmNode } from '@/lib/swarm/interactions';
import { getViewerSwarmRepostedPostIds } from '@/lib/swarm/reposts';
import { resolveUserHandle } from '@/lib/swarm/user-handle';

const embeddedPostRelations = {
  author: true,
  bot: true,
  media: true,
  replyTo: {
    with: {
      author: true,
      bot: true,
      media: true,
    },
  },
} as const;

const replyRelations = {
  ...embeddedPostRelations,
  repostOf: {
    with: embeddedPostRelations,
  },
} as const;

type RouteContext = { params: Promise<{ handle: string }> };

export async function GET(request: Request, context: RouteContext) {
  try {
    const { handle } = await context.params;
    const resolvedHandle = resolveUserHandle(handle);
    const cleanHandle = resolvedHandle.canonicalHandle;
    const { searchParams } = new URL(request.url);
    const limit = Math.min(parseInt(searchParams.get('limit') || '25'), 50);
    const cursor = searchParams.get('cursor');
    const remote = resolvedHandle.remote;

    const fetchRemoteReplies = async () => {
      if (!remote) {
        return NextResponse.json({ posts: [], nextCursor: null });
      }

      const baseUrl = getRemoteBaseUrl(remote.domain);
      const res = await fetch(`${baseUrl}/api/users/${remote.handle}/replies?limit=${limit}`, {
        headers: { Accept: 'application/json' },
        signal: AbortSignal.timeout(10000),
      });

      if (!res.ok) {
        return NextResponse.json({ posts: [], nextCursor: null });
      }

      const data = await res.json();
      const { getSession } = await import('@/lib/auth');
      const session = await getSession();
      const viewer = session?.user;
      const mappedPosts = (data.posts || []).map((post: any) => mapRemoteProfilePost(post, remote.domain));
      const repostedIds = viewer
        ? await getViewerSwarmRepostedPostIds(
            mappedPosts.map((post: any) => ({
              id: post.id,
              nodeDomain: remote.domain,
              originalPostId: post.originalPostId || post.id.split(':').pop(),
            })),
            viewer.id
          )
        : new Set<string>();
      return NextResponse.json({
        posts: mappedPosts.map((post: any) => ({
          ...post,
          isReposted: repostedIds.has(post.id),
        })),
        nextCursor: null,
      });
    };

    if (!db) {
      if (!remote) {
        return NextResponse.json({ posts: [], nextCursor: null });
      }

      let swarm = await isSwarmNode(remote.domain);
      if (!swarm) {
        const discovery = await discoverNode(remote.domain);
        swarm = discovery.success;
      }

      if (!swarm) {
        return NextResponse.json({ posts: [], nextCursor: null });
      }

      return await fetchRemoteReplies();
    }

    const user = await db.query.users.findFirst({
      where: { handle: cleanHandle },
    });
    const isRemotePlaceholder = Boolean(user && remote);

    if (!user || isRemotePlaceholder) {
      if (!remote) {
        return NextResponse.json({ error: 'User not found' }, { status: 404 });
      }

      let swarm = await isSwarmNode(remote.domain);
      if (!swarm) {
        const discovery = await discoverNode(remote.domain);
        swarm = discovery.success;
      }

      if (!swarm) {
        return NextResponse.json({ posts: [], nextCursor: null });
      }

      return await fetchRemoteReplies();
    }

    if (user.isSuspended) {
      return NextResponse.json({ error: 'User not found' }, { status: 404 });
    }

    let cursorDate: Date | undefined;

    if (cursor) {
      const cursorPost = await db.query.posts.findFirst({
        where: { id: cursor },
      });
      if (cursorPost) {
        cursorDate = cursorPost.createdAt;
      }
    }

    let replyPosts: any[] = await db.query.posts.findMany({
      where: {
        userId: user.id,
        isRemoved: false,
        OR: [
          { replyToId: { isNotNull: true } },
          { swarmReplyToId: { isNotNull: true } },
        ],
        ...(cursorDate ? { createdAt: { lt: cursorDate } } : {}),
      },
      with: replyRelations,
      orderBy: (posts, { desc }) => [desc(posts.createdAt)],
      limit,
    });

    try {
      const { getSession } = await import('@/lib/auth');
      const session = await getSession();

      if (session?.user && replyPosts.length > 0) {
        const viewer = session.user;
        const postIds = replyPosts.map((post) => post.id).filter(Boolean);

        const viewerLikes = postIds.length > 0
          ? await db.query.likes.findMany({
              where: { AND: [{ userId: viewer.id }, { postId: { in: postIds } }] },
            })
          : [];
        const likedPostIds = new Set(viewerLikes.map((like) => like.postId));

        const viewerReposts = postIds.length > 0
          ? await db.query.posts.findMany({
              where: { AND: [{ userId: viewer.id }, { repostOfId: { in: postIds } }, { isRemoved: false }] },
            })
          : [];
        const repostedPostIds = new Set(viewerReposts.map((post) => post.repostOfId));

        replyPosts = replyPosts.map((post) => ({
          ...post,
          isLiked: likedPostIds.has(post.id),
          isReposted: repostedPostIds.has(post.id),
        }));
      }
    } catch {
    }

    return NextResponse.json({
      posts: replyPosts,
      nextCursor: replyPosts.length === limit ? replyPosts[replyPosts.length - 1]?.id : null,
    });
  } catch (error) {
    console.error('Get user replies error:', error);
    return NextResponse.json({ error: 'Failed to get replies' }, { status: 500 });
  }
}
