import { useState, useEffect, useCallback, useRef } from 'react';
import { toast } from 'sonner';
import { TipTapEditor } from './TipTapEditor';
import { FrontmatterEditor } from './FrontmatterEditor';
import { PublishDialog } from './PublishDialog';
import { PublishSuccessDialog } from './PublishSuccessDialog';
import { useFileContent, useUpdateFile } from '../../lib/hooks/useFileContent';
import { useBranchStatus, usePublish } from '../../lib/hooks/useBranch';
import { debounce } from '../../lib/utils/debounce';
import { Loading } from '../ui/Loading';
import type { PublishResponse } from '../../lib/api/branch';

interface EditorContainerProps {
  owner: string;
  repo: string;
  path: string;
  onClose?: () => void;
}

export function EditorContainer({ owner, repo, path, onClose }: EditorContainerProps) {
  const { data: fileData, isLoading, error } = useFileContent(owner, repo, path);
  const { data: branchStatus } = useBranchStatus(owner, repo);
  const updateFile = useUpdateFile();
  const publish = usePublish();

  const [content, setContent] = useState('');
  const [frontmatter, setFrontmatter] = useState<Record<string, any>>({});
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
  const [lastSaved, setLastSaved] = useState<Date | null>(null);
  const [isSaving, setIsSaving] = useState(false);
  const [showPublishDialog, setShowPublishDialog] = useState(false);
  const [showSuccessDialog, setShowSuccessDialog] = useState(false);
  const [publishResult, setPublishResult] = useState<PublishResponse | undefined>();

  // Keep track of initial content to detect changes
  const initialContentRef = useRef<{ content: string; frontmatter: Record<string, any> } | null>(null);

  // Load file content when data is available
  useEffect(() => {
    if (fileData) {
      setContent(fileData.content || '');
      setFrontmatter(fileData.frontmatter || {});
      initialContentRef.current = {
        content: fileData.content || '',
        frontmatter: fileData.frontmatter || {},
      };
      setHasUnsavedChanges(false);
    }
  }, [fileData]);

  // Auto-save function
  const saveChanges = useCallback(async () => {
    if (!hasUnsavedChanges) return;

    setIsSaving(true);
    try {
      await updateFile.mutateAsync({
        owner,
        repo,
        path,
        content,
        frontmatter,
      });
      setLastSaved(new Date());
      setHasUnsavedChanges(false);
    } catch (error) {
      console.error('Failed to save:', error);
      toast.error('Failed to save changes', {
        description: error instanceof Error ? error.message : 'Please try again',
      });
    } finally {
      setIsSaving(false);
    }
  }, [owner, repo, path, content, frontmatter, hasUnsavedChanges, updateFile]);

  // Debounced auto-save (2 seconds)
  const debouncedSave = useCallback(
    debounce(() => {
      saveChanges();
    }, 2000),
    [saveChanges]
  );

  // Handle content changes
  const handleContentChange = (newContent: string) => {
    setContent(newContent);
    setHasUnsavedChanges(true);
    debouncedSave();
  };

  // Handle frontmatter changes
  const handleFrontmatterChange = (newFrontmatter: Record<string, any>) => {
    setFrontmatter(newFrontmatter);
    setHasUnsavedChanges(true);
    debouncedSave();
  };

  // Warn before leaving if there are unsaved changes
  useEffect(() => {
    const handleBeforeUnload = (e: BeforeUnloadEvent) => {
      if (hasUnsavedChanges) {
        e.preventDefault();
        e.returnValue = '';
      }
    };

    window.addEventListener('beforeunload', handleBeforeUnload);
    return () => window.removeEventListener('beforeunload', handleBeforeUnload);
  }, [hasUnsavedChanges]);

  // Handle publish
  const handlePublish = async (commitMessage: string, prTitle: string, prDescription: string) => {
    try {
      const result = await publish.mutateAsync({
        owner,
        repo,
        commit_message: commitMessage,
        pr_title: prTitle,
        pr_description: prDescription,
        files: [path],
      });

      setPublishResult(result);
      setShowPublishDialog(false);
      setShowSuccessDialog(true);
      setHasUnsavedChanges(false);
      toast.success('Pull request created successfully!', {
        description: `Branch: ${result.branch_name}`,
      });
    } catch (error) {
      console.error('Failed to publish:', error);
      toast.error('Failed to publish changes', {
        description: error instanceof Error ? error.message : 'Please try again',
      });
    }
  };

  if (isLoading) {
    return (
      <div className="flex items-center justify-center h-full">
        <Loading size="lg" text="Loading file..." />
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex items-center justify-center h-full">
        <div className="text-center max-w-md">
          <div className="text-red-600 text-xl font-bold mb-2">Error Loading File</div>
          <div className="text-gray-600 mb-4">
            {error instanceof Error ? error.message : 'Unknown error'}
          </div>
          {onClose && (
            <button
              onClick={onClose}
              className="px-4 py-2 bg-gray-900 text-white font-semibold hover:bg-gray-800"
            >
              Go Back
            </button>
          )}
        </div>
      </div>
    );
  }

  return (
    <div className="h-full flex flex-col">
      {/* Header */}
      <div className="bg-white border-b-2 border-gray-900 px-6 py-4 flex items-center justify-between">
        <div className="flex-1">
          <h2
            className="text-xl font-bold mb-1"
            style={{ fontFamily: 'Archivo Black, sans-serif' }}
          >
            {path.split('/').pop()}
          </h2>
          <div className="text-sm text-gray-600 font-mono">{path}</div>
        </div>

        <div className="flex items-center gap-4">
          {/* Save status */}
          <div className="text-sm">
            {isSaving ? (
              <span className="text-amber-600 font-semibold">Saving...</span>
            ) : hasUnsavedChanges ? (
              <span className="text-gray-600">Unsaved changes</span>
            ) : lastSaved ? (
              <span className="text-green-600 font-semibold">
                Saved {lastSaved.toLocaleTimeString()}
              </span>
            ) : null}
          </div>

          {/* Manual save button */}
          <button
            onClick={saveChanges}
            disabled={!hasUnsavedChanges || isSaving}
            className="px-4 py-2 bg-white text-gray-900 font-semibold border-2 border-gray-900 hover:bg-gray-100 disabled:bg-gray-200 disabled:cursor-not-allowed transition-colors"
          >
            {isSaving ? 'Saving...' : 'Save'}
          </button>

          {/* Publish button */}
          <button
            onClick={() => setShowPublishDialog(true)}
            disabled={hasUnsavedChanges}
            className="px-6 py-2 bg-amber-500 text-gray-900 font-bold border-2 border-gray-900 hover:bg-amber-600 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors"
            style={{ fontFamily: 'Archivo Black, sans-serif' }}
            title={hasUnsavedChanges ? 'Save changes before publishing' : 'Create pull request'}
          >
            Publish →
          </button>
        </div>
      </div>

      {/* Editor Content */}
      <div className="flex-1 overflow-y-auto p-6 bg-gray-50">
        <div className="max-w-4xl mx-auto space-y-6">
          <FrontmatterEditor
            frontmatter={frontmatter}
            onChange={handleFrontmatterChange}
          />

          <TipTapEditor
            content={content}
            onChange={handleContentChange}
            placeholder="Start writing your post..."
          />
        </div>
      </div>

      {/* Publish Dialog */}
      <PublishDialog
        isOpen={showPublishDialog}
        onClose={() => setShowPublishDialog(false)}
        onPublish={handlePublish}
        branchStatus={branchStatus}
        currentFilePath={path}
        isPublishing={publish.isPending}
      />

      {/* Success Dialog */}
      <PublishSuccessDialog
        isOpen={showSuccessDialog}
        onClose={() => setShowSuccessDialog(false)}
        publishResult={publishResult}
      />
    </div>
  );
}
