import { getRegisteredAccessToken } from '../tokenAccess';

const CHAT_API_RESOURCE_MARKER = '/api/chat/resources/';
const CHAT_DOT_CODEX_MARKER = '/.codex_chat/';
const CHAT_PUBLIC_DOT_CODEX_MARKER = '/public/.codex_chat/';
const RESOURCE_MANAGER_PREVIEW_MARKER = '/api/resource-manager/preview/';
const RESOURCE_MANAGER_ROOT_MARKER = 'resource/';

function buildCanonicalChatApiResourcePath(relativePath: string) {
  const normalizedRelativePath = String(relativePath ?? '').trim().replace(/^\/+/, '');

  if (!normalizedRelativePath) {
    return '';
  }

  if (normalizedRelativePath.startsWith('.codex_chat/')) {
    return `${CHAT_API_RESOURCE_MARKER}${normalizedRelativePath}`;
  }

  return `${CHAT_API_RESOURCE_MARKER}.codex_chat/${normalizedRelativePath}`;
}

function normalizeUrlFragmentValue(value: string) {
  const normalized = String(value ?? '').trim().replace(/^#+/, '');

  if (!normalized) {
    return '';
  }

  try {
    return decodeURIComponent(normalized);
  } catch {
    return normalized;
  }
}

function decodeRepeatedly(value: string, maxIterations = 3) {
  let current = value;

  for (let index = 0; index < maxIterations; index += 1) {
    try {
      const decoded = decodeURIComponent(current);

      if (!decoded || decoded === current) {
        break;
      }

      current = decoded;
    } catch {
      break;
    }
  }

  return current;
}

function normalizePreviewPathHash(value: string) {
  const normalized = String(value ?? '').trim();

  if (!normalized) {
    return '';
  }

  const isAbsoluteUrl = /^[a-z][a-z0-9+.-]*:\/\//i.test(normalized);
  const isRootRelative = normalized.startsWith('/');

  try {
    const parsed = new URL(normalized, 'https://local.invalid');
    const segments = parsed.pathname.split('/');
    const lastSegment = segments.at(-1) ?? '';
    const decodedLastSegment = decodeRepeatedly(lastSegment);
    const hashIndex = decodedLastSegment.lastIndexOf('#');

    if (hashIndex <= 0 || parsed.hash) {
      return normalized;
    }

    const fileName = decodedLastSegment.slice(0, hashIndex).trim();
    const fragment = normalizeUrlFragmentValue(decodedLastSegment.slice(hashIndex + 1));

    if (!fileName || !fragment || !/\.[a-z0-9]{1,16}$/i.test(fileName)) {
      return normalized;
    }

    segments[segments.length - 1] = encodeURIComponent(fileName);
    parsed.pathname = segments.join('/');
    parsed.hash = fragment;

    if (isAbsoluteUrl) {
      return parsed.toString();
    }

    const pathWithQueryAndHash = `${parsed.pathname}${parsed.search}${parsed.hash}`;
    return isRootRelative ? pathWithQueryAndHash : pathWithQueryAndHash.replace(/^\/+/, '');
  } catch {
    return normalized;
  }
}

function normalizeResourceManagerPathSegment(segment: string) {
  const normalized = String(segment ?? '').trim();

  if (!normalized) {
    return '';
  }

  try {
    return encodeURIComponent(decodeURIComponent(normalized));
  } catch {
    return encodeURIComponent(normalized);
  }
}

function buildResourceManagerPreviewPath(value: string) {
  const normalized = normalizePreviewPathHash(String(value ?? '').trim().replace(/\\/g, '/'));
  const hashIndex = normalized.indexOf('#');
  const hash = hashIndex >= 0 ? normalizeUrlFragmentValue(normalized.slice(hashIndex + 1)) : '';
  const normalizedPath = hashIndex >= 0 ? normalized.slice(0, hashIndex) : normalized;
  const matchedResourcePath = normalizedPath.match(/(?:^|\/)(resource\/.+)$/i)?.[1];
  const resourcePath = String(matchedResourcePath ?? '').trim().replace(/^\/+/, '');

  if (!resourcePath) {
    return '';
  }

  const relativePath = resourcePath.slice(RESOURCE_MANAGER_ROOT_MARKER.length).replace(/^\/+/, '');

  if (!relativePath) {
    return '';
  }

  const encodedPath = relativePath
    .split('/')
    .filter(Boolean)
    .map((segment) => normalizeResourceManagerPathSegment(segment))
    .join('/');

  return encodedPath ? `${RESOURCE_MANAGER_PREVIEW_MARKER}${encodedPath}${hash ? `#${hash}` : ''}` : '';
}

function resolveLegacyExternalImageUrl(value: string) {
  const normalized = String(value ?? '').trim();
  const match = normalized.match(/^\/api\/resource-manager\/preview\/(\d+)\/([^/?#]+\.(?:png|jpe?g|gif|webp|svg|bmp|ico))(?:[?#].*)?$/i);

  if (!match) {
    return '';
  }

  const [, directory, fileName] = match;

  if (!/^\d+_image\d+[_\d-]*\.(?:png|jpe?g|gif|webp|svg|bmp|ico)$/i.test(fileName)) {
    return '';
  }

  return `https://tong.visitkorea.or.kr/cms/resource/${directory}/${fileName}`;
}

function extractEmbeddedResourcePath(value: string) {
  const normalized = String(value ?? '').trim();

  if (!normalized) {
    return '';
  }

  const apiMarkerIndex = normalized.lastIndexOf(CHAT_API_RESOURCE_MARKER);

  if (apiMarkerIndex >= 0) {
    const apiPath = normalized.slice(apiMarkerIndex);
    const dotCodexIndex = apiPath.indexOf(CHAT_DOT_CODEX_MARKER);
    return dotCodexIndex >= 0
      ? buildCanonicalChatApiResourcePath(apiPath.slice(dotCodexIndex + 1))
      : apiPath;
  }

  const publicDotCodexIndex = normalized.lastIndexOf(CHAT_PUBLIC_DOT_CODEX_MARKER);

  if (publicDotCodexIndex >= 0) {
    return buildCanonicalChatApiResourcePath(normalized.slice(publicDotCodexIndex + 8));
  }

  const dotCodexIndex = normalized.lastIndexOf(CHAT_DOT_CODEX_MARKER);

  if (dotCodexIndex >= 0) {
    return buildCanonicalChatApiResourcePath(normalized.slice(dotCodexIndex + 1));
  }

  if (normalized === 'resource' || normalized === '/resource' || normalized.startsWith('resource/') || normalized.includes('/resource/')) {
    const resourceManagerPreviewPath = buildResourceManagerPreviewPath(normalized);

    if (resourceManagerPreviewPath) {
      return resourceManagerPreviewPath;
    }
  }

  return normalized;
}

function extractKnownPreviewPath(value: string) {
  const normalized = String(value ?? '').trim();

  if (!normalized) {
    return '';
  }

  try {
    const parsed = new URL(normalized);
    const pathname = `${parsed.pathname || ''}${parsed.search || ''}${parsed.hash || ''}`;

    if (pathname.startsWith(CHAT_API_RESOURCE_MARKER) || pathname.startsWith(RESOURCE_MANAGER_PREVIEW_MARKER)) {
      return normalizePreviewPathHash(pathname);
    }

    if (pathname.startsWith(CHAT_PUBLIC_DOT_CODEX_MARKER)) {
      return buildCanonicalChatApiResourcePath(pathname.slice(CHAT_PUBLIC_DOT_CODEX_MARKER.length));
    }

    if (pathname.startsWith(CHAT_DOT_CODEX_MARKER)) {
      return buildCanonicalChatApiResourcePath(pathname.slice(CHAT_DOT_CODEX_MARKER.length));
    }

    return normalized;
  } catch {
    return normalizePreviewPathHash(extractEmbeddedResourcePath(normalized));
  }
}

export function normalizeChatResourceUrl(value: string) {
  const normalized = normalizePreviewPathHash(extractKnownPreviewPath(value));
  const legacyExternalImageUrl = resolveLegacyExternalImageUrl(normalized);

  if (legacyExternalImageUrl) {
    return legacyExternalImageUrl;
  }

  if (typeof window === 'undefined') {
    return normalized;
  }

  try {
    const resolvedUrl = new URL(normalized, window.location.href);

    if (resolvedUrl.pathname.startsWith(RESOURCE_MANAGER_PREVIEW_MARKER) && !resolvedUrl.searchParams.has('token')) {
      const token = getRegisteredAccessToken();

      if (token) {
        resolvedUrl.searchParams.set('token', token);
      }
    }

    return resolvedUrl.toString();
  } catch {
    return normalized;
  }
}

export function isMarkdownResourceUrl(value?: string | null) {
  const normalized = String(value ?? '').trim();

  if (!normalized) {
    return false;
  }

  try {
    const resolvedUrl = new URL(normalized, 'http://localhost');
    return /\.(md|markdown)$/i.test(resolvedUrl.pathname);
  } catch {
    return /\.(md|markdown)(?:$|[?#])/i.test(normalized);
  }
}

export function isMarkdownContentType(contentType?: string | null) {
  if (!contentType) {
    return false;
  }

  const normalized = contentType.toLowerCase();

  return (
    normalized.includes('text/markdown') ||
    normalized.includes('text/x-markdown') ||
    normalized.includes('application/markdown')
  );
}
