import { useState, useEffect, useRef } from 'react';
import { X, Minus, Maximize2, Paperclip, Image, Link2, Smile, Loader2 } from 'lucide-react';
import { useAuth } from '@/contexts/AuthContext';
import { RichTextEditor } from './RichTextEditor';
import { ContactAutocomplete } from './ContactAutocomplete';
import { TrackingToggle } from './TrackingToggle';
import { QuotedMessages } from './QuotedMessages';
import { Contact, contactService } from '@/services/ContactService';
import type { Email } from '@/types';

interface ComposeModalProps {
  isOpen: boolean;
  onClose: () => void;
  onSend?: (
    to: string,
    subject: string,
    body: string,
    threadingMetadata?: {
      inReplyTo: string;
      references: string[];
    }
  ) => Promise<void>;
  sending?: boolean;
  replyTo?: Email | null;
  forwardEmail?: Email | null;
  onOptimisticUpdate?: (email: Email) => void;
}

export function ComposeModal({ isOpen, onClose, onSend, sending, replyTo, forwardEmail, onOptimisticUpdate }: ComposeModalProps) {
  const { getToken } = useAuth();
  const [to, setTo] = useState('');
  const [cc, setCc] = useState('');
  const [bcc, setBcc] = useState('');
  const [showCc, setShowCc] = useState(false);
  const [showBcc, setShowBcc] = useState(false);
  const [subject, setSubject] = useState('');
  const [body, setBody] = useState('');
  const [isMinimized, setIsMinimized] = useState(false);
  const [error, setError] = useState('');
  const [signature, setSignature] = useState('');
  const [attachments, setAttachments] = useState<File[]>([]);
  const [attachmentError, setAttachmentError] = useState('');
  const [trackingEnabled, setTrackingEnabled] = useState(false);
  const [isSending, setIsSending] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Constants
  const MAX_TOTAL_SIZE = 25 * 1024 * 1024; // 25MB
  const BLOCKED_EXTENSIONS = [
    'exe', 'bat', 'cmd', 'com', 'scr', 'vbs',
    'js', 'jar', 'msi', 'dll'
  ];

  // Helper function to extract email and display name from "Name <email>" format
  const extractEmailAndName = (emailString: string): { email: string; displayName: string } => {
    const match = emailString.match(/^(.+?)\s*<(.+?)>$/);
    if (match) {
      return {
        displayName: match[1].trim(),
        email: match[2].trim(),
      };
    }
    return {
      email: emailString.trim(),
      displayName: emailString.trim(),
    };
  };

  // Handle modal close
  const handleClose = () => {
    setAttachments([]);
    setAttachmentError('');
    setCc('');
    setBcc('');
    setShowCc(false);
    setShowBcc(false);
    setTrackingEnabled(false);
    onClose();
  };

  // Load signature from settings
  useEffect(() => {
    (async () => {
      try {
        const token = await getToken();
        const res = await fetch('/api/settings', {
          headers: { Authorization: `Bearer ${token}` },
        });
        const data = await res.json();
        if (data.signature) {
          setSignature(data.signature);
        }
      } catch (e) {
        console.error('Failed to load signature:', e);
      }
    })();
  }, [getToken]);

  // Prefill when replying or forwarding
  useEffect(() => {
    if (replyTo) {
      // Reply logic — only set reply area + signature in the editor
      setTo(replyTo.from.email);
      setSubject(
        replyTo.subject.startsWith('Re:') ? replyTo.subject : `Re: ${replyTo.subject}`
      );
      const replyAreaHtml = '<p><br/></p>';
      const signatureHtml = signature ? `<p><br/></p><div>${signature}</div>` : '';
      setBody(`${replyAreaHtml}${signatureHtml}`);
      setTrackingEnabled(false);
    } else if (forwardEmail) {
      // Forward logic — only set reply area + signature in the editor
      setTo('');
      setSubject(
        forwardEmail.subject.startsWith('Fwd:') ? forwardEmail.subject : `Fwd: ${forwardEmail.subject}`
      );
      const replyAreaHtml = '<p><br/></p>';
      const signatureHtml = signature ? `<p><br/></p><div>${signature}</div>` : '';
      setBody(`${replyAreaHtml}${signatureHtml}`);
      setTrackingEnabled(false);
    } else {
      // New email: just the signature with proper spacing
      setTo('');
      setSubject('');
      const signatureHtml = signature ? `<p><br/></p><div>${signature}</div>` : '';
      setBody(signatureHtml);
      setTrackingEnabled(false);
    }
  }, [replyTo, forwardEmail, signature]);

  if (!isOpen) return null;

  // File selection handler
  const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(event.target.files || []);

    // Validate file types
    const hasBlockedType = files.some(file => {
      const ext = file.name.split('.').pop()?.toLowerCase();
      return ext && BLOCKED_EXTENSIONS.includes(ext);
    });

    if (hasBlockedType) {
      setAttachmentError('Executable files are not allowed');
      return;
    }

    // Validate total size
    const currentSize = attachments.reduce((sum, f) => sum + f.size, 0);
    const newSize = files.reduce((sum, f) => sum + f.size, 0);
    const totalSize = currentSize + newSize;

    if (totalSize > MAX_TOTAL_SIZE) {
      const totalMB = (totalSize / (1024 * 1024)).toFixed(1);
      setAttachmentError(`Total size ${totalMB}MB exceeds 25MB limit`);
      return;
    }

    // Add files
    setAttachments(prev => [...prev, ...files]);
    setAttachmentError('');

    // Reset input
    if (fileInputRef.current) {
      fileInputRef.current.value = '';
    }
  };

  // Remove attachment handler
  const handleRemoveAttachment = (index: number) => {
    setAttachments(prev => prev.filter((_, i) => i !== index));
    setAttachmentError('');
  };

  // Format file size helper
  const formatFileSize = (bytes: number): string => {
    if (bytes < 1024) return `${bytes}B`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
    return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
  };

  /**
   * Build the full email body by combining user reply + quoted content.
   * This is used on send so the quoted thread is included in the sent email.
   */
  const buildFullBody = (): string => {
    const quotedEmail = replyTo || forwardEmail;
    if (!quotedEmail) return body;

    const separator = replyTo ? '--- Original Message ---' : '--- Forwarded Message ---';
    const fromLine = `From: ${quotedEmail.from.name} &lt;${quotedEmail.from.email}&gt;`;
    const dateLine = `Date: ${quotedEmail.date}`;
    const subjectLine = `Subject: ${quotedEmail.subject}`;
    const toLine = forwardEmail
      ? `To: ${forwardEmail.to.map(t => `${t.name} &lt;${t.email}&gt;`).join(', ')}`
      : '';
    const quotedBody = quotedEmail.body || quotedEmail.bodyText || '';

    const quotedHtml = [
      `<p><br/></p><div>${separator}</div>`,
      `<div>${fromLine}</div>`,
      `<div>${dateLine}</div>`,
      toLine ? `<div>${toLine}</div>` : '',
      `<div>${subjectLine}</div>`,
      `<div><br/></div><div>${quotedBody}</div>`,
    ].filter(Boolean).join('');

    return `${body}${quotedHtml}`;
  };

  const handleSend = async () => {
    if (!to || !subject) return;
    setError('');

    // Immediate UI feedback - set loading state within 100ms
    setIsSending(true);

    // Build the full body (reply + quoted content) for sending
    const fullBody = buildFullBody();

    // Optimistic UI update - create temporary email object
    const optimisticEmail: Email = {
      id: `temp-${Date.now()}`,
      from: { name: '', email: '' }, // Will be filled by backend
      to: [{ name: to, email: to }],
      subject,
      preview: body.substring(0, 150),
      body: fullBody,
      bodyText: fullBody,
      date: new Date().toISOString(),
      read: true,
      starred: false,
      folder: 'sent',
      hasAttachment: attachments.length > 0,
      labels: [],
      trackingId: trackingEnabled ? `temp-tracking-${Date.now()}` : undefined,
    };

    // Apply optimistic update immediately
    if (onOptimisticUpdate) {
      onOptimisticUpdate(optimisticEmail);
    }

    try {
      // Build FormData
      const formData = new FormData();
      formData.append('to', to);
      formData.append('subject', subject);
      formData.append('body', fullBody);

      // Extract threading metadata only if replying to an email (not forwarding)
      if (replyTo && !forwardEmail) {
        // Check if messageId exists before building threading metadata
        if (replyTo.messageId) {
          // Build new references array: existing references + original messageId
          const existingRefs = replyTo.references || [];
          const newReferences = [...existingRefs, replyTo.messageId];

          formData.append('inReplyTo', replyTo.messageId);
          formData.append('references', JSON.stringify(newReferences));
        } else {
          // Log warning when replying to an email without messageId
          console.warn(
            '[ComposeModal] Replying to email without messageId - threading headers will be omitted',
            { emailId: replyTo.id, subject: replyTo.subject }
          );
        }
      }

      // Add attachments
      attachments.forEach(file => {
        formData.append('attachments', file);
      });

      // Add tracking parameter
      if (trackingEnabled) {
        formData.append('tracking', 'true');
      }

      // Send request
      const token = await getToken();
      const response = await fetch('/api/mail/send', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
        },
        body: formData,
      });

      if (!response.ok) {
        const data = await response.json();
        throw new Error(data.error || 'Failed to send');
      }

      // After successful email send, save contact asynchronously
      // Extract email and display name from "to" field
      const { email, displayName } = extractEmailAndName(to);

      // Save contact without blocking (fire and forget)
      contactService.saveContact(email, displayName).catch((error) => {
        // Log error but don't block email send flow
        console.error('[ComposeModal] Failed to save contact after email send:', error);
      });

      // Clear form
      setTo('');
      setSubject('');
      setBody('');
      setAttachments([]);
      setAttachmentError('');
      setTrackingEnabled(false);
      handleClose();
    } catch (err: any) {
      setError(err.message || 'Failed to send');
      // Note: In a production app, we would rollback the optimistic update here
      // For now, the email list will refresh and remove the temporary email
    } finally {
      setIsSending(false);
    }
  };

  if (isMinimized) {
    return (
      <div className="fixed bottom-0 right-6 z-50 w-[320px] overflow-hidden rounded-t-xl border border-gray-200 bg-white shadow-lg">
        <div
          className="flex cursor-pointer items-center justify-between bg-gray-900 px-4 py-2.5"
          onClick={() => setIsMinimized(false)}
        >
          <span className="text-[13px] font-medium text-white">
            {subject || 'New Message'}
          </span>
          <div className="flex items-center gap-1">
            <button
              onClick={(e) => {
                e.stopPropagation();
                setIsMinimized(false);
              }}
              className="rounded p-1 text-gray-400 hover:text-white"
            >
              <Maximize2 className="h-3.5 w-3.5" strokeWidth={2} />
            </button>
            <button
              onClick={(e) => {
                e.stopPropagation();
                handleClose();
              }}
              className="rounded p-1 text-gray-400 hover:text-white"
            >
              <X className="h-3.5 w-3.5" strokeWidth={2} />
            </button>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="fixed bottom-0 right-6 z-50 w-[560px] overflow-hidden rounded-t-xl border border-gray-200 bg-white shadow-2xl">
      {/* Header */}
      <div className="flex items-center justify-between bg-gray-900 px-4 py-2.5">
        <span className="text-[13px] font-medium text-white">
          {replyTo ? 'Reply' : forwardEmail ? 'Forward' : 'New Message'}
        </span>
        <div className="flex items-center gap-1">
          <button
            onClick={() => setIsMinimized(true)}
            className="rounded p-1 text-gray-400 hover:text-white"
          >
            <Minus className="h-3.5 w-3.5" strokeWidth={2} />
          </button>
          <button
            onClick={handleClose}
            className="rounded p-1 text-gray-400 hover:text-white"
          >
            <X className="h-3.5 w-3.5" strokeWidth={2} />
          </button>
        </div>
      </div>

      {/* Error */}
      {error && (
        <div className="bg-red-50 px-4 py-2 text-[12px] text-red-600">{error}</div>
      )}

      {/* Attachment Error */}
      {attachmentError && (
        <div className="bg-yellow-50 px-4 py-2 text-[12px] text-yellow-700">{attachmentError}</div>
      )}

      {/* Fields */}
      <div className="border-b border-gray-100">
        <div className="flex items-center border-b border-gray-100 px-4">
          <label className="w-12 flex-shrink-0 text-[13px] text-gray-400">To</label>
          <ContactAutocomplete
            value={to}
            onChange={setTo}
            onSelect={(contact: Contact) => {
              setTo(contact.email);
            }}
            placeholder="recipient@example.com"
          />
          {!showCc && !showBcc && (
            <div className="ml-2 flex gap-2">
              <button
                type="button"
                onClick={() => setShowCc(true)}
                className="text-[12px] text-gray-400 hover:text-gray-600"
              >
                Cc
              </button>
              <button
                type="button"
                onClick={() => setShowBcc(true)}
                className="text-[12px] text-gray-400 hover:text-gray-600"
              >
                Bcc
              </button>
            </div>
          )}
        </div>
        {showCc && (
          <div className="flex items-center border-b border-gray-100 px-4">
            <label className="w-12 flex-shrink-0 text-[13px] text-gray-400">Cc</label>
            <ContactAutocomplete
              value={cc}
              onChange={setCc}
              onSelect={(contact: Contact) => {
                setCc(contact.email);
              }}
              placeholder="cc@example.com"
            />
            <button
              type="button"
              onClick={() => {
                setCc('');
                setShowCc(false);
              }}
              className="ml-2 text-gray-400 hover:text-gray-600"
            >
              <X className="h-3.5 w-3.5" />
            </button>
          </div>
        )}
        {showBcc && (
          <div className="flex items-center border-b border-gray-100 px-4">
            <label className="w-12 flex-shrink-0 text-[13px] text-gray-400">Bcc</label>
            <ContactAutocomplete
              value={bcc}
              onChange={setBcc}
              onSelect={(contact: Contact) => {
                setBcc(contact.email);
              }}
              placeholder="bcc@example.com"
            />
            <button
              type="button"
              onClick={() => {
                setBcc('');
                setShowBcc(false);
              }}
              className="ml-2 text-gray-400 hover:text-gray-600"
            >
              <X className="h-3.5 w-3.5" />
            </button>
          </div>
        )}
        <div className="flex items-center px-4">
          <label className="w-12 flex-shrink-0 text-[13px] text-gray-400">Subject</label>
          <input
            type="text"
            value={subject}
            onChange={(e) => setSubject(e.target.value)}
            className="flex-1 py-2.5 text-[13px] text-gray-900 outline-none placeholder:text-gray-300"
            placeholder="Subject"
          />
        </div>
      </div>

      {/* Body */}
      <div className="max-h-[400px] overflow-y-auto">
        <RichTextEditor
          value={body}
          onChange={setBody}
          placeholder="Write your message..."
          minHeight={replyTo || forwardEmail ? '150px' : '280px'}
          className="border-0 border-t border-gray-100"
          showAdvancedFormatting={true}
        />

        {/* Collapsible quoted messages */}
        {replyTo && <QuotedMessages email={replyTo} />}
        {forwardEmail && <QuotedMessages email={forwardEmail} isForward />}
      </div>

      {/* Attachments Display */}
      {attachments.length > 0 && (
        <div className="border-t border-gray-100 px-4 py-2">
          <div className="flex flex-wrap gap-2">
            {attachments.map((file, index) => (
              <div
                key={index}
                className="flex items-center gap-2 rounded-md bg-gray-50 px-3 py-1.5"
              >
                <Paperclip className="h-3.5 w-3.5 text-gray-400" />
                <span className="text-xs text-gray-700">{file.name}</span>
                <span className="text-xs text-gray-400">
                  ({formatFileSize(file.size)})
                </span>
                <button
                  onClick={() => handleRemoveAttachment(index)}
                  className="text-gray-400 hover:text-gray-600"
                >
                  <X className="h-3.5 w-3.5" />
                </button>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Hidden File Input */}
      <input
        ref={fileInputRef}
        type="file"
        multiple
        onChange={handleFileSelect}
        className="hidden"
      />

      {/* Footer */}
      <div className="flex items-center justify-between border-t border-gray-100 px-4 py-3">
        <div className="flex items-center gap-3">
          <button
            onClick={handleSend}
            disabled={!to || !subject || isSending}
            className="flex items-center gap-2 rounded-lg bg-blue-600 px-5 py-2 text-[13px] font-medium text-white hover:bg-blue-700 disabled:opacity-50"
          >
            {isSending ? (
              <>
                <Loader2 className="h-4 w-4 animate-spin" />
                Sending...
              </>
            ) : (
              'Send'
            )}
          </button>
          <div className="flex items-center gap-0.5">
            <button
              onClick={() => fileInputRef.current?.click()}
              className="rounded-md p-1.5 text-gray-400 hover:bg-gray-50 hover:text-gray-600"
            >
              <Paperclip className="h-4 w-4" strokeWidth={1.75} />
            </button>
            <button className="rounded-md p-1.5 text-gray-400 hover:bg-gray-50 hover:text-gray-600">
              <Image className="h-4 w-4" strokeWidth={1.75} />
            </button>
          </div>
          <TrackingToggle
            enabled={trackingEnabled}
            onChange={setTrackingEnabled}
          />
        </div>
        <button
          onClick={handleClose}
          className="rounded-md p-1.5 text-gray-400 hover:bg-gray-50 hover:text-gray-600"
        >
          <X className="h-4 w-4" strokeWidth={1.75} />
        </button>
      </div>
    </div>
  );
}
