import { useRef, useState } from 'react';
import {
  AlignLeft,
  Book,
  BookOpen,
  Braces,
  Code2,
  Download,
  Eye,
  Hash,
  Image as ImageIcon,
  Loader2,
  Pencil,
  Save,
  SlidersHorizontal,
  Terminal,
  X,
} from 'lucide-react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import CodeMirror, { EditorView } from '@uiw/react-codemirror';
import { oneDark } from '@codemirror/theme-one-dark';
import HexEditor from './HexEditor';
import CodeEditor from './CodeEditor';
import ConfigEditor from './ConfigEditor';
import type { EntryInfo } from '../webdav';

export type ViewMode = 'text' | 'markdown' | 'json' | 'xml' | 'hex' | 'image' | 'config' | 'code' | 'doc';

const VIEWER_LABEL: Record<ViewMode, string> = {
  code: 'Code', text: 'Text', markdown: 'Markdown', json: 'JSON', xml: 'HTML/XML',
  hex: 'Hex', image: 'Image', config: 'Config', doc: 'Document',
};

const EXT_TO_LANG: Record<string, string> = {
  asm: 'nasm', s: 'nasm', bas: 'basic',
  js: 'javascript', ts: 'typescript', jsx: 'jsx', tsx: 'tsx',
  css: 'css', scss: 'scss',
  py: 'python', c: 'c', cpp: 'cpp', h: 'cpp', hpp: 'cpp',
  lua: 'lua', sh: 'bash', bash: 'bash',
  php: 'php', rb: 'ruby', rs: 'rust', go: 'go',
  java: 'java', cs: 'csharp', kt: 'kotlin', sql: 'sql', pl: 'perl',
};

function ViewerModeIcon({ mode, className }: { mode: ViewMode; className?: string }) {
  const cls = className ?? 'w-4 h-4';
  switch (mode) {
    case 'text':     return <AlignLeft className={cls} />;
    case 'markdown': return <BookOpen  className={cls} />;
    case 'json':     return <Braces    className={cls} />;
    case 'code':     return <Terminal  className={cls} />;
    case 'xml':      return <Code2     className={cls} />;
    case 'hex':      return <Hash      className={cls} />;
    case 'image':    return <ImageIcon        className={cls} />;
    case 'config':   return <SlidersHorizontal className={cls} />;
    case 'doc':      return <Book      className={cls} />;
  }
}

function MarkdownViewer({ text }: { text: string }) {
  return (
    <div className="p-6 overflow-auto h-full text-neutral-200 text-sm leading-relaxed">
      <ReactMarkdown
        remarkPlugins={[remarkGfm]}
        components={{
          h1: ({ children }) => <h1 className="text-2xl font-bold mt-6 mb-3 text-white border-b border-neutral-700 pb-2">{children}</h1>,
          h2: ({ children }) => <h2 className="text-xl font-bold mt-5 mb-2 text-white">{children}</h2>,
          h3: ({ children }) => <h3 className="text-base font-semibold mt-4 mb-1 text-white">{children}</h3>,
          p:  ({ children }) => <p className="my-2">{children}</p>,
          a:  ({ href, children }) => <a href={href} className="text-blue-400 underline" target="_blank" rel="noopener noreferrer">{children}</a>,
          code: ({ className, children, ...props }) => {
            const match = /language-(\w+)/.exec(className ?? '');
            const inline = !match && !String(children).includes('\n');
            return inline
              ? <code className="bg-neutral-700 text-green-300 rounded px-1 text-xs font-mono" {...props}>{children}</code>
              : (
                <div className="my-3 rounded overflow-hidden text-xs">
                  <SyntaxHighlighter
                    language={match?.[1] ?? 'text'}
                    style={vscDarkPlus}
                    customStyle={{ margin: 0, background: '#1a1a1a' }}
                    PreTag="div"
                  >
                    {String(children).replace(/\n$/, '')}
                  </SyntaxHighlighter>
                </div>
              );
          },
          pre:        ({ children }) => <>{children}</>,
          blockquote: ({ children }) => <blockquote className="border-l-4 border-neutral-500 pl-4 my-2 text-neutral-400 italic">{children}</blockquote>,
          ul:  ({ children }) => <ul className="list-disc pl-5 my-2 space-y-1">{children}</ul>,
          ol:  ({ children }) => <ol className="list-decimal pl-5 my-2 space-y-1">{children}</ol>,
          li:  ({ children }) => <li>{children}</li>,
          hr:  ()            => <hr className="border-neutral-600 my-4" />,
          table:    ({ children }) => <table className="border-collapse my-3 text-sm w-full">{children}</table>,
          th: ({ children }) => <th className="border border-neutral-600 px-3 py-1 bg-neutral-800 font-semibold text-left">{children}</th>,
          td: ({ children }) => <td className="border border-neutral-600 px-3 py-1">{children}</td>,
          strong: ({ children }) => <strong className="text-white font-semibold">{children}</strong>,
          img: ({ src, alt }) => <img src={src} alt={alt} className="max-w-full my-2 rounded" />,
        }}
      >
        {text}
      </ReactMarkdown>
    </div>
  );
}

const CM_THEME = EditorView.theme({
  '&': { height: '100%', background: '#0a0a0a' },
  '.cm-scroller': { overflow: 'auto', fontFamily: 'ui-monospace,monospace', fontSize: '12px', lineHeight: '1.5' },
  '.cm-content': { padding: '12px 0' },
  '.cm-focused': { outline: 'none' },
});

