import { type } from "arktype";
import { describeRoute, resolver } from "hono-openapi";
import { BACKEND_STATUS, BACKEND_TYPES, volumeConfigSchema } from "~/schemas/volumes";

export const volumeSchema = type({
	id: "number",
	name: "string",
	type: type.valueOf(BACKEND_TYPES),
	status: type.valueOf(BACKEND_STATUS),
	lastError: "string | null",
	createdAt: "number",
	updatedAt: "number",
	lastHealthCheck: "number",
	config: volumeConfigSchema,
	autoRemount: "boolean",
});

export type VolumeDto = typeof volumeSchema.infer;

/**
 * List all volumes
 */
export const listVolumesResponse = volumeSchema.array();
export type ListVolumesDto = typeof listVolumesResponse.infer;

export const listVolumesDto = describeRoute({
	description: "List all volumes",
	tags: ["Volumes"],
	operationId: "listVolumes",
	responses: {
		200: {
			description: "A list of volumes",
			content: {
				"application/json": {
					schema: resolver(listVolumesResponse),
				},
			},
		},
	},
});

/**
 * Create a new volume
 */
export const createVolumeBody = type({
	name: "string",
	config: volumeConfigSchema,
});

export const createVolumeResponse = volumeSchema;
export type CreateVolumeDto = typeof createVolumeResponse.infer;

export const createVolumeDto = describeRoute({
	description: "Create a new volume",
	operationId: "createVolume",
	tags: ["Volumes"],
	responses: {
		201: {
			description: "Volume created successfully",
			content: {
				"application/json": {
					schema: resolver(createVolumeResponse),
				},
			},
		},
	},
});

/**
 * Delete a volume
 */
export const deleteVolumeResponse = type({
	message: "string",
});
export type DeleteVolumeDto = typeof deleteVolumeResponse.infer;

export const deleteVolumeDto = describeRoute({
	description: "Delete a volume",
	operationId: "deleteVolume",
	tags: ["Volumes"],
	responses: {
		200: {
			description: "Volume deleted successfully",
			content: {
				"application/json": {
					schema: resolver(deleteVolumeResponse),
				},
			},
		},
	},
});

const statfsSchema = type({
	total: "number",
	used: "number",
	free: "number",
});

const getVolumeResponse = type({
	volume: volumeSchema,
	statfs: statfsSchema,
});

export type GetVolumeDto = typeof getVolumeResponse.infer;
/**
 * Get a volume
 */
export const getVolumeDto = describeRoute({
	description: "Get a volume by name",
	operationId: "getVolume",
	tags: ["Volumes"],
	responses: {
		200: {
			description: "Volume details",
			content: {
				"application/json": {
					schema: resolver(getVolumeResponse),
				},
			},
		},
		404: {
			description: "Volume not found",
		},
	},
});

/**
 * Update a volume
 */
export const updateVolumeBody = type({
	autoRemount: "boolean?",
	config: volumeConfigSchema.optional(),
});

export type UpdateVolumeBody = typeof updateVolumeBody.infer;

export const updateVolumeResponse = volumeSchema;
export type UpdateVolumeDto = typeof updateVolumeResponse.infer;

export const updateVolumeDto = describeRoute({
	description: "Update a volume's configuration",
	operationId: "updateVolume",
	tags: ["Volumes"],
	responses: {
		200: {
			description: "Volume updated successfully",
			content: {
				"application/json": {
					schema: resolver(updateVolumeResponse),
				},
			},
		},
		404: {
			description: "Volume not found",
		},
	},
});

/**
 * Test connection
 */
export const testConnectionBody = type({
	config: volumeConfigSchema,
});

export const testConnectionResponse = type({
	success: "boolean",
	message: "string",
});
export type TestConnectionDto = typeof testConnectionResponse.infer;

export const testConnectionDto = describeRoute({
	description: "Test connection to backend",
	operationId: "testConnection",
	tags: ["Volumes"],
	responses: {
		200: {
			description: "Connection test result",
			content: {
				"application/json": {
					schema: resolver(testConnectionResponse),
				},
			},
		},
	},
});

