import * as path from 'node:path';
import { resolveDataDir } from '../../../comm/data-dir.js';
import { FileSessionTreeProvider } from './file_provider.js';
import { MySqlSessionTreeProvider, type SessionTreeRepositoryLike } from './mysql_provider.js';
import type { SessionTreeProvider } from './provider.js';

export interface AgentSessionTreeFileConfig {
  rootDir?: string;
}

export interface AgentSessionTreeConfig {
  backend?: 'file' | 'mysql';
  cwd?: string;
  file?: AgentSessionTreeFileConfig;
}

export interface SessionTreeGlobalDefaults {
  backend?: 'file' | 'mysql';
  dataDir?: string;
}

export interface ResolvedAgentSessionTreeConfig {
  backend: 'file' | 'mysql';
  cwd?: string;
  file?: {
    rootDir: string;
  };
}

export interface CreateSessionTreeProviderOptions {
  session: ResolvedAgentSessionTreeConfig;
  cwd?: string;
  sessionRepo?: SessionTreeRepositoryLike;
  entryRepo?: SessionTreeRepositoryLike;
}

export function resolveAgentSessionTreeConfig(
  agentConfig: AgentSessionTreeConfig | undefined,
  defaults: SessionTreeGlobalDefaults,
): ResolvedAgentSessionTreeConfig {
  const backend = agentConfig?.backend ?? defaults.backend ?? 'file';

  if (backend === 'file') {
    return {
      backend,
      cwd: agentConfig?.cwd,
      file: {
        rootDir: agentConfig?.file?.rootDir ?? path.join(defaults.dataDir ?? resolveDataDir(), 'sessions'),
      },
    };
  }

  return {
    backend,
    cwd: agentConfig?.cwd,
  };
}

export function createSessionTreeProvider(
  options: CreateSessionTreeProviderOptions,
): SessionTreeProvider {
  if (options.session.backend === 'file') {
    return new FileSessionTreeProvider({
      rootDir: options.session.file?.rootDir ?? path.join(resolveDataDir(), 'sessions'),
      cwd: options.cwd,
    });
  }

  if (!options.sessionRepo || !options.entryRepo) {
    throw new Error('MySqlSessionTreeProvider requires both sessionRepo and entryRepo');
  }

  return new MySqlSessionTreeProvider({
    sessionRepo: options.sessionRepo,
    entryRepo: options.entryRepo,
  });
}
