import { z } from 'zod';
import { type OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
import {
	UserCreateBodySchema,
	UserUpdateBodySchema,
	UserResponseSchema,
	UserListResponseSchema,
	RoleMutateBodySchema,
	RoleResponseSchema,
	RoleListResponseSchema,
	PermissionMutateBodySchema,
	PermissionResponseSchema,
	PermissionListResponseSchema,
	ResetPasswordResponseSchema,
	UserRoleMutateBodySchema,
	UserRoleResponseSchema,
	UserRoleListResponseSchema,
	RolePermissionBulkAssignBodySchema,
	RolePermissionListResponseSchema,
	RolePermissionArrayResponseSchema,
} from '#contracts/user/schema';
import {
	ApiResponseSchema,
	ErrorResponseSchema,
	QueryParamsSchema,
	SoftDeleteQueryParamsSchema,
} from '#contracts/shared';

export function registerUserPaths(registry: OpenAPIRegistry): void {
	// =========================================================================
	// Users
	// =========================================================================

	registry.registerPath({
		method: 'get',
		path: '/api/v1/users',
		operationId: 'getUsers',
		tags: ['Users'],
		summary: 'Get all users',
		description:
			'Retrieve paginated list of users. Admin 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: 'OK', content: { 'application/json': { schema: UserListResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	registry.registerPath({
		method: 'post',
		path: '/api/v1/users',
		operationId: 'createUser',
		tags: ['Users'],
		summary: 'Create a user',
		security: [{ BearerAuth: [] }],
		request: {
			body: { required: true, content: { 'application/json': { schema: UserCreateBodySchema } } },
		},
		responses: {
			200: { description: 'Created', content: { 'application/json': { schema: UserResponseSchema } } },
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	registry.registerPath({
		method: 'get',
		path: '/api/v1/users/{id}',
		operationId: 'getUserById',
		tags: ['Users'],
		summary: 'Get user by ID',
		description: 'Users may only access their own record; admins can access any.',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: UserResponseSchema } } },
			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 } } },
		},
	});

	registry.registerPath({
		method: 'put',
		path: '/api/v1/users/{id}',
		operationId: 'updateUser',
		tags: ['Users'],
		summary: 'Update user',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			body: { content: { 'application/json': { schema: UserUpdateBodySchema } } },
		},
		responses: {
			200: { description: 'Updated', content: { 'application/json': { schema: UserResponseSchema } } },
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			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 } } },
		},
	});

	registry.registerPath({
		method: 'delete',
		path: '/api/v1/users/{id}',
		operationId: 'deleteUser',
		tags: ['Users'],
		summary: 'Delete user',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: {
				description: 'Deleted',
				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 } } },
		},
	});

	// -------------------------------------------------------------------------
	// PUT /users/{id}/reset-password
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'put',
		path: '/api/v1/users/{id}/reset-password',
		operationId: 'adminResetUserPassword',
		tags: ['Users'],
		summary: 'Reset user password to default',
		description: 'Reset user password to default value. Admin only.',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
		},
		responses: {
			200: {
				description: 'Password reset successfully',
				content: { 'application/json': { schema: ResetPasswordResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			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 } } },
			500: {
				description: 'Default password not configured',
				content: { 'application/json': { schema: ErrorResponseSchema } },
			},
		},
	});

	// =========================================================================
	// Roles
	// =========================================================================

	registry.registerPath({
		method: 'get',
		path: '/api/v1/roles',
		operationId: 'getRoles',
		tags: ['Roles'],
		summary: 'Get all roles',
		security: [{ BearerAuth: [] }],
		request: {
			query: QueryParamsSchema,
		},
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: RoleListResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	registry.registerPath({
		method: 'post',
		path: '/api/v1/roles',
		operationId: 'createRole',
		tags: ['Roles'],
		summary: 'Create a role',
		security: [{ BearerAuth: [] }],
		request: {
			body: { required: true, content: { 'application/json': { schema: RoleMutateBodySchema } } },
		},
		responses: {
			200: { description: 'Created', content: { 'application/json': { schema: RoleResponseSchema } } },
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	registry.registerPath({
		method: 'get',
		path: '/api/v1/roles/{id}',
		operationId: 'getRoleById',
		tags: ['Roles'],
		summary: 'Get role by ID',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: RoleResponseSchema } } },
			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 } } },
		},
	});

	registry.registerPath({
		method: 'put',
		path: '/api/v1/roles/{id}',
		operationId: 'updateRole',
		tags: ['Roles'],
		summary: 'Update role',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			body: { content: { 'application/json': { schema: RoleMutateBodySchema } } },
		},
		responses: {
			200: { description: 'Updated', content: { 'application/json': { schema: RoleResponseSchema } } },
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			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 } } },
		},
	});

	registry.registerPath({
		method: 'delete',
		path: '/api/v1/roles/{id}',
		operationId: 'deleteRole',
		tags: ['Roles'],
		summary: 'Delete role',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: {
				description: 'Deleted',
				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 } } },
		},
	});

	// =========================================================================
	// Permissions
	// =========================================================================

	registry.registerPath({
		method: 'get',
		path: '/api/v1/permissions',
		operationId: 'getPermissions',
		tags: ['Permissions'],
		summary: 'Get all permissions',
		security: [{ BearerAuth: [] }],
		request: {
			query: QueryParamsSchema,
		},
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: PermissionListResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	registry.registerPath({
		method: 'post',
		path: '/api/v1/permissions',
		operationId: 'createPermission',
		tags: ['Permissions'],
		summary: 'Create a permission',
		security: [{ BearerAuth: [] }],
		request: {
			body: { required: true, content: { 'application/json': { schema: PermissionMutateBodySchema } } },
		},
		responses: {
			200: { description: 'Created', content: { 'application/json': { schema: PermissionResponseSchema } } },
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	registry.registerPath({
		method: 'get',
		path: '/api/v1/permissions/{id}',
		operationId: 'getPermissionById',
		tags: ['Permissions'],
		summary: 'Get permission by ID',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
		},
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: PermissionResponseSchema } } },
			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 } } },
		},
	});

	registry.registerPath({
		method: 'delete',
		path: '/api/v1/permissions/{id}',
		operationId: 'deletePermission',
		tags: ['Permissions'],
		summary: 'Delete permission',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: {
				description: 'Deleted',
				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 } } },
		},
	});

	// =========================================================================
	// User Roles
	// =========================================================================

	registry.registerPath({
		method: 'get',
		path: '/api/v1/user-roles',
		operationId: 'getUserRoles',
		tags: ['User Roles'],
		summary: 'Get user-role assignments',
		description: 'Retrieve a list of user-role assignments with pagination, filtering and sorting',
		security: [{ BearerAuth: [] }],
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: UserRoleListResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
			500: { description: 'Internal server error', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	registry.registerPath({
		method: 'post',
		path: '/api/v1/user-roles',
		operationId: 'assignRoleToUser',
		tags: ['User Roles'],
		summary: 'Assign a role to a user',
		description: 'Create a new user-role assignment',
		security: [{ BearerAuth: [] }],
		request: {
			body: { required: true, content: { 'application/json': { schema: UserRoleMutateBodySchema } } },
		},
		responses: {
			200: {
				description: 'Role assigned successfully',
				content: { 'application/json': { schema: UserRoleResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	registry.registerPath({
		method: 'get',
		path: '/api/v1/user-roles/{id}',
		operationId: 'getUserRoleById',
		tags: ['User Roles'],
		summary: 'Get user-role assignment by ID',
		description: 'Retrieve a single user-role assignment by its ID',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: {
				description: 'UserRole retrieved successfully',
				content: { 'application/json': { schema: UserRoleResponseSchema } },
			},
			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 } } },
		},
	});

	registry.registerPath({
		method: 'put',
		path: '/api/v1/user-roles/{id}',
		operationId: 'updateUserRoleById',
		tags: ['User Roles'],
		summary: 'Update user-role assignment by ID',
		description: 'Update a user-role assignment',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			body: { content: { 'application/json': { schema: UserRoleMutateBodySchema } } },
		},
		responses: {
			200: {
				description: 'UserRole updated successfully',
				content: { 'application/json': { schema: UserRoleResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			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 } } },
		},
	});

	registry.registerPath({
		method: 'delete',
		path: '/api/v1/user-roles/{id}',
		operationId: 'deleteUserRoleById',
		tags: ['User Roles'],
		summary: 'Delete user-role assignment by ID',
		description: 'Delete a user-role assignment (revoke role from user)',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: {
				description: 'Role revoked successfully',
				content: { 'application/json': { schema: ApiResponseSchema(z.string()) } },
			},
			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 } } },
		},
	});

	// =========================================================================
	// Role Permissions
	// =========================================================================

	registry.registerPath({
		method: 'get',
		path: '/api/v1/role-permissions',
		operationId: 'getRolePermissions',
		tags: ['Role Permissions'],
		summary: 'Get role-permission assignments',
		description: 'Retrieve a list of role-permission assignments with pagination, filtering and sorting. Admin only.',
		security: [{ BearerAuth: [] }],
		request: {
			query: QueryParamsSchema,
		},
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: RolePermissionListResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: { description: 'Forbidden', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	registry.registerPath({
		method: 'post',
		path: '/api/v1/role-permissions/{role_id}/assign',
		operationId: 'assignPermissionsToRole',
		tags: ['Role Permissions'],
		summary: 'Bulk assign permissions to a role',
		description: 'Assign multiple permissions to a role at once',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ role_id: z.uuid() }),
			body: { required: true, content: { 'application/json': { schema: RolePermissionBulkAssignBodySchema } } },
		},
		responses: {
			200: {
				description: 'Permissions assigned successfully',
				content: { 'application/json': { schema: RolePermissionArrayResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			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 } } },
		},
	});

	registry.registerPath({
		method: 'put',
		path: '/api/v1/role-permissions/{role_id}/assign',
		operationId: 'updateRolePermissions',
		tags: ['Role Permissions'],
		summary: 'Update role permissions',
		description: 'Replace all permissions of a role with a new set of permissions',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ role_id: z.uuid() }),
			body: { required: true, content: { 'application/json': { schema: RolePermissionBulkAssignBodySchema } } },
		},
		responses: {
			200: {
				description: 'Permissions updated successfully',
				content: { 'application/json': { schema: RolePermissionArrayResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			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 } } },
		},
	});
}
