import { NextRequest, NextResponse } from 'next/server';
import { getSession } from '@/lib/auth';
import { dbHelpers } from '@/lib/db';
import { needsLegacyConvert } from '@/lib/platform-run';
import { prepareSourceUpload } from '@/lib/prepare-source-upload';
import { resolveVcsAccessToken } from '@/lib/vcs-token';

async function authorize(request: NextRequest, projectId: string) {
  const session = await getSession(request.cookies.get('scriba.access_token')?.value);
  if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  const project = await dbHelpers.getProject(projectId);
  if (!project) return NextResponse.json({ error: 'Conversion not found' }, { status: 404 });
  if (project.userId !== session.user.id) return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
  return { session, project };
}

export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  const { id } = await params;
  const auth = await authorize(request, id);
  if (auth instanceof NextResponse) return auth;

  const { session, project } = auth;
  const cfg = (project.config ?? {}) as Record<string, unknown>;

  if (needsLegacyConvert(cfg, project as { repoUrl?: string; sourcePath?: string })) {
    return NextResponse.json(
      { error: 'This project requires the legacy conversion path (dependency mapping, plugin overrides, or engine-local source path).' },
      { status: 422 },
    );
  }

  let body: { force?: boolean } = {};
  try {
    body = await request.json();
  } catch {
    /* empty body ok */
  }

  const repoUrl = project.repoUrl ?? '';
  const ref = typeof cfg.branch === 'string' && cfg.branch.trim() ? cfg.branch.trim() : undefined;
  const existingUploadId = typeof cfg.uploadId === 'string' ? cfg.uploadId.trim() : undefined;
  const includePatterns =
    typeof cfg.includePatterns === 'string' && cfg.includePatterns.trim().length > 0
      ? cfg.includePatterns.trim()
      : undefined;
  const excludePatterns =
    typeof cfg.excludePatterns === 'string' && cfg.excludePatterns.trim().length > 0
      ? cfg.excludePatterns.trim()
      : undefined;

  if (!repoUrl && !existingUploadId) {
    return NextResponse.json({ error: 'Connect a repository or upload a source bundle first' }, { status: 422 });
  }

  try {
    const accessToken = repoUrl ? await resolveVcsAccessToken(session.user.id, repoUrl) : undefined;
    const result = await prepareSourceUpload({
      repoUrl: repoUrl || undefined,
      ref,
      accessToken,
      uploadId: existingUploadId,
      force: body.force === true,
      includePatterns,
      excludePatterns,
    });

    if (!result.reused) {
      await dbHelpers.updateProjectProgress(id, {
        config: {
          ...cfg,
          uploadId: result.uploadId,
          uploadMeta: {
            fileCount: result.fileCount,
            totalBytes: result.totalBytes,
            preparedAt: new Date().toISOString(),
          },
        },
      });
    }

    return NextResponse.json({
      uploadId: result.uploadId,
      fileCount: result.fileCount,
      totalBytes: result.totalBytes,
      reused: result.reused,
    });
  } catch (err) {
    const msg = err instanceof Error ? err.message : 'Failed to prepare upload';
    return NextResponse.json({ error: msg }, { status: 500 });
  }
}
