import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Link from '@tiptap/extension-link';
import Image from '@tiptap/extension-image';
import Placeholder from '@tiptap/extension-placeholder';
import { Node } from '@tiptap/core';
import { Button } from '@/components/ui/button';
import {
  Bold, Italic, List, ListOrdered, Quote, Link as LinkIcon,
  Image as ImageIcon, Heading1, Heading2, Undo, Redo,
  Maximize2, Minimize2, MousePointer, Square
} from 'lucide-react';
import { cn } from '@/lib/utils';
import { useCallback, useEffect, useState } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { toast } from '@/hooks/use-toast';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';

interface RichTextEditorProps {
  content: string;
  onChange: (html: string) => void;
  placeholder?: string;
  className?: string;
}

// Custom Image extension with resize support
const ResizableImage = Image.extend({
  addAttributes() {
    return {
      ...this.parent?.(),
      width: {
        default: null,
        parseHTML: element => element.getAttribute('width') || element.style.width?.replace('px', ''),
        renderHTML: attributes => {
          if (!attributes.width) return {};
          return { width: attributes.width, style: `width: ${attributes.width}px` };
        },
      },
      height: {
        default: null,
        parseHTML: element => element.getAttribute('height') || element.style.height?.replace('px', ''),
        renderHTML: attributes => {
          if (!attributes.height) return {};
          return { height: attributes.height, style: `height: ${attributes.height}px` };
        },
      },
    };
  },
});

// Custom Button extension for email templates
const EmailButton = Node.create({
  name: 'emailButton',

  group: 'block',

  addAttributes() {
    return {
      url: {
        default: '#',
        parseHTML: element => element.getAttribute('data-url') || '#',
        renderHTML: attributes => ({
          'data-url': attributes.url,
        }),
      },
      text: {
        default: 'Button',
        parseHTML: element => element.textContent || 'Button',
        renderHTML: attributes => ({}),
      },
      fullWidth: {
        default: false,
        parseHTML: element => element.classList.contains('btn-full'),
        renderHTML: attributes => ({
          class: attributes.fullWidth ? 'btn btn-full' : 'btn',
        }),
      },
    };
  },

  parseHTML() {
    return [
      {
        tag: 'div[data-email-button]',
      },
    ];
  },

  renderHTML({ HTMLAttributes, node }) {
    const { url, text, fullWidth } = node.attrs;
    return [
      'p',
      { style: 'margin-top: 20px; text-align: center;' },
      [
        'a',
        {
          href: url,
          class: fullWidth ? 'btn btn-full' : 'btn',
          'data-email-button': '',
          style: `
            display: inline-block;
            background-color: #000;
            color: #FFF !important;
            padding: 14px 28px;
            font-weight: 700;
            text-transform: uppercase;
            text-decoration: none !important;
            font-size: 16px;
            border: 2px solid #000;
            box-shadow: 4px 4px 0px 0px #000000;
            margin: 10px 0;
            transition: all 0.1s;
            text-align: center;
            ${fullWidth ? 'width: 100%; box-sizing: border-box;' : ''}
          `,
        },
        text || 'Button',
      ],
    ];
  },

  addNodeView() {
    return ({ node, editor }) => {
      const dom = document.createElement('div');
      dom.style.cssText = 'margin: 10px 0; border: 2px dashed #007acc; padding: 8px; border-radius: 4px; background: #f0f9ff;';

      const button = document.createElement('a');
      button.href = node.attrs.url;
      button.textContent = node.attrs.text;
      button.style.cssText = `
        display: inline-block;
        background-color: #000;
        color: #FFF;
        padding: 14px 28px;
        font-weight: 700;
        text-transform: uppercase;
        text-decoration: none;
        font-size: 16px;
        border: 2px solid #000;
        box-shadow: 4px 4px 0px 0px #000000;
        cursor: pointer;
        ${node.attrs.fullWidth ? 'width: 100%; text-align: center; box-sizing: border-box;' : ''}
      `;

      dom.appendChild(button);

      return {
        dom,
        destroy: () => {
          dom.remove();
        },
      };
    };
  },
});

