import React, { useState, useEffect } from 'react';
import { CheckCircle2, AlertCircle, RefreshCw, Save, FolderOpen, ChevronDown, ChevronUp, Terminal, Copy, Check } from 'lucide-react';
import { InstConfigStatus, InstallResult } from '../../types';
import { useSetupWizard } from '../SetupWizardContext';
import { Card } from '../../components/ui/card';
import { Button } from '../../components/ui/button';
import { Alert, AlertDescription } from '../../components/ui/alert';
import { Badge } from '../../components/ui/badge';
import terminalIcon from '../../assets/terminal-icon.png';

export const InstCliConfigFileStep: React.FC = () => {
  const { refreshStepStatus, refreshTrigger, scrollToTop } = useSetupWizard();
  const [status, setStatus] = useState<InstConfigStatus>({
    exists: false,
    content: null,
    path: ''
  });
  const [configContent, setConfigContent] = useState<string>('');
  const [saving, setSaving] = useState(false);
  const [refreshing, setRefreshing] = useState(true);
  const [result, setResult] = useState<InstallResult | null>(null);
  const [showAboutStep, setShowAboutStep] = useState(false);
  const [showTroubleshooting, setShowTroubleshooting] = useState(false);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
  const [isConfigured, setIsConfigured] = useState(false);
  const [copiedCode, setCopiedCode] = useState<string | null>(null);

  const checkStatus = async (forceRefresh = false, preserveContent = false) => {
    try {
      const configStatus = await window.setupWizardAPI.getInstConfigStatus();
      setStatus(configStatus);

      // Check the backend state to see if step is marked as complete
      const currentState = await window.setupWizardAPI.getState();
      const stepData = currentState.stepStatus['inst-cli-config-file'];
      const isStepComplete = stepData?.completed === true;

      // Normalize content helper
      const normalizeContent = (content: string) => {
        return content?.replace(/\r\n/g, '\n').trimEnd() || '';
      };

      // Only update content if not preserving (i.e., not from refresh with unsaved changes)
      if (configStatus.content && !preserveContent) {
        // Normalize the content when loading to ensure consistency
        setConfigContent(normalizeContent(configStatus.content));
      }

      // Check if file content differs from normalized content and auto-fix if needed
      if (configStatus.exists && configStatus.actualFileContent && configStatus.content) {
        const normalizedDisplayContent = normalizeContent(configStatus.content);
        const normalizedFileContent = normalizeContent(configStatus.actualFileContent);

        // If the normalized display content (with correct paths/indentation) differs from file content
        // automatically save the corrected version to fix indentation/formatting issues
        if (normalizedDisplayContent !== normalizedFileContent) {
          console.log('Auto-fixing inst.yml formatting...');
          await window.setupWizardAPI.saveInstConfig(normalizedDisplayContent);
        }
      }

      // Determine if configured based on backend state and file existence
      if (configStatus.exists && isStepComplete) {
        setIsConfigured(true);
        setHasUnsavedChanges(false);
      } else if (configStatus.exists) {
        // File exists but step not marked as complete - might need to be saved
        setIsConfigured(false);
      } else {
        setIsConfigured(false);
      }

      // Refresh validation status
      await refreshStepStatus('inst-cli-config-file');
    } catch (error) {
      console.error('Failed to check inst config status:', error);
    } finally {
    }
  };

  useEffect(() => {
    const loadInitialStatus = async () => {
      await checkStatus();
      setRefreshing(false);
    };
    loadInitialStatus();
  }, []);

  // Listen to refresh trigger from context
  useEffect(() => {
    if (refreshTrigger > 0) {
      handleRefresh();
    }
  }, [refreshTrigger]);

  const handleContentChange = async (newContent: string) => {
    setConfigContent(newContent);
    setHasUnsavedChanges(true);
    setIsConfigured(false);

    // Mark step as not complete when content is edited
    const currentState = await window.setupWizardAPI.getState();
    const updatedState = {
      ...currentState,
      stepStatus: {
        ...currentState.stepStatus,
        'inst-cli-config-file': {
          ...currentState.stepStatus['inst-cli-config-file'],
          completed: false,
          lastChecked: Date.now()
        }
      }
    };
    await window.setupWizardAPI.setState(updatedState);

    // Refresh validation to update sidebar
    await refreshStepStatus('inst-cli-config-file');
  };

  const handleSave = async () => {
    setSaving(true);
    setResult(null);

    try {
      const saveResult = await window.setupWizardAPI.saveInstConfig(configContent);
      setResult(saveResult);

      if (saveResult.success) {
        setHasUnsavedChanges(false);
        setIsConfigured(true);

        // Mark step as complete after successful save
        const currentState = await window.setupWizardAPI.getState();
        const updatedState = {
          ...currentState,
          stepStatus: {
            ...currentState.stepStatus,
            'inst-cli-config-file': {
              ...currentState.stepStatus['inst-cli-config-file'],
              completed: true,
              lastChecked: Date.now()
            }
          }
        };
        await window.setupWizardAPI.setState(updatedState);

        // Wait for UI to update before scrolling and refreshing
        setTimeout(() => {
          scrollToTop();
          checkStatus(true);
        }, 500);
      }
    } catch (error: any) {
      setResult({
        success: false,
        message: error.message || 'Failed to save configuration'
      });
    } finally {
      setSaving(false);
    }
  };

  const handleOpenInFinder = async () => {
    if (status.path) {
      try {
        const success = await window.setupWizardAPI.showInFinder(status.path);
        if (!success) {
          setResult({
            success: false,
            message: 'Failed to open file in Finder'
          });
        }
      } catch (error) {
        console.error('Error opening in Finder:', error);
        setResult({
          success: false,
          message: 'Failed to open file in Finder'
        });
      }
    }
  };

  const handleRefresh = async () => {
    setRefreshing(true);
    setResult(null);

    // Get the current file status
    const configStatus = await window.setupWizardAPI.getInstConfigStatus();

    // Compare the UI content with the actual file content (not the path-replaced version)
    // We need to compare with actualFileContent to detect real file changes
    const fileContentToCompare = configStatus.actualFileContent || configStatus.content;

    // Normalize both strings for comparison (handle line endings and trailing whitespace)
    const normalizeContent = (content: string) => {
      return content?.replace(/\r\n/g, '\n').trimEnd() || '';
    };

    // If they differ, mark the step as not configured
    const contentDiffers = fileContentToCompare && normalizeContent(configContent) !== normalizeContent(fileContentToCompare);

    if (contentDiffers) {

      // Content differs - mark step as not complete and show unsaved changes warning
      setHasUnsavedChanges(true);
      setIsConfigured(false);

      const currentState = await window.setupWizardAPI.getState();
      const updatedState = {
        ...currentState,
        stepStatus: {
          ...currentState.stepStatus,
          'inst-cli-config-file': {
            ...currentState.stepStatus['inst-cli-config-file'],
            completed: false,
            lastChecked: Date.now()
          }
        }
      };
      await window.setupWizardAPI.setState(updatedState);

      // Show a message to inform the user
      setResult({
        success: false,
        message: 'The content on screen differs from the saved file. Please save your changes.'
      });
    } else {
      // Content matches - clear unsaved changes flag if it was set
      setHasUnsavedChanges(false);
      setIsConfigured(configStatus.exists);

      // If file exists and content matches, mark step as complete
      if (configStatus.exists) {
        const currentState = await window.setupWizardAPI.getState();
        const updatedState = {
          ...currentState,
          stepStatus: {
            ...currentState.stepStatus,
            'inst-cli-config-file': {
              ...currentState.stepStatus['inst-cli-config-file'],
              completed: true,
              lastChecked: Date.now()
            }
          }
        };
        await window.setupWizardAPI.setState(updatedState);
      }
    }

    // Refresh validation status explicitly
    await checkStatus(true, contentDiffers);

    setRefreshing(false);
  };

  const handleOpenTerminal = async () => {
    try {
      const result = await window.setupWizardAPI.openTerminal();
      if (!result.success) {
        setResult({
          success: false,
          message: result.message || 'Failed to open Terminal'
        });
      }
    } catch (error: any) {
      setResult({
        success: false,
        message: error.message || 'Failed to open Terminal'
      });
    }
  };

  const handleCopyCode = async (code: string, id: string) => {
    try {
      await navigator.clipboard.writeText(code);
      setCopiedCode(id);
      setTimeout(() => setCopiedCode(null), 2000);
    } catch (error) {
      console.error('Failed to copy code:', error);
    }
  };

  return (
    <div className="space-y-4">
      <Card className="px-4 py-3">
        <div className="flex items-center justify-between">
          <p className="text-sm font-medium text-foreground">
            Configure inst-cli configuration file
          </p>
          <Button
            onClick={handleRefresh}
            disabled={refreshing || saving}
            variant="ghost"
            size="sm"
          >
            <RefreshCw className={`h-4 w-4 mr-2 ${refreshing ? 'animate-spin' : ''}`} />
            {refreshing ? 'Refreshing...' : 'Refresh Status'}
          </Button>
        </div>
      </Card>

      {/* About This Step Section */}
      <Card className="p-5">
        <div className="space-y-3">
          <button
            onClick={() => setShowAboutStep(!showAboutStep)}
            className="flex items-center gap-2 text-sm w-full text-foreground hover:opacity-80"
          >
            {showAboutStep ? (
              <ChevronUp className="h-4 w-4" />
            ) : (
              <ChevronDown className="h-4 w-4" />
            )}
            About This Step
          </button>

          {showAboutStep && (
            <div className="p-4 rounded-lg text-sm space-y-4 bg-muted text-muted-foreground">
              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  What is inst.yml?
                </p>
                <p>
                  inst.yml is the configuration file for inst-cli that defines your Canvas development environment settings, including repository paths and custom configurations.
                </p>
              </div>

              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  Why is it needed?
                </p>
                <p>
                  inst-cli needs to know where your repositories are located and how to configure your development environment. This file tells inst-cli how to set up Canvas.
                </p>
              </div>

              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  What actions does this step perform?
                </p>
                <ul className="list-disc list-inside space-y-1">
                  <li>Checks if ~/.inst-cli/inst.yml exists</li>
                  <li>Reads and displays current configuration</li>
                  <li>Validates required fields (base_code_directory, canvas-lms source path)</li>
                  <li>Provides a text editor to modify the configuration</li>
                  <li>Saves changes to ~/.inst-cli/inst.yml</li>
                  <li>Verifies configuration syntax and required fields</li>
                </ul>
              </div>
            </div>
          )}
        </div>
      </Card>

      {result && (
        <Alert variant={result.success ? "success" : "destructive"}>
          <AlertDescription className="text-xs">
            {result.message}
          </AlertDescription>
        </Alert>
      )}

      <Card className="p-5">
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center gap-3">
            <div className="w-10 h-10 rounded-lg overflow-hidden flex-shrink-0">
              <img src={terminalIcon} alt="inst-cli" className="w-full h-full object-cover" />
            </div>
            <div>
              <h3 className="text-[15px] font-semibold text-foreground">inst.yml Configuration</h3>
              <div className="mt-1">
                {isConfigured && !hasUnsavedChanges ? (
                  <Badge variant="success" className="text-xs">
                    <CheckCircle2 className="h-3.5 w-3.5 mr-1" />
                    Configured
                  </Badge>
                ) : (
                  <Badge variant="warning" className="text-xs">
                    <AlertCircle className="h-3.5 w-3.5 mr-1" />
                    Not Configured
                  </Badge>
                )}
              </div>
            </div>
          </div>
        </div>

        <div className="space-y-4">
          {status.exists && (
            <Alert variant="success">
              <CheckCircle2 className="h-5 w-5" />
              <AlertDescription>
                <p className="font-medium mb-1">Configuration file exists</p>
                <p className="text-xs">
                  File location: <code className="bg-green-100 dark:bg-green-900/30 px-1 rounded">{status.path}</code>
                </p>
              </AlertDescription>
            </Alert>
          )}

          {!status.exists && (
            <Alert variant="warning">
              <AlertCircle className="h-5 w-5" />
              <AlertDescription>
                <p className="font-medium mb-1">Configuration file not found</p>
                <p className="text-xs">
                  The file <code className="bg-yellow-100 dark:bg-yellow-900/30 px-1 rounded">~/.inst-cli/inst.yml</code> does not exist.
                  You can create it by editing the template below and clicking "Save Configuration".
                </p>
              </AlertDescription>
            </Alert>
          )}

          <div className="space-y-2">
            <label className="text-sm font-medium block text-foreground">
              ~/.inst-cli/inst.yml
            </label>
            <textarea
              value={configContent}
              onChange={(e) => handleContentChange(e.target.value)}
              rows={15}
              className="w-full px-3 py-2 text-sm font-mono rounded border bg-muted text-muted-foreground"
              placeholder="inst.yml configuration content..."
            />
            {hasUnsavedChanges && (
              <p className="text-xs text-orange-600">You have unsaved changes</p>
            )}
          </div>

          <div className="flex gap-2">
            <Button
              onClick={handleSave}
              disabled={saving || !configContent.trim()}
              className="flex-1"
            >
              {saving ? (
                <>
                  <RefreshCw className="h-4 w-4 mr-2 animate-spin" />
                  Saving...
                </>
              ) : (
                <>
                  <Save className="h-4 w-4 mr-2" />
                  Save Configuration
                </>
              )}
            </Button>

            {status.exists && (
              <Button
                onClick={handleOpenInFinder}
                variant="outline"
                disabled={saving}
              >
                <FolderOpen className="h-4 w-4 mr-2" />
                Open in Finder
              </Button>
            )}
          </div>

          <div className="pt-3 border-t border-border">
            <p className="text-xs mb-2 text-muted-foreground">
              <strong>Note:</strong> The configuration file should contain:
            </p>
            <ul className="text-xs space-y-1 list-disc list-inside text-muted-foreground">
              <li><code className="bg-muted px-1 rounded">base_code_directory</code> - Path to the folder containing your repositories</li>
              <li><code className="bg-muted px-1 rounded">canvas-lms: source</code> - Path to the canvas-lms repository</li>
            </ul>
          </div>
        </div>
      </Card>

      <Card className="p-5">
        <div className="space-y-3">
          <div className="flex items-center justify-between">
            <button
              onClick={() => setShowTroubleshooting(!showTroubleshooting)}
              className="flex items-center gap-2 text-sm text-foreground hover:opacity-80"
            >
              {showTroubleshooting ? (
                <ChevronUp className="h-4 w-4" />
              ) : (
                <ChevronDown className="h-4 w-4" />
              )}
              Troubleshooting
            </button>
            {showTroubleshooting && (
              <Button
                onClick={handleOpenTerminal}
                variant="outline"
                size="sm"
                className="h-8 text-xs"
              >
                <Terminal className="h-3.5 w-3.5 mr-1.5" />
                Open Terminal
              </Button>
            )}
          </div>

          {showTroubleshooting && (
            <div className="p-4 rounded-lg text-sm space-y-4 bg-muted text-muted-foreground">
              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  YAML syntax errors
                </p>
                <p>
                  If you see validation errors when saving:
                </p>
                <ul className="list-disc list-inside space-y-1 ml-2">
                  <li>Check indentation (use spaces, not tabs)</li>
                  <li>Ensure colons have a space after them</li>
                  <li>Verify paths don't have trailing slashes</li>
                  <li>Make sure all quotes are properly closed</li>
                </ul>
              </div>

              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  Required fields missing
                </p>
                <p>
                  The inst.yml file requires:
                </p>
                <ul className="list-disc list-inside space-y-1 ml-2">
                  <li><code className="bg-secondary px-1 rounded">base_code_directory</code> - Path to your code folder</li>
                  <li><code className="bg-secondary px-1 rounded">canvas-lms</code> source path under plugins</li>
                  <li><code className="bg-secondary px-1 rounded">inst_domain</code> - Your Canvas development domain</li>
                </ul>
              </div>

              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  Manually editing inst.yml
                </p>
                <p>
                  To edit the file manually:
                </p>
                <div className="flex items-center gap-2">
                  <code className="px-2 py-1 rounded text-xs bg-secondary text-foreground flex-1">
                    open -e ~/.inst-cli/inst.yml
                  </code>
                  <button
                    onClick={() => handleCopyCode('open -e ~/.inst-cli/inst.yml', 'open-inst-yml')}
                    className="p-1 hover:bg-secondary rounded"
                    title="Copy to clipboard"
                  >
                    {copiedCode === 'open-inst-yml' ? (
                      <Check className="h-3.5 w-3.5 text-green-600" />
                    ) : (
                      <Copy className="h-3.5 w-3.5 text-muted-foreground" />
                    )}
                  </button>
                </div>
                <p className="text-xs mt-2">
                  Or use your preferred text editor to edit <code className="bg-secondary px-1 rounded">~/.inst-cli/inst.yml</code>
                </p>
              </div>

              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  Resetting to default configuration
                </p>
                <p>
                  To start fresh with a default inst.yml:
                </p>
                <div className="flex items-center gap-2">
                  <code className="px-2 py-1 rounded text-xs bg-secondary text-foreground flex-1">
                    mv ~/.inst-cli/inst.yml ~/.inst-cli/inst.yml.backup
                  </code>
                  <button
                    onClick={() => handleCopyCode('mv ~/.inst-cli/inst.yml ~/.inst-cli/inst.yml.backup', 'mv-inst-yml')}
                    className="p-1 hover:bg-secondary rounded flex-shrink-0"
                    title="Copy to clipboard"
                  >
                    {copiedCode === 'mv-inst-yml' ? (
                      <Check className="h-3.5 w-3.5 text-green-600" />
                    ) : (
                      <Copy className="h-3.5 w-3.5 text-muted-foreground" />
                    )}
                  </button>
                </div>
                <p className="text-xs mt-2">
                  Then refresh this page to create a new default configuration.
                </p>
              </div>
            </div>
          )}
        </div>
      </Card>
    </div>
  );
};
