import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
import type { DevBacklog, DevTask } from './types.js';
import type { Logger } from './logger.js';

const BACKLOG_FILE = '/home/fitcrm/data/dev-backlog.json';

function loadBacklog(): DevBacklog {
  try {
    if (fs.existsSync(BACKLOG_FILE)) {
      return JSON.parse(fs.readFileSync(BACKLOG_FILE, 'utf-8')) as DevBacklog;
    }
  } catch {
    // Corrupted file — start fresh
  }
  return { tasks: [], lastUpdated: new Date().toISOString() };
}

function saveBacklog(backlog: DevBacklog): void {
  fs.mkdirSync(path.dirname(BACKLOG_FILE), { recursive: true });
  backlog.lastUpdated = new Date().toISOString();
  fs.writeFileSync(BACKLOG_FILE, JSON.stringify(backlog, null, 2));
}

/** Returns endpoints that are NOT yet in the backlog (truly new discoveries) */
export function filterNewMissingEndpoints(
  serviceId: string,
  missingEndpoints: { endpoint: string; page: string }[],
): { endpoint: string; page: string }[] {
  const backlog = loadBacklog();
  const known = new Set(
    backlog.tasks
      .filter((t) => t.serviceId === serviceId && t.status !== 'done')
      .map((t) => t.endpoint),
  );

  return missingEndpoints.filter((ep) => !known.has(ep.endpoint));
}

/** Returns all known missing endpoints for a service (to exclude from checks) */
export function getKnownMissingEndpoints(serviceId: string): Set<string> {
  const backlog = loadBacklog();
  return new Set(
    backlog.tasks
      .filter((t) => t.serviceId === serviceId && t.status !== 'done')
      .map((t) => t.endpoint),
  );
}

/** Register newly discovered missing endpoints in the backlog */
export function addToBacklog(
  serviceId: string,
  serviceName: string,
  endpoints: { endpoint: string; page: string }[],
  logger: Logger,
): DevTask[] {
  const backlog = loadBacklog();
  const newTasks: DevTask[] = [];

  for (const ep of endpoints) {
    const task: DevTask = {
      id: crypto.randomUUID(),
      serviceId,
      serviceName,
      endpoint: ep.endpoint,
      page: ep.page,
      discoveredAt: new Date().toISOString(),
      status: 'pending',
    };
    backlog.tasks.push(task);
    newTasks.push(task);
  }

  saveBacklog(backlog);
  logger.info(`Added ${newTasks.length} endpoints to dev backlog`, {
    serviceId,
    endpoints: endpoints.map((e) => e.endpoint),
  });

  return newTasks;
}

/** Mark endpoint as done (e.g. after it's implemented) */
export function markEndpointDone(endpoint: string, logger: Logger): void {
  const backlog = loadBacklog();
  let changed = false;

  for (const task of backlog.tasks) {
    if (task.endpoint === endpoint && task.status !== 'done') {
      task.status = 'done';
      changed = true;
    }
  }

  if (changed) {
    saveBacklog(backlog);
    logger.info(`Marked endpoint as done: ${endpoint}`);
  }
}

/** Check if previously missing endpoints are now implemented and clean them up */
export function recheckResolvedEndpoints(_logger: Logger): string[] {
  const backlog = loadBacklog();
  // We don't do the HTTP check here — that's done in the checker
  // This just returns the list of pending tasks for external checking
  return backlog.tasks.filter((t) => t.status === 'pending').map((t) => t.endpoint);
}

/** Get summary of backlog for display */
export function getBacklogSummary(): {
  total: number;
  pending: number;
  byService: Record<string, number>;
} {
  const backlog = loadBacklog();
  const pending = backlog.tasks.filter((t) => t.status !== 'done');
  const byService: Record<string, number> = {};

  for (const task of pending) {
    byService[task.serviceName] = (byService[task.serviceName] ?? 0) + 1;
  }

  return { total: backlog.tasks.length, pending: pending.length, byService };
}
