import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
import { getApiBase } from '../utils/apiBase';
import { useRoute, useRouter } from 'vue-router';
import { marked } from 'marked';
import { ws, lastViewerPath, useViewerStore } from '../store';

export function useViewer() {
  const route = useRoute();
  const router = useRouter();
  const { onMessage } = ws;

  const viewerStore = useViewerStore();
  const fstoken = computed(() => viewerStore.fstoken);
  const viewerRoots = computed(() => viewerStore.roots);
  const token = fstoken;

  function normalizePath(path: string): string {
    if (!path) return path;
    const roots = viewerStore.roots;
    if (!roots.length) return path;
    const [prefix, ...rest] = path.split('/');
    if (roots.includes(prefix)) return path;
    const canonical = roots.find(r => r === `workspace-${prefix}` || r.endsWith(`-${prefix}`));
    return canonical ? [canonical, ...rest].join('/') : path;
  }

  const currentPath = ref(normalizePath(
    (route.query.path as string) || localStorage.getItem('viewer_last_path') || ''
  ));
  const sidebarCollapsed = ref(window.innerWidth < 768);
  const content = ref('');
  const fileType = ref<'md' | 'pdf' | 'text' | 'dir' | ''>('');
  const dirFiles = ref<{ name: string; path: string; mtime: number }[]>([]);
  const dirDirs = ref<string[]>([]);
  const loading = ref(false);
  const showLoading = ref(false);
  let loadingTimer: ReturnType<typeof setTimeout> | null = null;
  const fetchError = ref('');
  const pdfCacheBust = ref(Date.now());
  const mdRaw = ref(false);

  const mdLineCount = computed(() => {
    if (!content.value) return 0;
    return content.value.split('\n').length;
  });

  const renderedMd = computed(() => {
    if (fileType.value !== 'md' || !content.value) return '';
    return marked.parse(content.value) as string;
  });

  const pdfSrc = computed(() => {
    if (fileType.value !== 'pdf' || !currentPath.value || !token.value) return '';
    const base = getBaseUrl();
    return `${base}/api/viewer/file?path=${encodeURIComponent(currentPath.value)}&token=${encodeURIComponent(token.value)}&t=${pdfCacheBust.value}`;
  });

  function getBaseUrl(): string {
    return getApiBase();
  }

  function extOf(p: string): string {
    const m = p.match(/\.([^./]+)$/);
    return m ? m[1].toLowerCase() : '';
  }

  function startLoading(silent: boolean) {
    if (silent) return;
    loading.value = true;
    showLoading.value = false;
    if (loadingTimer) clearTimeout(loadingTimer);
    loadingTimer = setTimeout(() => { showLoading.value = true; }, 3000);
  }
  function stopLoading() {
    loading.value = false;
    showLoading.value = false;
    if (loadingTimer) { clearTimeout(loadingTimer); loadingTimer = null; }
  }

  async function fetchContent(path: string, silent = false, _retry = false) {
    startLoading(silent);
    try {
      const base = getBaseUrl();
      const url = `${base}/api/viewer/file?path=${encodeURIComponent(path)}&token=${encodeURIComponent(token.value)}`;
      const res = await fetch(url);
      if (res.status === 401 && !_retry) {
        viewerStore.invalidate();
        await viewerStore.acquire(true);
        return fetchContent(path, silent, true);
      }
      if (!res.ok) {
        fetchError.value = `${res.status}: ${await res.text()}`;
        return;
      }
      fetchError.value = '';
      content.value = await res.text();
    } catch (e: any) {
      fetchError.value = e.message || 'Fetch failed';
    } finally {
      stopLoading();
    }
  }

  async function openFile(path: string) {
    path = normalizePath(path);
    currentPath.value = path;
    localStorage.setItem('viewer_last_path', path);
    lastViewerPath.value = path;
    if (route.query.path !== path) {
      router.push({ name: 'viewer', query: { path } });
    }
    const ext = extOf(path);

    // Empty path = root listing (show viewer roots)
    if (!path) {
      fileType.value = 'dir';
      content.value = '';
      fetchError.value = '';
      dirDirs.value = viewerRoots.value.length ? viewerRoots.value : ['shared', 'workspace-titan'];
      dirFiles.value = [];
      return;
    }

    // No extension = directory
    if (!ext) {
      fileType.value = 'dir';
      content.value = '';
      fetchError.value = '';
      // Keep old dir content visible while fetching new
      startLoading(false);
      try {
        const base = getBaseUrl();
        const url = `${base}/api/viewer/tree?root=${encodeURIComponent(path)}&token=${encodeURIComponent(token.value)}`;
        const res = await fetch(url);
        if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
        const data = await res.json();
        dirDirs.value = data.dirs || [];
        dirFiles.value = data.files || [];
      } catch (e: any) {
        dirDirs.value = [];
        dirFiles.value = [];
        fetchError.value = e.message || 'Failed to load directory';
      } finally {
        stopLoading();
      }
      return;
    }

    if (ext === 'pdf') {
      fileType.value = 'pdf';
      content.value = '';
      fetchError.value = '';
      pdfCacheBust.value = Date.now();
      fetch(`${getBaseUrl()}/api/viewer/file?path=${encodeURIComponent(path)}&token=${encodeURIComponent(token.value)}`, { method: 'HEAD' }).catch(() => {});
      return;
    }

    fileType.value = ext === 'md' ? 'md' : 'text';
    fetchError.value = '';
    await fetchContent(path, false);
  }

  function onCopy(e: ClipboardEvent) {
    const sel = window.getSelection();
    if (!sel || sel.isCollapsed) return;
    const html = (() => {
      const div = document.createElement('div');
      div.appendChild(sel.getRangeAt(0).cloneContents());
      return div.innerHTML;
    })();
    const clean = html.replace(/background(-color)?:[^;"]*(;|(?="))/gi, '');
    const plain = sel.toString();
    e.clipboardData!.setData('text/html', clean);
    e.clipboardData!.setData('text/plain', plain);
    e.preventDefault();
  }

  async function refreshFile(path: string) {
    const ext = extOf(path);
    if (ext === 'pdf') {
      pdfCacheBust.value = Date.now();
      return;
    }
    await fetchContent(path, true);
  }

  // Lifecycle
  let unsubscribe: (() => void) | null = null;

  onMounted(() => {
    unsubscribe = onMessage((data: any) => {
      if (data.type === 'viewer_file_changed' && data.path === currentPath.value) {
        refreshFile(currentPath.value);
      }
      if (data.type === 'viewer_tree_changed' && data.path === currentPath.value && fileType.value === 'dir') {
        openFile(currentPath.value);
      }
    });
    viewerStore.acquire();
    if (currentPath.value) openFile(currentPath.value);
  });

  watch(() => route.query.path, (newPath) => {
    if (newPath && newPath !== currentPath.value) {
      openFile(newPath as string);
    }
  });

  onUnmounted(() => {
    if (unsubscribe) unsubscribe();
  });

  return {
    fstoken,
    viewerRoots,
    currentPath,
    sidebarCollapsed,
    content,
    fileType,
    loading,
    fetchError,
    mdRaw,
    mdLineCount,
    renderedMd,
    pdfSrc,
    openFile,
    onCopy,
    dirFiles,
    dirDirs,
    showLoading,
  };
}