// Custom OTP Box extension
const OTPBox = Node.create({
  name: 'otpBox',

  group: 'block',

  addAttributes() {
    return {
      code: {
        default: '123-456',
        parseHTML: element => element.getAttribute('data-code') || '123-456',
        renderHTML: attributes => ({
          'data-code': attributes.code,
        }),
      },
    };
  },

  parseHTML() {
    return [
      {
        tag: 'div[data-otp-box]',
      },
    ];
  },

  renderHTML({ HTMLAttributes, node }) {
    const { code } = node.attrs;
    return [
      'div',
      {
        'data-otp-box': '',
        style: `
          background-color: #F4F4F5;
          border: 2px dashed #000;
          padding: 20px;
          text-align: center;
          margin: 20px 0;
          letter-spacing: 5px;
          font-family: 'Courier New', Courier, monospace;
          font-size: 32px;
          font-weight: 700;
          color: #000;
        `,
      },
      code,
    ];
  },

  addNodeView() {
    return ({ node, editor }) => {
      const dom = document.createElement('div');
      dom.style.cssText = 'margin: 10px 0; border: 2px dashed #007acc; padding: 8px; border-radius: 4px; background: #f0f9ff;';
      dom.innerHTML = `
        <div style="text-align: center; font-size: 12px; color: #007acc; margin-bottom: 4px;">OTP Box: ${node.attrs.code}</div>
        <div style="
          background-color: #F4F4F5;
          border: 2px dashed #000;
          padding: 20px;
          letter-spacing: 5px;
          font-family: 'Courier New', Courier, monospace;
          font-size: 32px;
          font-weight: 700;
          color: #000;
          text-align: center;
        ">${node.attrs.code}</div>
      `;

      return {
        dom,
        destroy: () => {
          dom.remove();
        },
      };
    };
  },
});


