import {type BlueprintError, validateResource} from '../index.js'

/**
 * Validates that the given resource is a valid Robot.
 * @param resource The Robot resource
 * @returns A list of validation errors
 */
export function validateRobot(resource: unknown): BlueprintError[] {
  if (!resource) return [{type: 'invalid_value', message: 'Robot config must be provided'}]
  if (typeof resource !== 'object') return [{type: 'invalid_type', message: 'Robot config must be an object'}]

  const errors: BlueprintError[] = validateResource(resource, {projectContained: true})

  if (!('name' in resource) || !resource.name) {
    errors.push({type: 'missing_parameter', message: 'Robot name is required'})
  } else if (typeof resource.name !== 'string') {
    errors.push({type: 'invalid_type', message: 'Robot name must be a string'})
  }

  if (!('type' in resource)) {
    errors.push({type: 'missing_parameter', message: 'Robot type is required'})
  } else if (resource.type !== 'sanity.access.robot') {
    errors.push({type: 'invalid_value', message: 'Robot type must be `sanity.access.robot`'})
  }

  if (!('label' in resource) || !resource.label) {
    errors.push({type: 'missing_parameter', message: 'Robot label is required'})
  } else if (typeof resource.label !== 'string') {
    errors.push({type: 'invalid_type', message: 'Robot label must be a string'})
  }

  if (!('memberships' in resource)) {
    errors.push({type: 'missing_parameter', message: 'Robot memberships array is required'})
  } else if (!Array.isArray(resource.memberships)) {
    errors.push({type: 'invalid_type', message: 'Robot memberships must be an array'})
  } else if (resource.memberships.length === 0) {
    errors.push({type: 'invalid_value', message: 'Robot must have at least one membership'})
  } else {
    errors.push(...resource.memberships.flatMap(validateRobotMembership))
  }

  if ('resourceType' in resource) {
    if (resource.resourceType !== 'organization' && resource.resourceType !== 'project') {
      errors.push({type: 'invalid_value', message: 'Robot resource type must be `organization` or `project`'})
    }
    if (!('resourceId' in resource)) {
      errors.push({type: 'missing_parameter', message: 'Robot resource ID is required when resource type is provided'})
    }
  }

  if ('resourceId' in resource) {
    if (typeof resource.resourceId !== 'string') {
      errors.push({type: 'invalid_type', message: 'Robot resource ID must be a string'})
    }
    if (!('resourceType' in resource)) {
      errors.push({type: 'missing_parameter', message: 'Robot resource type is required when resource ID is provided'})
    }
  }

  return errors
}

export function validateRobotMembership(membership: unknown): BlueprintError[] {
  if (!membership) return [{type: 'invalid_value', message: 'Membership config must be provided'}]
  if (typeof membership !== 'object') return [{type: 'invalid_type', message: 'Membership config must be an object'}]

  const errors: BlueprintError[] = []

  if (!('resourceType' in membership)) {
    errors.push({type: 'missing_parameter', message: 'Membership resource type is required'})
  } else if (membership.resourceType !== 'organization' && membership.resourceType !== 'project') {
    errors.push({type: 'invalid_value', message: 'Membership resource type must be `organization` or `project`'})
  }

  if (!('resourceId' in membership) || !membership.resourceId) {
    errors.push({type: 'missing_parameter', message: 'Membership resource ID is required'})
  } else if (typeof membership.resourceId !== 'string') {
    errors.push({type: 'invalid_type', message: 'Membership resource ID must be a string'})
  }

  if (!('roleNames' in membership)) {
    errors.push({type: 'missing_parameter', message: 'Membership role names array is required'})
  } else if (!Array.isArray(membership.roleNames)) {
    errors.push({type: 'invalid_type', message: 'Membership role names must be an array'})
  } else if (membership.roleNames.length === 0) {
    errors.push({type: 'invalid_value', message: 'Membership must have at least one role name'})
  } else {
    for (const roleName of membership.roleNames) {
      if (!roleName || typeof roleName !== 'string') {
        errors.push({type: 'invalid_value', message: 'Membership role name must have at least one character'})
      }
    }
  }

  return errors
}
