const VALID_PROFILES = ['auto', 'fast', 'quality'] as const;
const VALID_OUTPUT_FORMATS = ['text', 'markdown', 'json'] as const;
const VALID_ASK_POLICIES = ['low', 'high'] as const;
const VALID_PRIORITIES = ['low', 'medium', 'high'] as const;

const MAX_BODY_LENGTH = 100_000;
const MAX_TITLE_LENGTH = 200;
const MAX_COMMENT_LENGTH = 100_000;

export function parseTaskId(raw: string): number | null {
  const n = Number(raw);
  if (!Number.isInteger(n) || n <= 0) return null;
  return n;
}

export interface ValidatedCreateTask {
  body: string;
  title?: string;
  piece?: string;
  profile?: typeof VALID_PROFILES[number];
  outputFormat?: typeof VALID_OUTPUT_FORMATS[number];
  askPolicy?: typeof VALID_ASK_POLICIES[number];
  priority?: typeof VALID_PRIORITIES[number];
  attachments?: Array<{ name: string; contentBase64: string }>;
}

type ValidationResult =
  | { valid: true; data: ValidatedCreateTask }
  | { valid: false; error: string };

export function validateCreateTaskBody(raw: unknown): ValidationResult {
  if (!raw || typeof raw !== 'object') {
    return { valid: false, error: 'Request body must be an object' };
  }
  const obj = raw as Record<string, unknown>;

  if (typeof obj.body !== 'string' || obj.body.trim().length === 0) {
    return { valid: false, error: 'body is required' };
  }
  if (obj.body.length > MAX_BODY_LENGTH) {
    return { valid: false, error: `body must be ${MAX_BODY_LENGTH} characters or less` };
  }

  if (obj.title !== undefined && obj.title !== null) {
    if (typeof obj.title !== 'string') {
      return { valid: false, error: 'title must be a string' };
    }
    if (obj.title.length > MAX_TITLE_LENGTH) {
      return { valid: false, error: `title must be ${MAX_TITLE_LENGTH} characters or less` };
    }
  }

  if (obj.profile !== undefined && obj.profile !== null) {
    if (!(VALID_PROFILES as readonly string[]).includes(String(obj.profile))) {
      return { valid: false, error: `profile must be one of: ${VALID_PROFILES.join(', ')}` };
    }
  }
  if (obj.outputFormat !== undefined && obj.outputFormat !== null) {
    if (!(VALID_OUTPUT_FORMATS as readonly string[]).includes(String(obj.outputFormat))) {
      return { valid: false, error: `outputFormat must be one of: ${VALID_OUTPUT_FORMATS.join(', ')}` };
    }
  }
  if (obj.askPolicy !== undefined && obj.askPolicy !== null) {
    if (!(VALID_ASK_POLICIES as readonly string[]).includes(String(obj.askPolicy))) {
      return { valid: false, error: `askPolicy must be one of: ${VALID_ASK_POLICIES.join(', ')}` };
    }
  }
  if (obj.priority !== undefined && obj.priority !== null) {
    if (!(VALID_PRIORITIES as readonly string[]).includes(String(obj.priority))) {
      return { valid: false, error: `priority must be one of: ${VALID_PRIORITIES.join(', ')}` };
    }
  }

  return {
    valid: true,
    data: {
      body: obj.body as string,
      title: obj.title as string | undefined,
      piece: obj.piece as string | undefined,
      profile: obj.profile as ValidatedCreateTask['profile'],
      outputFormat: obj.outputFormat as ValidatedCreateTask['outputFormat'],
      askPolicy: obj.askPolicy as ValidatedCreateTask['askPolicy'],
      priority: obj.priority as ValidatedCreateTask['priority'],
      attachments: obj.attachments as ValidatedCreateTask['attachments'],
    },
  };
}

export function validateCommentBody(raw: unknown): { valid: true; body: string; author: string; attachments?: Array<{ name: string; contentBase64: string }> } | { valid: false; error: string } {
  if (!raw || typeof raw !== 'object') {
    return { valid: false, error: 'Request body must be an object' };
  }
  const obj = raw as Record<string, unknown>;
  const body = String(obj.body ?? '').trim();
  if (!body) {
    return { valid: false, error: 'body is required' };
  }
  if (body.length > MAX_COMMENT_LENGTH) {
    return { valid: false, error: `body must be ${MAX_COMMENT_LENGTH} characters or less` };
  }
  const author = String(obj.author ?? 'user').trim() || 'user';
  const attachments = Array.isArray(obj.attachments) ? obj.attachments as Array<{ name: string; contentBase64: string }> : undefined;
  return { valid: true, body, author, attachments };
}

export type ValidatedFeedback = {
  rating: 'good' | 'bad';
  tags: string[];
  comment: string | null;
};

type FeedbackValidationResult =
  | { valid: true; data: ValidatedFeedback }
  | { valid: false; error: string };

export function validateFeedbackBody(raw: unknown): FeedbackValidationResult {
  if (!raw || typeof raw !== 'object') {
    return { valid: false, error: 'Request body must be an object' };
  }
  const obj = raw as Record<string, unknown>;

  if (obj.rating !== 'good' && obj.rating !== 'bad') {
    return { valid: false, error: "rating must be 'good' or 'bad'" };
  }

  if (!Array.isArray(obj.tags) || obj.tags.some((t: unknown) => typeof t !== 'string')) {
    return { valid: false, error: 'tags must be an array of strings' };
  }
  if (obj.tags.length > 10) {
    return { valid: false, error: 'tags must have at most 10 items' };
  }

  const comment = obj.comment != null ? String(obj.comment) : null;
  if (comment && comment.length > 1000) {
    return { valid: false, error: 'comment must be at most 1000 characters' };
  }

  return {
    valid: true,
    data: { rating: obj.rating, tags: obj.tags as string[], comment },
  };
}
