import React, { useState, useEffect, createElement } from 'react';
import { MDXProvider } from '@mdx-js/react';
import { compile } from '@mdx-js/mdx';
import * as runtime from 'react/jsx-runtime';
import { ComponentProps } from 'react';

interface CodeProps extends ComponentProps<'code'> {
  className?: string;
  children?: React.ReactNode;
}

interface BlockquoteProps extends ComponentProps<'blockquote'> { }

interface UlProps extends ComponentProps<'ul'> { }
interface OlProps extends ComponentProps<'ol'> { }

interface ListItemProps extends ComponentProps<'li'> { }

const components = {
  h1: (props: ComponentProps<'h1'>) => <h1 style={{ color: '#2563eb' }} {...props} />,
  h2: (props: ComponentProps<'h2'>) => <h2 style={{ color: '#1e40af' }} {...props} />,
  p: (props: ComponentProps<'p'>) => <p style={{ fontSize: '16px', lineHeight: '1.6' }} {...props} />,
  code: ({ className, children, ...props }: CodeProps) => (
    <code
      style={{
        backgroundColor: '#f3f4f6',
        padding: '2px 6px',
        borderRadius: '4px',
        fontFamily: 'monospace'
      }}
      {...props}
    >
      {children}
    </code>
  ),
  pre: (props: ComponentProps<'pre'>) => (
    <pre
      style={{
        backgroundColor: '#1f2937',
        color: '#f9fafb',
        padding: '16px',
        borderRadius: '8px',
        overflow: 'auto',
        fontFamily: 'monospace'
      }}
      {...props}
    />
  ),
  blockquote: (props: BlockquoteProps) => (
    <blockquote
      style={{
        borderLeft: '4px solid #e5e7eb',
        paddingLeft: '16px',
        margin: '16px 0',
        fontStyle: 'italic'
      }}
      {...props}
    />
  ),
  ul: (props: UlProps) => <ul style={{ paddingLeft: '20px' }} {...props} />,
  ol: (props: OlProps) => <ol style={{ paddingLeft: '20px' }} {...props} />,
  li: (props: ListItemProps) => <li style={{ marginBottom: '8px' }} {...props} />
};

