import { useState, useEffect, useRef, useCallback } from 'react';
import { useParams } from 'react-router-dom';
import { ConfigProvider, Layout, Typography, Spin, Result, Space, theme, Tag } from 'antd';
import {
  LockOutlined,
  EditOutlined,
  EyeOutlined,
  LinkOutlined,
} from '@ant-design/icons';
import axios from 'axios';
import Editor from '@monaco-editor/react';
import type { OnMount } from '@monaco-editor/react';
import type { editor as monacoEditor } from 'monaco-editor';
import { MonacoBinding } from 'y-monaco';
import { useDocShareCollaboration } from '@/hooks/useDocShareCollaboration';
import { CollaboratorAvatars } from '@/components/docs/CollaboratorAvatars';
import DocsEditorToolbar from '@/components/docs/DocsEditorToolbar';
import { SNIPPETS, applySnippet } from '@/components/docs/mkdocs-snippets';

const { Header, Content } = Layout;
const { Title, Text } = Typography;

interface ShareValidation {
  documentPath: string;
  documentName: string;
  canEdit: boolean;
  collabToken: string;
  guestIdentity: { id: string; name: string; color: string };
}

type PageState =
  | { status: 'loading' }
  | { status: 'ready'; data: ShareValidation }
  | { status: 'error'; code: string; message: string };