/**
 * Mount volume
 */
export const mountVolumeResponse = type({
	error: "string?",
	status: type.valueOf(BACKEND_STATUS),
});
export type MountVolumeDto = typeof mountVolumeResponse.infer;

export const mountVolumeDto = describeRoute({
	description: "Mount a volume",
	operationId: "mountVolume",
	tags: ["Volumes"],
	responses: {
		200: {
			description: "Volume mounted successfully",
			content: {
				"application/json": {
					schema: resolver(mountVolumeResponse),
				},
			},
		},
	},
});

/**
 * Unmount volume
 */
export const unmountVolumeResponse = type({
	error: "string?",
	status: type.valueOf(BACKEND_STATUS),
});
export type UnmountVolumeDto = typeof unmountVolumeResponse.infer;

export const unmountVolumeDto = describeRoute({
	description: "Unmount a volume",
	operationId: "unmountVolume",
	tags: ["Volumes"],
	responses: {
		200: {
			description: "Volume unmounted successfully",
			content: {
				"application/json": {
					schema: resolver(unmountVolumeResponse),
				},
			},
		},
	},
});

export const healthCheckResponse = type({
	error: "string?",
	status: type.valueOf(BACKEND_STATUS),
});
export type HealthCheckDto = typeof healthCheckResponse.infer;

export const healthCheckDto = describeRoute({
	description: "Perform a health check on a volume",
	operationId: "healthCheckVolume",
	tags: ["Volumes"],
	responses: {
		200: {
			description: "Volume health check result",
			content: {
				"application/json": {
					schema: resolver(healthCheckResponse),
				},
			},
		},
		404: {
			description: "Volume not found",
		},
	},
});

/**
 * Get containers using a volume
 */
const containerSchema = type({
	id: "string",
	name: "string",
	state: "string",
	image: "string",
});

export const listContainersResponse = containerSchema.array();
export type ListContainersDto = typeof listContainersResponse.infer;

export const getContainersDto = describeRoute({
	description: "Get containers using a volume by name",
	operationId: "getContainersUsingVolume",
	tags: ["Volumes"],
	responses: {
		200: {
			description: "List of containers using the volume",
			content: {
				"application/json": {
					schema: resolver(listContainersResponse),
				},
			},
		},
		404: {
			description: "Volume not found",
		},
	},
});

/**
 * List files in a volume
 */
const fileEntrySchema = type({
	name: "string",
	path: "string",
	type: type.enumerated("file", "directory"),
	size: "number?",
	modifiedAt: "number?",
});

export const listFilesResponse = type({
	files: fileEntrySchema.array(),
	path: "string",
});
export type ListFilesDto = typeof listFilesResponse.infer;

export const listFilesDto = describeRoute({
	description: "List files in a volume directory",
	operationId: "listFiles",
	tags: ["Volumes"],
	parameters: [
		{
			in: "query",
			name: "path",
			required: false,
			schema: {
				type: "string",
			},
			description: "Subdirectory path to list (relative to volume root)",
		},
	],
	responses: {
		200: {
			description: "List of files in the volume",
			content: {
				"application/json": {
					schema: resolver(listFilesResponse),
				},
			},
		},
	},
});

/**
 * Browse filesystem directories
 */
export const browseFilesystemResponse = type({
	directories: fileEntrySchema.array(),
	path: "string",
});
export type BrowseFilesystemDto = typeof browseFilesystemResponse.infer;

export const browseFilesystemDto = describeRoute({
	description: "Browse directories on the host filesystem",
	operationId: "browseFilesystem",
	tags: ["Volumes"],
	parameters: [
		{
			in: "query",
			name: "path",
			required: false,
			schema: {
				type: "string",
			},
			description: "Directory path to browse (absolute path, defaults to /)",
		},
	],
	responses: {
		200: {
			description: "List of directories in the specified path",
			content: {
				"application/json": {
					schema: resolver(browseFilesystemResponse),
				},
			},
		},
	},
});