export function RichTextEditor({ content, onChange, placeholder = 'Tulis konten...', className }: RichTextEditorProps) {
  const [uploading, setUploading] = useState(false);
  const [selectedImage, setSelectedImage] = useState<{ src: string; width?: number; height?: number } | null>(null);
  const [imageWidth, setImageWidth] = useState('');
  const [imageHeight, setImageHeight] = useState('');

  const editor = useEditor({
    extensions: [
      StarterKit,
      Link.configure({
        openOnClick: false,
        HTMLAttributes: {
          class: 'text-primary underline',
        },
      }),
      ResizableImage.configure({
        HTMLAttributes: {
          class: 'max-w-full h-auto rounded-md cursor-pointer',
        },
      }),
      EmailButton,
      OTPBox,
      Placeholder.configure({
        placeholder,
      }),
    ],
    content,
    onUpdate: ({ editor }) => {
      onChange(editor.getHTML());
    },
    onSelectionUpdate: ({ editor }) => {
      // Check if an image is selected
      const { selection } = editor.state;
      const node = editor.state.doc.nodeAt(selection.from);
      if (node?.type.name === 'image') {
        setSelectedImage({
          src: node.attrs.src,
          width: node.attrs.width,
          height: node.attrs.height,
        });
        setImageWidth(node.attrs.width?.toString() || '');
        setImageHeight(node.attrs.height?.toString() || '');
      } else {
        setSelectedImage(null);
      }
    },
  });

  // Sync content when it changes externally
  useEffect(() => {
    if (editor && content !== editor.getHTML()) {
      editor.commands.setContent(content || '');
    }
  }, [content, editor]);

  const addLink = useCallback(() => {
    if (!editor) return;
    const url = window.prompt('Masukkan URL:');
    if (url) {
      editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run();
    }
  }, [editor]);

  const addButton = useCallback(() => {
    if (!editor) return;
    const text = window.prompt('Teks Button:') || 'Button';
    const url = window.prompt('URL Button:') || '#';
    const fullWidth = window.confirm('Gunakan lebar penuh?');

    editor.chain().focus().insertContent({
      type: 'emailButton',
      attrs: {
        text,
        url,
        fullWidth,
      },
    }).run();
  }, [editor]);

  const addOTPBox = useCallback(() => {
    if (!editor) return;
    const code = window.prompt('Kode OTP (contoh: 123-456):') || '123-456';

    editor.chain().focus().insertContent({
      type: 'otpBox',
      attrs: {
        code,
      },
    }).run();
  }, [editor]);

  
  const uploadImageToStorage = async (file: File): Promise<string | null> => {
    try {
      const fileExt = file.name.split('.').pop();
      const fileName = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}.${fileExt}`;
      const filePath = `editor-images/${fileName}`;

      const { data, error } = await supabase.storage
        .from('content')
        .upload(filePath, file, {
          cacheControl: '3600',
          upsert: false,
        });

      if (error) {
        console.error('Storage upload error:', error);
        // Fall back to base64 if storage fails
        return null;
      }

      const { data: urlData } = supabase.storage.from('content').getPublicUrl(filePath);
      return urlData.publicUrl;
    } catch (err) {
      console.error('Upload error:', err);
      return null;
    }
  };

  const convertToDataUrl = (file: File): Promise<string> => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result as string);
      reader.onerror = reject;
      reader.readAsDataURL(file);
    });
  };

  const handleImageUpload = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file || !editor) return;

    setUploading(true);
    
    // Try to upload to storage first
    let imageUrl = await uploadImageToStorage(file);
    
    // Fall back to base64 if storage upload fails
    if (!imageUrl) {
      toast({
        title: 'Info',
        description: 'Menggunakan penyimpanan lokal untuk gambar',
      });
      imageUrl = await convertToDataUrl(file);
    }

    editor.chain().focus().setImage({ src: imageUrl }).run();
    setUploading(false);
    
    // Reset input
    e.target.value = '';
  }, [editor]);

  const handlePaste = useCallback(async (e: React.ClipboardEvent) => {
    const items = e.clipboardData?.items;
    if (!items || !editor) return;

    for (const item of Array.from(items)) {
      if (item.type.startsWith('image/')) {
        e.preventDefault();
        const file = item.getAsFile();
        if (!file) continue;

        setUploading(true);
        
        let imageUrl = await uploadImageToStorage(file);
        if (!imageUrl) {
          imageUrl = await convertToDataUrl(file);
        }

        editor.chain().focus().setImage({ src: imageUrl }).run();
        setUploading(false);
        break;
      }
    }
  }, [editor]);

  const updateImageSize = useCallback(() => {
    if (!editor || !selectedImage) return;
    
    const width = imageWidth ? parseInt(imageWidth) : null;
    const height = imageHeight ? parseInt(imageHeight) : null;

    editor.chain().focus().updateAttributes('image', { width, height }).run();
    
    toast({ title: 'Berhasil', description: 'Ukuran gambar diperbarui' });
  }, [editor, selectedImage, imageWidth, imageHeight]);

  const setPresetSize = useCallback((size: 'small' | 'medium' | 'large' | 'full') => {
    if (!editor) return;
    
    const sizes = {
      small: { width: 200, height: null },
      medium: { width: 400, height: null },
      large: { width: 600, height: null },
      full: { width: null, height: null },
    };

    const { width, height } = sizes[size];
    editor.chain().focus().updateAttributes('image', { width, height }).run();
    setImageWidth(width?.toString() || '');
    setImageHeight(height?.toString() || '');
  }, [editor]);

  if (!editor) return null;

  return (
    <div className={cn("border-2 border-border rounded-md", className)}>
      <div className="flex flex-wrap gap-1 p-2 border-b-2 border-border bg-muted">
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => editor.chain().focus().toggleBold().run()}
          className={editor.isActive('bold') ? 'bg-accent' : ''}
        >
          <Bold className="w-4 h-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => editor.chain().focus().toggleItalic().run()}
          className={editor.isActive('italic') ? 'bg-accent' : ''}
        >
          <Italic className="w-4 h-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
          className={editor.isActive('heading', { level: 1 }) ? 'bg-accent' : ''}
        >
          <Heading1 className="w-4 h-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
          className={editor.isActive('heading', { level: 2 }) ? 'bg-accent' : ''}
        >
          <Heading2 className="w-4 h-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => editor.chain().focus().toggleBulletList().run()}
          className={editor.isActive('bulletList') ? 'bg-accent' : ''}
        >
          <List className="w-4 h-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => editor.chain().focus().toggleOrderedList().run()}
          className={editor.isActive('orderedList') ? 'bg-accent' : ''}
        >
          <ListOrdered className="w-4 h-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => editor.chain().focus().toggleBlockquote().run()}
          className={editor.isActive('blockquote') ? 'bg-accent' : ''}
        >
          <Quote className="w-4 h-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={addLink}
          className={editor.isActive('link') ? 'bg-accent' : ''}
        >
          <LinkIcon className="w-4 h-4" />
        </Button>

        {/* Email Components Separator */}
        <div className="w-px h-6 bg-border mx-1" />

        {/* Email Component Buttons */}
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={addButton}
          title="Tambah Email Button"
        >
          <MousePointer className="w-4 h-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={addOTPBox}
          title="Tambah OTP Box"
        >
          <Square className="w-4 h-4" />
        </Button>
  
        {/* Image Upload Separator */}
        <div className="w-px h-6 bg-border mx-1" />

        <label>
          <Button type="button" variant="ghost" size="sm" asChild disabled={uploading}>
            <span className={uploading ? 'opacity-50' : ''}>
              <ImageIcon className="w-4 h-4" />
            </span>
          </Button>
          <input
            type="file"
            accept="image/*"
            onChange={handleImageUpload}
            className="hidden"
            disabled={uploading}
          />
        </label>

        {/* Image resize popover */}
        {selectedImage && (
          <Popover>
            <PopoverTrigger asChild>
              <Button type="button" variant="ghost" size="sm" className="bg-accent">
                <Maximize2 className="w-4 h-4" />
              </Button>
            </PopoverTrigger>
            <PopoverContent className="w-64">
              <div className="space-y-4">
                <h4 className="font-medium">Ukuran Gambar</h4>
                <div className="grid grid-cols-4 gap-2">
                  <Button type="button" variant="outline" size="sm" onClick={() => setPresetSize('small')}>S</Button>
                  <Button type="button" variant="outline" size="sm" onClick={() => setPresetSize('medium')}>M</Button>
                  <Button type="button" variant="outline" size="sm" onClick={() => setPresetSize('large')}>L</Button>
                  <Button type="button" variant="outline" size="sm" onClick={() => setPresetSize('full')}>Full</Button>
                </div>
                <div className="grid grid-cols-2 gap-2">
                  <div>
                    <Label className="text-xs">Lebar (px)</Label>
                    <Input
                      type="number"
                      value={imageWidth}
                      onChange={(e) => setImageWidth(e.target.value)}
                      placeholder="Auto"
                      className="h-8"
                    />
                  </div>
                  <div>
                    <Label className="text-xs">Tinggi (px)</Label>
                    <Input
                      type="number"
                      value={imageHeight}
                      onChange={(e) => setImageHeight(e.target.value)}
                      placeholder="Auto"
                      className="h-8"
                    />
                  </div>
                </div>
                <Button type="button" size="sm" onClick={updateImageSize} className="w-full">
                  Terapkan
                </Button>
              </div>
            </PopoverContent>
          </Popover>
        )}

        <div className="flex-1" />
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => editor.chain().focus().undo().run()}
          disabled={!editor.can().undo()}
        >
          <Undo className="w-4 h-4" />
        </Button>
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => editor.chain().focus().redo().run()}
          disabled={!editor.can().redo()}
        >
          <Redo className="w-4 h-4" />
        </Button>
      </div>
      <div onPaste={handlePaste}>
        <EditorContent 
          editor={editor} 
          className="prose prose-sm max-w-none p-4 min-h-[200px] focus:outline-none [&_.ProseMirror]:outline-none [&_.ProseMirror]:min-h-[180px] [&_img]:cursor-pointer [&_img.ProseMirror-selectednode]:ring-2 [&_img.ProseMirror-selectednode]:ring-primary"
        />
      </div>
      {uploading && (
        <div className="p-2 text-sm text-muted-foreground text-center border-t border-border">
          Mengunggah gambar...
        </div>
      )}
    </div>
  );
}
