import { z } from 'zod';
import { type OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
import {
	booleanFromString,
	ApiResponseSchema,
	ErrorResponseSchema,
	SoftDeleteQueryParamsSchema,
} from '#contracts/shared';
import {
	FileSchema,
	FileMutateBodySchema,
	FileUploadBodySchema,
	FileResponseSchema,
	FileListResponseSchema,
	FileArrayResponseSchema,
	RestoreFileResponseSchema,
	FileLinkResponseSchema,
	QuotaResponseSchema,
	PresignResponseSchema,
	PresignRequestSchema,
	ConfirmFileRequestSchema,
	BatchLinkResponseSchema,
	BatchLinkRequestSchema,
} from '#contracts/file/schema';

export function registerFilePaths(registry: OpenAPIRegistry): void {
	// -------------------------------------------------------------------------
	// GET /files
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'get',
		path: '/api/v1/files',
		operationId: 'getFiles',
		tags: ['Files'],
		summary: 'Get all files',
		description:
			'Admin/system_admin: all files. Regular user: own uploads only. By default, soft-deleted records are excluded (deleted_at==null). To include soft-deleted records, omit the filters parameter or use filters=deleted_at!=null.',
		security: [{ BearerAuth: [] }],
		request: {
			query: SoftDeleteQueryParamsSchema,
		},
		responses: {
			200: {
				description: 'Files retrieved successfully',
				content: { 'application/json': { schema: FileListResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /files  (multipart/form-data)
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/files',
		operationId: 'uploadFile',
		tags: ['Files'],
		summary: 'Upload a file',
		security: [{ BearerAuth: [] }],
		request: {
			body: {
				required: true,
				content: { 'multipart/form-data': { schema: FileUploadBodySchema } },
			},
		},
		responses: {
			200: {
				description: 'File uploaded successfully',
				content: { 'application/json': { schema: FileResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			429: { description: 'Rate limit exceeded', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// GET /files/{id}
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'get',
		path: '/api/v1/files/{id}',
		operationId: 'getFileById',
		tags: ['Files'],
		summary: 'Get file by ID',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
		},
		responses: {
			200: {
				description: 'File retrieved successfully',
				content: { 'application/json': { schema: FileResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
			404: { description: 'Not Found', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// PUT /files/{id}  (multipart/form-data — optional file replacement + metadata)
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'put',
		path: '/api/v1/files/{id}',
		operationId: 'updateFile',
		tags: ['Files'],
		summary: 'Update file metadata (or replace file)',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			body: {
				content: { 'application/json': { schema: FileMutateBodySchema } },
			},
		},
		responses: {
			200: {
				description: 'File updated successfully',
				content: { 'application/json': { schema: FileResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
			404: { description: 'Not Found', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// DELETE /files/{id}
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'delete',
		path: '/api/v1/files/{id}',
		operationId: 'deleteFile',
		tags: ['Files'],
		summary: 'Delete file',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
		},
		responses: {
			200: {
				description: 'File deleted successfully',
				content: { 'application/json': { schema: ApiResponseSchema(z.null()) } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
			404: { description: 'Not Found', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /files/upload-multiple
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/files/upload-multiple',
		operationId: 'uploadMultipleFiles',
		tags: ['Files'],
		summary: 'Upload multiple files',
		description:
			'Upload up to 10 files at once. Each file undergoes magic-byte, MIME/extension, and virus scan validation.',
		security: [{ BearerAuth: [] }],
		request: {
			body: {
				required: true,
				content: {
					'multipart/form-data': {
						schema: z.object({
							files: z.array(z.string().openapi({ format: 'binary' })),
							title: z.string().max(150).optional(),
							description: z.string().max(500).optional(),
							note: z.string().max(255).optional(),
							is_library: booleanFromString().optional(),
						}),
					},
				},
			},
		},
		responses: {
			200: {
				description: 'Files uploaded successfully',
				content: { 'application/json': { schema: FileArrayResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			429: { description: 'Rate limit exceeded', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// GET /files/quota
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'get',
		path: '/api/v1/files/quota',
		operationId: 'getFileQuota',
		tags: ['Files'],
		summary: 'Get storage quota',
		description: 'Get storage quota and usage breakdown for the current user',
		security: [{ BearerAuth: [] }],
		responses: {
			200: {
				description: 'Quota retrieved successfully',
				content: { 'application/json': { schema: QuotaResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /files/presign
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/files/presign',
		operationId: 'presignFileUpload',
		tags: ['Files'],
		summary: 'Get presigned upload URL',
		description: 'Get a presigned URL for direct MinIO upload (MinIO only)',
		security: [{ BearerAuth: [] }],
		request: {
			body: {
				required: true,
				content: { 'application/json': { schema: PresignRequestSchema } },
			},
		},
		responses: {
			200: {
				description: 'Presigned URL generated',
				content: { 'application/json': { schema: PresignResponseSchema } },
			},
			400: {
				description: 'Direct upload only supported with MinIO',
				content: { 'application/json': { schema: ErrorResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /files/confirm
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/files/confirm',
		operationId: 'confirmFileUpload',
		tags: ['Files'],
		summary: 'Confirm direct upload',
		description: 'Confirm a direct MinIO upload and save metadata',
		security: [{ BearerAuth: [] }],
		request: {
			body: {
				required: true,
				content: { 'application/json': { schema: ConfirmFileRequestSchema } },
			},
		},
		responses: {
			200: {
				description: 'File confirmed successfully',
				content: { 'application/json': { schema: ApiResponseSchema(FileSchema) } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// GET /files/{id}/content
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'get',
		path: '/api/v1/files/{id}/content',
		operationId: 'getFileContent',
		tags: ['Files'],
		summary: 'Get file content (view or download)',
		description:
			'Stream the file directly or redirect to a signed URL for cloud storage. Use mode=view for preview (inline) or mode=download for download (attachment)',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			query: z.object({
				mode: z.enum(['view', 'download']).default('view').optional(),
			}),
		},
		responses: {
			200: {
				description: 'File stream or redirect',
				content: { 'application/octet-stream': { schema: z.string() } },
			},
			307: { description: 'Temporary redirect to signed URL' },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
			404: { description: 'Not Found', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// GET /files/{id}/link
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'get',
		path: '/api/v1/files/{id}/link',
		operationId: 'getFileLink',
		tags: ['Files'],
		summary: 'Get file link (view or download)',
		description:
			'Generate a signed URL for file access. Use mode=view for preview (inline) or mode=download for download (attachment)',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			query: z.object({
				mode: z.enum(['view', 'download']).default('view').optional(),
				expires: z.coerce.number().int().default(3600).optional(),
			}),
		},
		responses: {
			200: {
				description: 'File link generated',
				content: { 'application/json': { schema: FileLinkResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
			404: { description: 'Not Found', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// PUT /files/{id}/restore
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'put',
		path: '/api/v1/files/{id}/restore',
		operationId: 'restoreFile',
		tags: ['Files'],
		summary: 'Restore a soft-deleted file',
		description:
			'Restores a soft-deleted file by setting is_deleted = false. The physical file must still exist on disk/storage for it to be usable.',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
		},
		responses: {
			200: {
				description: 'File restored successfully',
				content: { 'application/json': { schema: RestoreFileResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			404: { description: 'Not Found', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /files/batch-link
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/files/batch-link',
		operationId: 'batchLink',
		tags: ['Files'],
		summary: 'Batch get file links',
		description:
			'Generate file links for up to 100 file IDs in a single request. Use mode=view for preview (inline) or mode=download for download (attachment)',
		security: [{ BearerAuth: [] }],
		request: {
			body: {
				required: true,
				content: { 'application/json': { schema: BatchLinkRequestSchema } },
			},
		},
		responses: {
			200: {
				description: 'File links resolved',
				content: { 'application/json': { schema: BatchLinkResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});
}
