/**
 * Joi validation schemas for all request bodies and query parameters.
 * All validation logic lives here — controllers invoke these schemas.
 */

import Joi from 'joi';

const SEMVER_PATTERN =
  /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;

const CAPABILITY_PATTERN = /^[a-z0-9_-]+:[a-z0-9_*-]+$/;

const AGENT_TYPES = [
  'screener',
  'classifier',
  'orchestrator',
  'extractor',
  'summarizer',
  'router',
  'monitor',
  'custom',
] as const;

const DEPLOYMENT_ENVS = ['development', 'staging', 'production'] as const;

const AGENT_STATUSES = ['active', 'suspended', 'decommissioned'] as const;

const CREDENTIAL_STATUSES = ['active', 'revoked'] as const;

const AUDIT_ACTIONS = [
  'agent.created',
  'agent.updated',
  'agent.decommissioned',
  'agent.suspended',
  'agent.reactivated',
  'token.issued',
  'token.revoked',
  'token.introspected',
  'credential.generated',
  'credential.rotated',
  'credential.revoked',
  'auth.failed',
] as const;

const AUDIT_OUTCOMES = ['success', 'failure'] as const;

const OAUTH_SCOPES = ['agents:read', 'agents:write', 'tokens:read', 'audit:read'] as const;

/** Schema for POST /agents request body. */
export const createAgentSchema = Joi.object({
  email: Joi.string().email().required(),
  agentType: Joi.string()
    .valid(...AGENT_TYPES)
    .required(),
  version: Joi.string().pattern(SEMVER_PATTERN).required(),
  capabilities: Joi.array()
    .items(Joi.string().pattern(CAPABILITY_PATTERN))
    .min(1)
    .required(),
  owner: Joi.string().min(1).max(128).required(),
  deploymentEnv: Joi.string()
    .valid(...DEPLOYMENT_ENVS)
    .required(),
});

/** Schema for PATCH /agents/:agentId request body. */
export const updateAgentSchema = Joi.object({
  agentType: Joi.string().valid(...AGENT_TYPES),
  version: Joi.string().pattern(SEMVER_PATTERN),
  capabilities: Joi.array().items(Joi.string().pattern(CAPABILITY_PATTERN)).min(1),
  owner: Joi.string().min(1).max(128),
  deploymentEnv: Joi.string().valid(...DEPLOYMENT_ENVS),
  status: Joi.string().valid(...AGENT_STATUSES),
  isPublic: Joi.boolean(),
})
  .min(1)
  .options({ allowUnknown: false });

/** Schema for GET /agents query params. */
export const listAgentsQuerySchema = Joi.object({
  page: Joi.number().integer().min(1).default(1),
  limit: Joi.number().integer().min(1).max(100).default(20),
  owner: Joi.string(),
  agentType: Joi.string().valid(...AGENT_TYPES),
  status: Joi.string().valid(...AGENT_STATUSES),
});

/** Schema for POST /token request body (form-encoded). */
export const tokenRequestSchema = Joi.object({
  grant_type: Joi.string().required(),
  client_id: Joi.string().uuid(),
  client_secret: Joi.string(),
  scope: Joi.string().pattern(
    new RegExp(
      `^(${OAUTH_SCOPES.join('|')})(\\s(${OAUTH_SCOPES.join('|')}))*$`,
    ),
  ),
});

/** Schema for POST /token/introspect request body. */
export const introspectRequestSchema = Joi.object({
  token: Joi.string().required(),
  token_type_hint: Joi.string().valid('access_token'),
});

/** Schema for POST /token/revoke request body. */
export const revokeRequestSchema = Joi.object({
  token: Joi.string().required(),
  token_type_hint: Joi.string().valid('access_token'),
});

/** Schema for POST /agents/:agentId/credentials request body. */
export const generateCredentialSchema = Joi.object({
  expiresAt: Joi.date().iso().min('now').optional(),
});

/** Schema for GET /agents/:agentId/credentials query params. */
export const listCredentialsQuerySchema = Joi.object({
  page: Joi.number().integer().min(1).default(1),
  limit: Joi.number().integer().min(1).max(100).default(20),
  status: Joi.string().valid(...CREDENTIAL_STATUSES),
});

/** Schema for GET /audit query params. */
export const auditQuerySchema = Joi.object({
  page: Joi.number().integer().min(1).default(1),
  limit: Joi.number().integer().min(1).max(200).default(50),
  agentId: Joi.string().uuid(),
  action: Joi.string().valid(...AUDIT_ACTIONS),
  outcome: Joi.string().valid(...AUDIT_OUTCOMES),
  fromDate: Joi.string().isoDate(),
  toDate: Joi.string().isoDate(),
});

/** Schema for UUID path parameters. */
export const uuidParamSchema = Joi.object({
  id: Joi.string().uuid().required(),
});

/** Schema for GET /marketplace/agents query params. */
export const marketplaceQuerySchema = Joi.object({
  page: Joi.number().integer().min(1).default(1),
  limit: Joi.number().integer().min(1).max(100).default(20),
  q: Joi.string().max(256),
  capability: Joi.string().pattern(CAPABILITY_PATTERN),
  publisher: Joi.string().max(128),
});
