import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Box, CircularProgress, IconButton, MenuItem, Select, TextField, Typography } from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings';
import { useAuth } from '../../../contexts/AuthContext';

type PageImagesManifest = {
  version: number;
  file_id: string;
  page_count: number;
  bucket?: string;
  base_dir?: string;
  page_images: Array<{
    page: number;
    full_image_path: string;
    thumbnail_path: string;
    full_dimensions?: { width: number; height: number };
    thumbnail_dimensions?: { width: number; height: number };
  }>
};

type OutlineSection = {
  id: string;
  title: string;
  level: number;
  start_page: number;
  end_page: number;
  parent_id?: string | null;
  children?: string[];
};

type Outline = {
  sections: OutlineSection[];
};

type QueueTaskBrief = {
  id: string;
  service?: string;
  task_type?: string;
  status?: string;
  priority?: string;
  created_at?: number;
  scheduled_at?: number;
  depends_on?: string[];
};

type FileTasksResponse = { file_id: string; count: number; tasks: QueueTaskBrief[] } | { error: string };

export const CCFileDetailPanel: React.FC<{
  fileId: string;
  selectedPage: number;
  onSelectPage: (p: number) => void;
}> = ({ fileId, selectedPage, onSelectPage }) => {
  const { accessToken } = useAuth();
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [manifest, setManifest] = useState<PageImagesManifest | null>(null);
  const [outline, setOutline] = useState<Outline | null>(null);
  const [collapsed, setCollapsed] = useState<Set<string>>(() => new Set());
  // outline only used for grouping thumbnails
  const [thumbUrls] = useState<Map<number, string>>(() => new Map());
  const [showAdmin, setShowAdmin] = useState(false);
  const [adminData, setAdminData] = useState<FileTasksResponse | null>(null);

  const API_BASE = useMemo(() => import.meta.env.VITE_API_BASE || (location.port.startsWith('517') ? 'http://127.0.0.1:8080' : '/api'), []);

  useEffect(() => {
    const run = async () => {
      if (!fileId) return;
      setLoading(true);
      setError(null);
      try {
        const mRes = await fetch(`${API_BASE}/database/files/${encodeURIComponent(fileId)}/page-images/manifest`, {
          headers: { 'Authorization': `Bearer ${accessToken || ''}` }
        });
        if (!mRes.ok) throw new Error(await mRes.text());
        const m: PageImagesManifest = await mRes.json();
        setManifest(m);

        // Try to load outline structure artefact (for grouping only)
        try {
          const artsRes = await fetch(`${API_BASE}/database/files/${encodeURIComponent(fileId)}/artefacts`, {
            headers: { 'Authorization': `Bearer ${accessToken || ''}` }
          });
          if (artsRes.ok) {
            const arts: Array<{ id: string; type: string }> = await artsRes.json();
            const outlineArt = arts.find(a => a.type === 'document_outline_hierarchy');
            if (outlineArt) {
              const jsonRes = await fetch(`${API_BASE}/database/files/${encodeURIComponent(fileId)}/artefacts/${encodeURIComponent(outlineArt.id)}/json`, {
                headers: { 'Authorization': `Bearer ${accessToken || ''}` }
              });
              if (jsonRes.ok) {
                const outJson = await jsonRes.json();
                const secs = (outJson.sections || []) as OutlineSection[];
                setOutline({ sections: secs });
              }
            }
          }
        } catch {
          // ignore
        }
      } catch (e: unknown) {
        setError(e instanceof Error ? e.message : 'Failed to load manifest');
      } finally {
        setLoading(false);
      }
    };
    run();
  }, [fileId, API_BASE]);

  const fetchThumb = useCallback(async (page: number): Promise<string | undefined> => {
    if (!manifest) return undefined;
    const cached = thumbUrls.get(page);
    if (cached) return cached;
    const idx = Math.max(0, Math.min((manifest.page_count || 1) - 1, page - 1));
    const pg = manifest.page_images[idx];
    if (!pg) return undefined;
    const url = `${API_BASE}/database/files/proxy?bucket=${encodeURIComponent(manifest.bucket || '')}&path=${encodeURIComponent(pg.thumbnail_path)}`;
    const token = accessToken || '';
    const resp = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });
    if (!resp.ok) return undefined;
    const blob = await resp.blob();
    const objUrl = URL.createObjectURL(blob);
    thumbUrls.set(page, objUrl);
    return objUrl;
  }, [manifest, API_BASE, thumbUrls]);

  useEffect(() => {
    if (!manifest) return;
    // Prefetch first few thumbs
    const prefetch = async () => {
      const limit = Math.min(10, manifest.page_count || 0);
      for (let p = 1; p <= limit; p++) {
        // eslint-disable-next-line no-await-in-loop
        await fetchThumb(p);
      }
    };
    prefetch();
  }, [manifest, fetchThumb]);

  if (loading) return <Box sx={{ p: 2 }}><CircularProgress size={18} /></Box>;
  if (error) return <Box sx={{ p: 2, color: 'var(--color-text-2)' }}>{error}</Box>;
  if (!manifest) return <Box sx={{ p: 2, color: 'var(--color-text-2)' }}>No page images manifest.</Box>;

  return (
    <Box sx={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      <Box sx={{ p: 1, borderBottom: '1px solid var(--color-divider)', fontWeight: 600, flexShrink: 0, bgcolor: 'var(--color-panel)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>File Details
        <IconButton size="small" onClick={async () => {
          try {
            setShowAdmin(true);
            const token = accessToken || '';
            const res = await fetch(`${API_BASE}/queue/queue/tasks/by-file/${encodeURIComponent(fileId)}`, { headers: { Authorization: `Bearer ${token}` } });
            const data = await res.json();
            setAdminData(data);
          } catch (e) {
            setAdminData({ error: (e as Error)?.message || 'Failed to load' });
          }
        }} title="Queue debug (admin)"><AdminPanelSettingsIcon fontSize="inherit" /></IconButton>
      </Box>
      <Box sx={{ p: 1, borderBottom: '1px solid var(--color-divider)', display: 'flex', alignItems: 'center', justifyContent: 'flex-start', gap: 1, flexShrink: 0, bgcolor: 'var(--color-panel)' }}>
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
          <IconButton size="small" onClick={() => onSelectPage(Math.max(1, selectedPage - 1))}><ArrowBackIosNew fontSize="inherit" /></IconButton>
          <TextField
            size="small"
            value={selectedPage}
            onChange={(e) => onSelectPage(Number(e.target.value) || 1)}
            sx={{ flexShrink: 0 }}
            InputProps={{ sx: { width: 64, '& input': { textAlign: 'center', padding: '6px' } } }}
            inputProps={{ inputMode: 'numeric', pattern: '[0-9]*', maxLength: 4 }}
          />
          <IconButton size="small" onClick={() => onSelectPage(Math.min(manifest.page_count, selectedPage + 1))}><ArrowForwardIos fontSize="inherit" /></IconButton>
          <Typography variant="body2" sx={{ color: 'var(--color-text-2)' }}>/ {manifest.page_count}</Typography>
        </Box>
      </Box>
      <Box sx={{ p: 1, borderBottom: '1px solid var(--color-divider)', display: 'flex', alignItems: 'center', gap: 1, flexShrink: 0, bgcolor: 'var(--color-panel)' }}>
        <Select size="small" value={getCurrentSectionStart(outline, selectedPage)} onChange={(e) => onSelectPage(Number(e.target.value))} displayEmpty sx={{ width: '100%', flexShrink: 0, '& .MuiSelect-select': { whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }}>
          {!outline || outline.sections.length === 0 ? (
            <MenuItem value={selectedPage} disabled>No outline</MenuItem>
          ) : (
            outline.sections.sort((a, b) => a.start_page - b.start_page).map((sec) => (
              <MenuItem key={sec.id} value={sec.start_page}>{sec.title.length > 60 ? `${sec.title.slice(0,60)}…` : sec.title} (p{sec.start_page})</MenuItem>
            ))
          )}
        </Select>
        {outline && outline.sections.length > 0 && (
          <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
            <IconButton size="small" title="Expand all" onClick={() => setCollapsed(new Set())}><ExpandMore fontSize="inherit" /></IconButton>
            <IconButton size="small" title="Collapse all" onClick={() => setCollapsed(new Set(collectAllIds(outline.sections)))}><ChevronRight fontSize="inherit" /></IconButton>
          </Box>
        )}
      </Box>
      <Box sx={{ flex: 1, overflowY: 'auto', overflowX: 'hidden', display: 'block', p: 1 }}>
        {showAdmin && (
          <Box sx={{ mb: 1, p: 1, border: '1px dashed var(--color-divider)', borderRadius: 1, bgcolor: 'var(--color-panel)' }}>
            <Typography variant="caption" sx={{ color: 'var(--color-text-3)' }}>Queue tasks for this file</Typography>
            <pre style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontSize: 11, margin: 0 }}>{JSON.stringify(adminData, null, 2)}</pre>
          </Box>
        )}
        {outline && outline.sections.length > 0 && (
          <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1 }}>
            <Typography variant="body2" sx={{ color: 'var(--color-text-2)', fontWeight: 600 }}>Sections</Typography>
            <Box>
              <IconButton size="small" title="Expand all" onClick={() => setCollapsed(new Set())}><ExpandMore fontSize="inherit" /></IconButton>
              <IconButton size="small" title="Collapse all" onClick={() => setCollapsed(new Set(collectAllIds(outline.sections)))}><ChevronRight fontSize="inherit" /></IconButton>
            </Box>
          </Box>
        )}
        {renderGroupedTiles(manifest, outline, fetchThumb, selectedPage, onSelectPage, collapsed, (id) => setCollapsed((prev) => {
          const next = new Set(prev);
          if (next.has(id)) next.delete(id); else next.add(id);
          return next;
        }))}
      </Box>
    </Box>
  );
};

