import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs';
import { readToolRuntimeContext } from './runtime_context.js';

const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
const NARROW_NO_BREAK_SPACE = '\u202F';

function normalizeAtPrefix(filePath: string): string {
  return filePath.startsWith('@') ? filePath.slice(1) : filePath;
}

function normalizeUnicodeSpaces(filePath: string): string {
  return filePath.replace(UNICODE_SPACES, ' ');
}

export function expandToolPath(inputPath: string): string {
  const normalized = normalizeUnicodeSpaces(normalizeAtPrefix(inputPath.trim()));
  if (normalized === '~') {
    return os.homedir();
  }
  if (normalized.startsWith('~/') || normalized.startsWith('~\\')) {
    return path.join(os.homedir(), normalized.slice(2));
  }
  return normalized;
}

export function resolveToolPath(inputPath: string, cwd: string = process.cwd()): string {
  const expanded = expandToolPath(inputPath);
  if (path.isAbsolute(expanded)) {
    return path.resolve(expanded);
  }
  return path.resolve(cwd, expanded);
}

export function resolveToolPathFromParams(
  inputPath: string,
  params: Record<string, unknown> | undefined,
  fallbackCwd: string = process.cwd()
): string {
  const runtime = readToolRuntimeContext(params);
  const effectiveCwd = runtime?.sessionCwd || fallbackCwd;
  return resolveToolPath(inputPath, effectiveCwd);
}

export function resolveToolReadPathFromParams(
  inputPath: string,
  params: Record<string, unknown> | undefined,
  fallbackCwd: string = process.cwd()
): string {
  const resolved = resolveToolPathFromParams(inputPath, params, fallbackCwd);
  return findReadablePathVariant(resolved);
}

function findReadablePathVariant(resolvedPath: string): string {
  const variants = [
    resolvedPath,
    tryMacOSScreenshotPath(resolvedPath),
    resolvedPath.normalize('NFD'),
    tryCurlyQuoteVariant(resolvedPath),
    tryCurlyQuoteVariant(resolvedPath.normalize('NFD')),
  ];

  for (const variant of variants) {
    if (variant && fileExists(variant)) {
      return variant;
    }
  }

  return resolvedPath;
}

function tryMacOSScreenshotPath(filePath: string): string {
  return filePath.replace(/ (AM|PM)\./gi, `${NARROW_NO_BREAK_SPACE}$1.`);
}

function tryCurlyQuoteVariant(filePath: string): string {
  return filePath.replace(/'/g, '\u2019');
}

function fileExists(filePath: string): boolean {
  try {
    fs.accessSync(filePath, fs.constants.F_OK);
    return true;
  } catch {
    return false;
  }
}
