// Extracted from src/db/repository.ts (mechanical split — bodies unchanged).
// worker-nodes repository domain. Facade: src/db/repository.ts (Repository class).
import Database from 'better-sqlite3';
import { encodeTags, decodeTags, decodeAvailableModels, utc } from './shared.js';

export interface WorkerNode {
  workerId: string;
  endpoint: string;
  enabled: boolean;
  healthy: boolean;
  roles: string[];
  availableModels: string[];
  inflightJobs: number;
  maxConcurrency: number;
  lastError: string | null;
  lastSeenAt: string;
  updatedAt: string;
}


export interface UpsertWorkerNodeParams {
  workerId: string;
  endpoint: string;
  enabled: boolean;
  healthy: boolean;
  roles: string[];
  availableModels?: string[];
  inflightJobs?: number;
  maxConcurrency?: number;
  lastError?: string | null;
}


export interface WorkerNodeRow {
  worker_id: string;
  endpoint: string;
  enabled: number;
  healthy: number;
  profile_tags: string;
  task_class_tags: string;
  available_models: string | null;
  inflight_jobs: number;
  max_concurrency: number;
  last_error: string | null;
  last_seen_at: string;
  updated_at: string;
}


export function rowToWorkerNode(row: WorkerNodeRow): WorkerNode {
  return {
    workerId: row.worker_id,
    endpoint: row.endpoint,
    enabled: row.enabled === 1,
    healthy: row.healthy === 1,
    roles: decodeTags(row.profile_tags),
    availableModels: decodeAvailableModels(row.available_models),
    inflightJobs: row.inflight_jobs,
    maxConcurrency: row.max_concurrency,
    lastError: row.last_error,
    lastSeenAt: utc(row.last_seen_at),
    updatedAt: utc(row.updated_at),
  };
}


  export async function upsertWorkerNode(db: Database.Database, params: UpsertWorkerNodeParams): Promise<void> {
    const now = new Date().toISOString();
    db.prepare(`
      INSERT INTO worker_nodes (
        worker_id, endpoint, enabled, healthy, profile_tags, task_class_tags, available_models,
        inflight_jobs, max_concurrency, last_error, last_seen_at, updated_at
      ) VALUES (
        @workerId, @endpoint, @enabled, @healthy, @roleTags, @roleTags, @availableModels,
        @inflightJobs, @maxConcurrency, @lastError, @now, @now
      )
      ON CONFLICT(worker_id) DO UPDATE SET
        endpoint = excluded.endpoint,
        enabled = excluded.enabled,
        healthy = excluded.healthy,
        profile_tags = excluded.profile_tags,
        task_class_tags = excluded.task_class_tags,
        available_models = excluded.available_models,
        inflight_jobs = excluded.inflight_jobs,
        max_concurrency = excluded.max_concurrency,
        last_error = excluded.last_error,
        last_seen_at = excluded.last_seen_at,
        updated_at = excluded.updated_at
    `).run({
      workerId: params.workerId,
      endpoint: params.endpoint,
      enabled: params.enabled ? 1 : 0,
      healthy: params.healthy ? 1 : 0,
      roleTags: encodeTags(params.roles),
      availableModels: JSON.stringify(params.availableModels ?? []),
      inflightJobs: params.inflightJobs ?? 0,
      maxConcurrency: params.maxConcurrency ?? 1,
      lastError: params.lastError ?? null,
      now,
    });
  }


  export async function updateWorkerNodeHealth(db: Database.Database, workerId: string, updates: { healthy: boolean; lastError?: string | null; inflightJobs?: number; availableModels?: string[]; enabled?: boolean }): Promise<void> {
    const setClauses = [
      'healthy = @healthy',
      'last_error = @lastError',
      "last_seen_at = @now",
      "updated_at = @now",
    ];
    const params: Record<string, unknown> = {
      workerId,
      healthy: updates.healthy ? 1 : 0,
      lastError: updates.lastError ?? null,
      now: new Date().toISOString(),
    };

    if (updates.inflightJobs !== undefined) {
      setClauses.push('inflight_jobs = @inflightJobs');
      params['inflightJobs'] = updates.inflightJobs;
    }
    if (updates.availableModels !== undefined) {
      setClauses.push('available_models = @availableModels');
      params['availableModels'] = JSON.stringify(updates.availableModels);
    }
    if (updates.enabled !== undefined) {
      setClauses.push('enabled = @enabled');
      params['enabled'] = updates.enabled ? 1 : 0;
    }

    db.prepare(`UPDATE worker_nodes SET ${setClauses.join(', ')} WHERE worker_id = @workerId`).run(params);
  }


  export async function getWorkerNode(db: Database.Database, workerId: string): Promise<WorkerNode | null> {
    const row = db
      .prepare('SELECT * FROM worker_nodes WHERE worker_id = ?')
      .get(workerId) as WorkerNodeRow | undefined;
    return row ? rowToWorkerNode(row) : null;
  }