function MarkdownEditor({ text, onSave }: { text: string; onSave?: (s: string) => Promise<void> }) {
  const [editMode, setEditMode]         = useState(false);
  const [editInitText, setEditInitText] = useState('');
  const [saving, setSaving]             = useState(false);
  const editorViewRef = useRef<EditorView | null>(null);

  const save = async () => {
    if (!editorViewRef.current || !onSave) return;
    setSaving(true);
    try { await onSave(editorViewRef.current.state.doc.toString()); }
    finally { setSaving(false); }
  };

  return (
    <div className="flex flex-col h-full">
      <div className="flex items-center gap-2 px-3 py-1.5 bg-neutral-900 border-b border-neutral-700 flex-shrink-0 text-xs">
        {onSave && (
          <button
            onClick={() => { if (!editMode) setEditInitText(text); setEditMode(v => !v); }}
            className={editMode
              ? 'px-2 py-1 rounded bg-amber-600 text-white inline-flex items-center gap-1'
              : 'px-2 py-1 rounded bg-neutral-700 text-neutral-300 hover:bg-neutral-600 inline-flex items-center gap-1'}
          >
            {editMode ? <><Eye className="w-3.5 h-3.5" /> View</> : <><Pencil className="w-3.5 h-3.5" /> Edit</>}
          </button>
        )}
        {editMode && onSave && (
          <button onClick={() => void save()} disabled={saving}
            className="px-2 py-1 rounded bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50 inline-flex items-center gap-1">
            <Save className="w-3.5 h-3.5" /> {saving ? 'Saving…' : 'Save'}
          </button>
        )}
        {editMode && <span className="text-neutral-600 ml-auto">Ctrl+Z/Y undo · Ctrl+F search</span>}
      </div>
      {editMode ? (
        <div className="flex-1 overflow-hidden">
          <CodeMirror
            value={editInitText}
            extensions={[CM_THEME]}
            theme={oneDark}
            height="100%"
            onCreateEditor={v => { editorViewRef.current = v; }}
          />
        </div>
      ) : (
        <MarkdownViewer text={text} />
      )}
    </div>
  );
}

export interface MediaViewerEditorProps {
  entry: EntryInfo;
  mode: ViewMode;
  availableModes: ViewMode[];
  text: string | null;
  imgUrl: string | null;
  hexData: Uint8Array | null;
  loading: boolean;
  onClose: () => void;
  onSwitchMode: (mode: ViewMode) => void;
  onSave: (content: string | Uint8Array) => Promise<void>;
  onDownload: () => void;
}

export default function MediaViewerEditor({
  entry, mode, availableModes, text, imgUrl, hexData, loading,
  onClose, onSwitchMode, onSave, onDownload,
}: MediaViewerEditorProps) {
  return (
    <div className="fixed inset-0 bg-neutral-950 z-50 flex flex-col">
      {/* Title + mode switcher */}
      <div className="bg-neutral-900 flex items-center px-4 py-2 gap-3 border-b border-neutral-700 flex-shrink-0">
        <button onClick={onClose} className="p-1.5 rounded hover:bg-neutral-700">
          <X className="w-5 h-5 text-white" />
        </button>
        <span className="font-medium truncate flex-1 text-sm text-white">{entry.name}</span>
        <div className="flex items-center gap-1">
          {availableModes.map(m => (
            <button
              key={m}
              onClick={() => onSwitchMode(m)}
              title={VIEWER_LABEL[m]}
              className={`px-2 py-1 rounded text-xs inline-flex items-center gap-1 transition-colors ${
                mode === m
                  ? 'bg-blue-600 text-white'
                  : 'text-neutral-400 hover:bg-neutral-700 hover:text-white'
              }`}
            >
              <ViewerModeIcon mode={m} className="w-3.5 h-3.5" />
              <span className="hidden sm:inline">{VIEWER_LABEL[m]}</span>
            </button>
          ))}
        </div>
        <button onClick={onDownload} className="p-1.5 rounded hover:bg-neutral-700 text-neutral-300 hover:text-white" title="Download">
          <Download className="w-4 h-4" />
        </button>
      </div>

      <div className="flex-1 overflow-hidden bg-neutral-950">
        {loading && (
          <div className="h-full flex items-center justify-center gap-2 text-neutral-400">
            <Loader2 className="w-5 h-5 animate-spin" /> Loading…
          </div>
        )}
        {!loading && mode === 'image' && imgUrl && (
          <div className="h-full flex items-center justify-center overflow-auto p-4">
            <img src={imgUrl} alt={entry.name} className="max-w-full max-h-full object-contain" />
          </div>
        )}
        {!loading && mode === 'hex' && hexData && (
          <HexEditor key={entry.path} data={hexData} onSave={d => void onSave(d)} />
        )}
        {!loading && mode === 'markdown' && text !== null && (
          <MarkdownEditor key={entry.path} text={text} onSave={s => onSave(s)} />
        )}
        {!loading && (mode === 'text' || mode === 'json' || mode === 'xml') && text !== null && (
          <CodeEditor key={entry.path} text={text} mode={mode} onSave={s => onSave(s)} />
        )}
        {!loading && mode === 'config' && text !== null && (
          <ConfigEditor key={entry.path} text={text} onSave={s => onSave(s)} />
        )}
        {!loading && mode === 'code' && text !== null && (
          <CodeEditor
            key={entry.path}
            text={text}
            mode="code"
            syntaxHighlightLang={EXT_TO_LANG[entry.name.split('.').pop()?.toLowerCase() ?? ''] ?? 'text'}
            onSave={s => onSave(s)}
          />
        )}
      </div>
    </div>
  );
}