type SectionNode = { sec: OutlineSection; children: SectionNode[] };

const buildSectionTree = (sections: OutlineSection[]): SectionNode[] => {
  const roots: SectionNode[] = [];
  const stack: SectionNode[] = [];
  const sorted = [...sections].sort((a, b) => a.start_page - b.start_page);
  for (const s of sorted) {
    const level = Math.max(1, Number(s.level || 1));
    const node: SectionNode = { sec: s, children: [] };
    while (stack.length && (stack.length >= level)) stack.pop();
    const parent = stack[stack.length - 1];
    if (parent) parent.children.push(node); else roots.push(node);
    stack.push(node);
  }
  return roots;
};

const renderGroupedTiles = (
  manifest: PageImagesManifest,
  outline: Outline | null,
  fetchThumb: (p: number) => Promise<string | undefined>,
  selectedPage: number,
  onSelectPage: (p: number) => void,
  collapsed: Set<string>,
  toggleCollapse: (id: string) => void
) => {
  if (!outline || outline.sections.length === 0) {
    // No outline: show a simple grid of page tiles
    return (
      <Box sx={{ width: '100%', display: 'grid', gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', gap: 1 }}>
        {manifest.page_images.map((pg) => (
          <PageTile key={pg.page} page={pg.page} fetchSrc={() => fetchThumb(pg.page)} selected={pg.page === selectedPage} onClick={() => onSelectPage(pg.page)} />
        ))}
      </Box>
    );
  }
  const tree = buildSectionTree(outline.sections);
  return tree.map((node) => (
    <SectionTile
      key={node.sec.id}
      node={node}
      manifest={manifest}
      fetchThumb={fetchThumb}
      selectedPage={selectedPage}
      onSelectPage={onSelectPage}
      collapsed={collapsed}
      toggleCollapse={toggleCollapse}
      level={Math.max(1, Number(node.sec.level || 1))}
    />
  ));
};

  // OutlineTree UI has been moved to top navigation; grouping-by-section thumbnails remain below.

const SectionTile: React.FC<{
  node: SectionNode;
  manifest: PageImagesManifest;
  fetchThumb: (p: number) => Promise<string | undefined>;
  selectedPage: number;
  onSelectPage: (p: number) => void;
  collapsed: Set<string>;
  toggleCollapse: (id: string) => void;
  level: number;
}> = ({ node, manifest, fetchThumb, selectedPage, onSelectPage, collapsed, toggleCollapse, level }) => {
  const s = node.sec;
  const ml = (level - 1) * 1;
  const isCollapsed = collapsed.has(s.id);
  return (
    <Box sx={{ width: '100%', mt: 1, ml, border: '1px solid var(--color-divider)', borderRadius: 1, overflow: 'hidden', bgcolor: 'var(--color-panel)' }}>
      <Box sx={{ px: 1, py: 0.75, fontWeight: 700, color: 'var(--color-text-1)', display: 'flex', alignItems: 'center', gap: 0.5, cursor: 'pointer', background:
        level === 1 ? 'rgba(0,0,0,0.03)' : level === 2 ? 'rgba(0,0,0,0.02)' : 'transparent',
        borderBottom: '1px solid var(--color-divider)'
      }}>
        <IconButton size="small" onClick={(e) => { e.stopPropagation(); toggleCollapse(s.id); }}>
          {isCollapsed ? <ChevronRight fontSize="inherit" /> : <ExpandMore fontSize="inherit" />}
        </IconButton>
        <Box onClick={() => onSelectPage(Math.max(1, s.start_page))}>
          <Typography component="span" sx={{ color: 'var(--color-text-1)' }}>{s.title}</Typography>
        </Box>
        <Typography component="span" sx={{ fontSize: 12, color: 'var(--color-text-3)', ml: 1 }}>({s.start_page}–{s.end_page})</Typography>
      </Box>
      {!isCollapsed && (
        <Box sx={{ p: 1 }}>
          <Box sx={{ width: '100%', display: 'grid', gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', gap: 1 }}>
            {Array.from({ length: Math.max(0, Math.min(s.end_page, manifest.page_count) - s.start_page + 1) }).map((_, i) => {
              const p = s.start_page + i;
              return (
                <PageTile key={`p-${p}`} page={p} fetchSrc={() => fetchThumb(p)} selected={p === selectedPage} onClick={() => onSelectPage(p)} />
              );
            })}
          </Box>
        </Box>
      )}
      {!isCollapsed && node.children.length > 0 && (
        <Box sx={{ p: 1 }}>
          {node.children.map((child) => (
            <SectionTile key={child.sec.id} node={child} manifest={manifest} fetchThumb={fetchThumb} selectedPage={selectedPage} onSelectPage={onSelectPage} collapsed={collapsed} toggleCollapse={toggleCollapse} level={Math.max(1, Number(child.sec.level || level + 1))} />
          ))}
        </Box>
      )}
    </Box>
  );
};

function getCurrentSectionStart(outline: Outline | null, selectedPage: number): number {
  if (!outline || outline.sections.length === 0) return selectedPage;
  const secs = [...outline.sections].sort((a, b) => a.start_page - b.start_page);
  for (let i = 0; i < secs.length; i++) {
    const s = secs[i];
    const end = s.end_page ?? (i + 1 < secs.length ? secs[i + 1].start_page - 1 : Number.MAX_SAFE_INTEGER);
    if (selectedPage >= s.start_page && selectedPage <= end) return s.start_page;
  }
  return selectedPage;
}

function collectAllIds(sections: OutlineSection[]): string[] {
  const ids: string[] = [];
  for (const s of sections) ids.push(s.id);
  return ids;
}

const PageTile: React.FC<{
  page: number;
  selected: boolean;
  fetchSrc: () => Promise<string | undefined>;
  onClick: () => void;
}> = ({ page, selected, fetchSrc, onClick }) => {
  const [src, setSrc] = useState<string | undefined>(undefined);
  useEffect(() => { (async () => setSrc(await fetchSrc()))(); }, [fetchSrc, page]);
  return (
    <Box onClick={onClick} sx={{ width: '100%', minWidth: 0, display: 'flex', flexDirection: 'column', borderRadius: 1, overflow: 'hidden', cursor: 'pointer', border: selected ? '2px solid #1976d2' : '1px solid var(--color-divider)', boxShadow: selected ? '0 0 0 2px rgba(25,118,210,0.15) inset' : 'none', bgcolor: 'rgba(0,0,0,0.02)' }}>
      <Box sx={{ position: 'relative', width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', bgcolor: 'rgba(0,0,0,0.05)' }}>
        {src ? <img src={src} alt={`p${page}`} style={{ maxHeight: '100%', maxWidth: '100%', display: 'block' }} /> : <CircularProgress size={16} />}
        <Box sx={{ position: 'absolute', top: 6, right: 6, bgcolor: 'rgba(0,0,0,0.6)', color: '#fff', borderRadius: 1, px: 0.5, fontSize: 11, lineHeight: '16px' }}>{page}</Box>
      </Box>
    </Box>
  );
};

// Replaced old ThumbRow with PageTile-based grid tiles

export default CCFileDetailPanel;