const App = () => {
  const [Content, setContent] = useState<React.ComponentType | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [reloading, setReloading] = useState(false);

  useEffect(() => {
    const loadMDX = async () => {
      if (!loading) {
        setReloading(true);
      }
      try {
        const response = await fetch('/example.mdx?t=' + Date.now());
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const text = await response.text();

        const compiledCode = await compile(text, {
          outputFormat: 'function-body',
          development: import.meta.env.DEV,
        });

        const code = String(compiledCode);
        console.log('Raw compiled code:', code);

        try {
          // Define basic HTML components for missing ones
          const htmlComponents = {
            h3: (props: any) => <h3 style={{ color: '#374151' }} {...props} />,
            h4: (props: any) => <h4 style={{ color: '#4b5563' }} {...props} />,
            h5: (props: any) => <h5 style={{ color: '#6b7280' }} {...props} />,
            h6: (props: any) => <h6 style={{ color: '#9ca3af' }} {...props} />,
            a: (props: any) => <a style={{ color: '#2563eb', textDecoration: 'underline' }} {...props} />,
            img: (props: any) => <img style={{ maxWidth: '100%', height: 'auto' }} {...props} />,
            hr: (props: any) => <hr style={{ border: '1px solid #e5e7eb', margin: '16px 0' }} {...props} />,
            br: (props: any) => <br {...props} />,
            em: (props: any) => <em style={{ fontStyle: 'italic' }} {...props} />,
            strong: (props: any) => <strong style={{ fontWeight: 'bold' }} {...props} />,
            table: (props: any) => <table style={{ width: '100%', borderCollapse: 'collapse', margin: '16px 0' }} {...props} />,
            thead: (props: any) => <thead style={{ backgroundColor: '#f9fafb' }} {...props} />,
            tbody: (props: any) => <tbody {...props} />,
            tr: (props: any) => <tr style={{ borderBottom: '1px solid #e5e7eb' }} {...props} />,
            th: (props: any) => <th style={{ padding: '12px', textAlign: 'left', fontWeight: 'bold' }} {...props} />,
            td: (props: any) => <td style={{ padding: '12px' }} {...props} />,
            div: (props: any) => <div {...props} />,
            span: (props: any) => <span {...props} />,
          };

          // Merge all components
          const allComponents = { ...components, ...htmlComponents };

          const scope = {
            React,
            components: allComponents,
            createElement,
            Fragment: React.Fragment,
            jsx: runtime.jsx,
            jsxs: runtime.jsxs,
            // Include all components directly in scope
            h1: allComponents.h1,
            h2: allComponents.h2,
            h3: allComponents.h3,
            h4: allComponents.h4,
            h5: allComponents.h5,
            h6: allComponents.h6,
            p: allComponents.p,
            a: allComponents.a,
            img: allComponents.img,
            ul: allComponents.ul,
            ol: allComponents.ol,
            li: allComponents.li,
            blockquote: allComponents.blockquote,
            hr: allComponents.hr,
            br: allComponents.br,
            em: allComponents.em,
            strong: allComponents.strong,
            code: allComponents.code,
            pre: allComponents.pre,
            table: allComponents.table,
            thead: allComponents.thead,
            tbody: allComponents.tbody,
            tr: allComponents.tr,
            th: allComponents.th,
            td: allComponents.td,
            div: allComponents.div,
            span: allComponents.span,
          };

          const keys = Object.keys(scope);
          const values = Object.values(scope);

          // Try to evaluate the code using a more robust approach
          try {
            // First, try to execute as function body
            const fn1 = new Function(
              ...keys,
              `${code}; return MDXContent;`
            );
            const Component1 = fn1(...values);
            const MDXComponent1 = Component1.default || Component1;

            if (MDXComponent1) {
              setContent(() => MDXComponent1);
              setLoading(false);
              return;
            }
          } catch (e1) {
            console.log('First evaluation method failed, trying second...');
          }

          try {
            // Second, try to execute as function expression
            const fn2 = new Function(
              ...keys,
              `return ${code}`
            );
            const Component2 = fn2(...values);
            const MDXComponent2 = Component2.default || Component2;

            if (MDXComponent2) {
              setContent(() => MDXComponent2);
              setLoading(false);
              return;
            }
          } catch (e2) {
            console.log('Second evaluation method failed, trying third...');
          }

          try {
            // Third, try to execute directly with eval-like approach
            const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
            const fn3 = new AsyncFunction(
              ...keys,
              code
            );
            const result = await fn3(...values);
            const MDXComponent3 = result.default || result;

            if (MDXComponent3) {
              setContent(() => MDXComponent3);
              setLoading(false);
              return;
            }
          } catch (e3) {
            console.log('Third evaluation method failed');
          }

          throw new Error('All evaluation methods failed');
        } catch (evalError) {
          console.error('Evaluation error:', evalError);
          console.error('Compiled code sample:', code.substring(0, 500));
          const errorMessage = evalError instanceof Error ? evalError.message : String(evalError);
          throw new Error(`MDX evaluation failed: ${errorMessage}`);
        }
      } catch (err) {
        console.error('Error loading MDX:', err);
        setError(err instanceof Error ? err.message : String(err));
        setLoading(false);
      } finally {
        setReloading(false);
      }
    };

    loadMDX();

    // Set up interval for auto-reloading during development
    let intervalId: NodeJS.Timeout;
    if (import.meta.env.DEV) {
      intervalId = setInterval(loadMDX, 2000); // Check every 2 seconds
    }

    return () => {
      if (intervalId) {
        clearInterval(intervalId);
      }
    };
  }, [loading]);

  if (loading) {
    return (
      <div style={{ padding: '20px', textAlign: 'center' }}>
        <h1>MDX Viewer</h1>
        <p>Loading MDX content...</p>
      </div>
    );
  }

  if (error) {
    return (
      <div style={{ padding: '20px' }}>
        <h1>MDX Viewer</h1>
        <div style={{
          backgroundColor: '#fef2f2',
          border: '1px solid #fecaca',
          borderRadius: '8px',
          padding: '16px',
          color: '#dc2626'
        }}>
          <h3>Error loading MDX:</h3>
          <p>{error}</p>
        </div>
      </div>
    );
  }

  return (
    <MDXProvider components={components}>
      <div style={{
        maxWidth: '800px',
        margin: '0 auto',
        padding: '20px',
        fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
      }}>
        <div style={{ marginBottom: '32px', textAlign: 'center', position: 'relative' }}>
          <h1>MDX Viewer</h1>
          {reloading && (
            <div style={{
              position: 'absolute',
              top: '0',
              right: '0',
              backgroundColor: '#22c55e',
              color: 'white',
              padding: '4px 8px',
              borderRadius: '4px',
              fontSize: '12px',
              fontWeight: 'bold'
            }}>
              🔄 Reloading...
            </div>
          )}
        </div>
        {Content && <Content />}
      </div>
    </MDXProvider>
  );
};

export default App;