import { NextResponse } from 'next/server';
import { apiError } from '@/lib/security/api-route-standards';
import { prisma } from '@/lib/core/prisma';
import {
    buildTestCaseConfigObjectKey,
    buildTestCaseFileObjectKey,
    createStoredName,
} from '@/lib/security/file-security';
import { createLogger } from '@/lib/core/logger';
import { copyObject } from '@/lib/storage/object-store-utils';
import { guardTestCaseRouteRequest } from '@/lib/security/test-case-route-access';
import { TEST_STATUS } from '@/types';

const logger = createLogger('api:test-cases:clone');

export const dynamic = 'force-dynamic';

export async function POST(
    request: Request,
    { params }: { params: Promise<{ id: string }> }
) {
    const guard = await guardTestCaseRouteRequest({
        request,
        params,
        query: {
            include: {
                files: {
                    orderBy: { createdAt: 'desc' }
                },
                configs: {
                    orderBy: { createdAt: 'asc' }
                }
            }
        }
    });
    if (!guard.ok) {
        return guard.response;
    }

    try {
        const existingTestCase = guard.testCase;

        const clonedTestCase = await prisma.testCase.create({
            data: {
                name: `${existingTestCase.name} (Copy)`,
                url: existingTestCase.url,
                prompt: existingTestCase.prompt,
                steps: existingTestCase.steps,
                browserConfig: existingTestCase.browserConfig,
                projectId: existingTestCase.projectId,
                displayId: existingTestCase.displayId,
                kind: existingTestCase.kind,
                status: TEST_STATUS.DRAFT,
            },
        });

        for (const file of existingTestCase.files) {
            const storedName = createStoredName(file.filename);
            const objectKey = buildTestCaseFileObjectKey(clonedTestCase.id, storedName);
            const copied = await copyObject({
                sourceKey: file.storedName,
                targetKey: objectKey,
                contentType: file.mimeType,
            });

            if (!copied) {
                logger.warn('clone: source test case file missing from object storage, skipping', {
                    testCaseId: existingTestCase.id,
                    fileId: file.id,
                    objectKey: file.storedName,
                });
                continue;
            }

            await prisma.testCaseFile.create({
                data: {
                    testCaseId: clonedTestCase.id,
                    filename: file.filename,
                    storedName: objectKey,
                    mimeType: file.mimeType,
                    size: file.size,
                }
            });
        }

        for (const testCaseConfig of existingTestCase.configs) {
            let value = testCaseConfig.value;

            if (testCaseConfig.type === 'FILE' && testCaseConfig.value) {
                const storedName = createStoredName(testCaseConfig.filename || testCaseConfig.name);
                const objectKey = buildTestCaseConfigObjectKey(clonedTestCase.id, storedName);
                const copied = await copyObject({
                    sourceKey: testCaseConfig.value,
                    targetKey: objectKey,
                    contentType: testCaseConfig.mimeType ?? undefined,
                });

                if (!copied) {
                    logger.warn('clone: source test case config file missing from object storage, skipping config', {
                        testCaseId: existingTestCase.id,
                        configId: testCaseConfig.id,
                        objectKey: testCaseConfig.value,
                    });
                    continue;
                }

                value = objectKey;
            }

            await prisma.testCaseConfig.create({
                data: {
                    testCaseId: clonedTestCase.id,
                    name: testCaseConfig.name,
                    type: testCaseConfig.type,
                    value,
                    masked: testCaseConfig.masked,
                    filename: testCaseConfig.filename,
                    mimeType: testCaseConfig.mimeType,
                    size: testCaseConfig.size,
                }
            });
        }

        return NextResponse.json(clonedTestCase);
    } catch (error) {
        logger.error('Failed to clone test case', error);
        return apiError({ status: 500, code: 'INTERNAL_ERROR', error: 'Failed to clone test case' });
    }
}
