import { readFile } from 'node:fs/promises';
import YAML from 'yaml';
import type { FleetAgent } from '../commands/fleet.js';

const REQUIRED_RUNTIME = 'pi';
const REQUIRED_MODEL = 'openai/gpt-5.6-sol';
const REQUIRED_REASONING = 'high';
const REQUIRED_TOOL_POLICY = 'operator-interaction';
const AGENT_NAME_PATTERN = /^[A-Za-z0-9_.-]+$/;

export interface InteractionServiceProfile {
  runtime: string;
  model: string;
  reasoning: string;
  toolPolicy: string;
}

export interface EffectiveInteractionPolicy {
  agentName: string;
  runtime: string;
  model: string;
  reasoning: string;
  toolPolicy: string;
}

export class InteractionServiceProfileError extends Error {
  constructor(
    readonly code: 'invalid_profile' | 'invalid_request',
    message: string,
  ) {
    super(message);
    this.name = InteractionServiceProfileError.name;
  }
}

export async function readInteractionServiceProfile(
  path: string,
  overrides: Partial<InteractionServiceProfile> = {},
): Promise<InteractionServiceProfile> {
  const parsed: unknown = YAML.parse(await readFile(path, 'utf8'));
  if (!isRecord(parsed)) {
    throw new InteractionServiceProfileError(
      'invalid_profile',
      'Service profile must be an object',
    );
  }
  const profile: InteractionServiceProfile = {
    runtime: valueOrUndefined(overrides.runtime, parsed['runtime']),
    model: valueOrUndefined(overrides.model, parsed['model']),
    reasoning: valueOrUndefined(overrides.reasoning, parsed['reasoning']),
    toolPolicy: valueOrUndefined(overrides.toolPolicy, parsed['tool_policy']),
  };
  assertPinnedPolicy(profile);
  return profile;
}

export function provisionInteractionService(
  profile: InteractionServiceProfile,
  input: { agentName: string },
): { rosterAgent: FleetAgent; effectivePolicy: EffectiveInteractionPolicy } {
  assertPinnedPolicy(profile);
  if (!AGENT_NAME_PATTERN.test(input.agentName)) {
    throw new InteractionServiceProfileError(
      'invalid_request',
      'Agent name must contain only letters, numbers, dots, underscores, or hyphens',
    );
  }
  const effectivePolicy: EffectiveInteractionPolicy = {
    agentName: input.agentName,
    runtime: profile.runtime,
    model: profile.model,
    reasoning: profile.reasoning,
    toolPolicy: profile.toolPolicy,
  };
  return {
    rosterAgent: {
      name: input.agentName,
      runtime: profile.runtime,
      className: profile.toolPolicy,
      modelHint: profile.model,
      reasoningLevel: profile.reasoning,
      toolPolicy: profile.toolPolicy,
      persistentPersona: true,
    },
    effectivePolicy,
  };
}

function assertPinnedPolicy(profile: InteractionServiceProfile): void {
  const invalid =
    profile.runtime !== REQUIRED_RUNTIME ||
    profile.model !== REQUIRED_MODEL ||
    profile.reasoning !== REQUIRED_REASONING ||
    profile.toolPolicy !== REQUIRED_TOOL_POLICY;
  if (invalid) {
    throw new InteractionServiceProfileError(
      'invalid_profile',
      `Service profile must pin ${REQUIRED_RUNTIME}, ${REQUIRED_MODEL}, ${REQUIRED_REASONING}, and ${REQUIRED_TOOL_POLICY}`,
    );
  }
}

function valueOrUndefined(override: string | undefined, value: unknown): string {
  if (override !== undefined) return override;
  return typeof value === 'string' ? value : '';
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}
