import { snapshotTag } from '@agentuity/server';
import { z } from 'zod';
import { getCommand } from '../../../../command-prefix';
import { getGlobalCatalystAPIClient } from '../../../../config';
import * as tui from '../../../../tui';
import { createCommand } from '../../../../types';

const SNAPSHOT_TAG_REGEX = /^[a-zA-Z0-9_][a-zA-Z0-9._-]*$/;
const MAX_SNAPSHOT_TAG_LENGTH = 128;

const SnapshotTagResponseSchema = z.object({
	snapshotId: z.string().describe('Snapshot ID'),
	tag: z.string().nullable().optional().describe('New tag'),
});

export const tagSubcommand = createCommand({
	name: 'tag',
	description: 'Add or update a tag on a snapshot',
	tags: ['slow', 'requires-auth'],
	requires: { auth: true, org: true },
	examples: [
		{
			command: getCommand('cloud sandbox snapshot tag snp_abc123 latest'),
			description: 'Tag a snapshot as "latest"',
		},
		{
			command: getCommand('cloud sandbox snapshot tag snp_abc123 --clear'),
			description: 'Remove a tag from a snapshot',
		},
	],
	schema: {
		args: z.object({
			snapshotId: z.string().describe('Snapshot ID to tag'),
			tag: z.string().optional().describe('Tag name to apply'),
		}),
		options: z.object({
			clear: z.boolean().optional().describe('Remove the tag from the snapshot'),
		}),
		response: SnapshotTagResponseSchema,
	},

	async handler(ctx) {
		const { args, opts, options, auth, logger, orgId, config } = ctx;
		const client = await getGlobalCatalystAPIClient(
			logger,
			auth,
			config?.name,
			undefined,
			config
		);

		if (!args.tag && !opts.clear) {
			throw new Error('Either provide a tag name or use --clear to remove the tag');
		}

		if (args.tag) {
			if (args.tag.length > MAX_SNAPSHOT_TAG_LENGTH) {
				logger.fatal(
					`Invalid snapshot tag: must be at most ${MAX_SNAPSHOT_TAG_LENGTH} characters`
				);
			}
			if (!SNAPSHOT_TAG_REGEX.test(args.tag)) {
				logger.fatal(
					'Invalid snapshot tag: must only contain letters, numbers, dashes, underscores, and dots, and cannot start with a period or dash'
				);
			}
		}

		const tag = opts.clear ? null : (args.tag ?? null);

		const snapshot = await snapshotTag(client, {
			snapshotId: args.snapshotId,
			tag,
			orgId,
		});

		if (!options.json) {
			if (tag) {
				tui.success(`tagged snapshot ${tui.bold(snapshot.snapshotId)} as ${tui.bold(tag)}`);
			} else {
				tui.success(`removed tag from snapshot ${tui.bold(snapshot.snapshotId)}`);
			}
		}

		return {
			snapshotId: snapshot.snapshotId,
			tag: snapshot.tag,
		};
	},
});

export default tagSubcommand;