export default function SharedDocEditorPage() {
  const { shareToken } = useParams<{ shareToken: string }>();
  const [pageState, setPageState] = useState<PageState>({ status: 'loading' });

  const monacoEditorRef = useRef<monacoEditor.IStandaloneCodeEditor | null>(null);
  const monacoRef = useRef<typeof import('monaco-editor') | null>(null);
  const monacoBindingRef = useRef<MonacoBinding | null>(null);
  const [editorReady, setEditorReady] = useState(false);

  // Extract data for hooks (hooks must be called unconditionally)
  const shareData = pageState.status === 'ready' ? pageState.data : null;

  const collab = useDocShareCollaboration(
    shareData?.documentPath ?? null,
    !!shareData,
    shareData?.collabToken ?? null,
    shareData?.guestIdentity ?? null,
  );

  // Validate share token on mount
  useEffect(() => {
    if (!shareToken) {
      setPageState({ status: 'error', code: 'INVALID', message: 'No share token provided' });
      return;
    }

    let cancelled = false;

    async function validate() {
      try {
        const { data } = await axios.get<ShareValidation>(
          `/api/docs-access/share/public/${shareToken}`,
        );
        if (!cancelled) {
          setPageState({ status: 'ready', data });
        }
      } catch (err: unknown) {
        if (cancelled) return;
        const resp = (err as { response?: { data?: { error?: { message?: string; code?: string } }; status?: number } })?.response;
        const errorCode = resp?.data?.error?.code || 'UNKNOWN';
        const errorMessage = resp?.data?.error?.message || 'Failed to validate share link';

        if (resp?.status === 404) {
          setPageState({ status: 'error', code: errorCode, message: 'This share link was not found.' });
        } else if (resp?.status === 410) {
          setPageState({
            status: 'error',
            code: errorCode,
            message: errorCode === 'SHARE_LINK_REVOKED'
              ? 'This share link has been revoked by the document owner.'
              : 'This share link has expired.',
          });
        } else if (resp?.status === 429) {
          setPageState({ status: 'error', code: errorCode, message: 'This share link has reached its maximum number of uses.' });
        } else {
          setPageState({ status: 'error', code: errorCode, message: errorMessage });
        }
      }
    }

    validate();
    return () => { cancelled = true; };
  }, [shareToken]);

  // Monaco editor mount handler
  const handleEditorMount: OnMount = useCallback((editor, monaco) => {
    monacoEditorRef.current = editor;
    monacoRef.current = monaco;
    setEditorReady(true);

    // Register Ctrl+B / Ctrl+I keyboard shortcuts for markdown formatting
    SNIPPETS.filter(s => s.keybinding).forEach(snippet => {
      const kb = snippet.keybinding === 'ctrl+b'
        ? monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyB
        : monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI;
      editor.addAction({
        id: `mkdocs.${snippet.id}`,
        label: snippet.label,
        keybindings: [kb],
        run: (ed) => applySnippet(ed as monacoEditor.IStandaloneCodeEditor, snippet, monaco),
      });
    });
  }, []);

  // MonacoBinding effect: binds Y.Text to Monaco editor when both are ready
  useEffect(() => {
    if (monacoBindingRef.current) {
      monacoBindingRef.current.destroy();
      monacoBindingRef.current = null;
    }

    const ed = monacoEditorRef.current;
    if (!collab.active || !collab.yText || !collab.provider || !ed || !editorReady) return;

    const model = ed.getModel();
    if (!model) return;

    const binding = new MonacoBinding(
      collab.yText,
      model,
      new Set([ed]),
      collab.provider.awareness,
    );
    monacoBindingRef.current = binding;

    return () => {
      binding.destroy();
      monacoBindingRef.current = null;
    };
  }, [collab.active, collab.yText, collab.provider, editorReady]);

  // Determine file language for Monaco
  const getLanguage = (path: string): string => {
    if (path.endsWith('.md')) return 'markdown';
    if (path.endsWith('.yml') || path.endsWith('.yaml')) return 'yaml';
    if (path.endsWith('.json')) return 'json';
    if (path.endsWith('.html')) return 'html';
    if (path.endsWith('.css')) return 'css';
    if (path.endsWith('.js') || path.endsWith('.ts')) return 'typescript';
    if (path.endsWith('.py')) return 'python';
    return 'plaintext';
  };

  return (
    <ConfigProvider
      theme={{
        algorithm: theme.darkAlgorithm,
        token: {
          colorPrimary: '#3498db',
          colorBgBase: '#0d1b2a',
          colorBgContainer: '#1b2838',
        },
      }}
    >
      <Layout style={{ height: '100vh', background: '#0d1b2a' }}>
        {/* Header */}
        <Header
          style={{
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'space-between',
            background: '#1b2838',
            borderBottom: '1px solid rgba(255,255,255,0.08)',
            padding: '0 24px',
            height: 56,
          }}
        >
          <Space align="center">
            <LinkOutlined style={{ fontSize: 18, color: '#3498db' }} />
            <Title level={5} style={{ margin: 0, color: '#fff' }}>
              Shared Document
            </Title>
            {shareData && (
              <>
                <Text type="secondary" style={{ fontSize: 13 }}>
                  {shareData.documentName}
                </Text>
                <Tag
                  icon={shareData.canEdit ? <EditOutlined /> : <EyeOutlined />}
                  color={shareData.canEdit ? 'blue' : 'default'}
                >
                  {shareData.canEdit ? 'Edit' : 'View only'}
                </Tag>
              </>
            )}
          </Space>

          <Space align="center">
            {shareData && (
              <CollaboratorAvatars
                collaborators={collab.collaborators}
                connected={collab.connected}
              />
            )}
          </Space>
        </Header>

        {/* Content */}
        <Content style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
          {pageState.status === 'loading' && (
            <div
              style={{
                flex: 1,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
              }}
            >
              <Space direction="vertical" align="center">
                <Spin size="large" />
                <Text type="secondary">Validating share link...</Text>
              </Space>
            </div>
          )}

          {pageState.status === 'error' && (
            <div
              style={{
                flex: 1,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
              }}
            >
              <Result
                status={
                  pageState.code === 'SHARE_LINK_REVOKED' || pageState.code === 'SHARE_LINK_EXPIRED'
                    ? 'warning'
                    : pageState.code === 'SHARE_LINK_NOT_FOUND'
                      ? '404'
                      : 'error'
                }
                icon={
                  pageState.code === 'SHARE_LINK_REVOKED' ? (
                    <LockOutlined style={{ color: '#faad14' }} />
                  ) : undefined
                }
                title={
                  pageState.code === 'SHARE_LINK_EXPIRED'
                    ? 'Link Expired'
                    : pageState.code === 'SHARE_LINK_REVOKED'
                      ? 'Link Revoked'
                      : pageState.code === 'SHARE_LINK_NOT_FOUND'
                        ? 'Not Found'
                        : 'Error'
                }
                subTitle={pageState.message}
              />
            </div>
          )}

          {pageState.status === 'ready' && (
            <div style={{ flex: 1, display: 'flex', flexDirection: 'column', position: 'relative' }}>
              {!collab.active && (
                <div
                  style={{
                    position: 'absolute',
                    inset: 0,
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    zIndex: 10,
                    background: 'rgba(13,27,42,0.8)',
                  }}
                >
                  <Space direction="vertical" align="center">
                    <Spin size="large" />
                    <Text type="secondary">Connecting to collaboration session...</Text>
                  </Space>
                </div>
              )}

              {/* Formatting toolbar for editable markdown files */}
              {shareData?.canEdit && shareData.documentPath.endsWith('.md') && (
                <DocsEditorToolbar
                  editorRef={monacoEditorRef}
                  monacoRef={monacoRef}
                  background="#1b2838"
                />
              )}

              <div style={{ flex: 1, minHeight: 0 }}>
                <Editor
                  height="100%"
                  language={getLanguage(shareData?.documentPath ?? '')}
                  theme="vs-dark"
                  options={{
                    readOnly: !shareData?.canEdit,
                    minimap: { enabled: false },
                    wordWrap: 'on',
                    lineNumbers: 'on',
                    fontSize: 14,
                    scrollBeyondLastLine: false,
                    automaticLayout: true,
                    padding: { top: 12 },
                  }}
                  onMount={handleEditorMount}
                />
              </div>
            </div>
          )}
        </Content>
      </Layout>
    </ConfigProvider>
  );
}
