import React, { useState, useEffect } from 'react';
import { RefreshCw, FolderOpen, GitBranch, GitCommit , ChevronDown, ChevronUp, Terminal, Copy, Check } from 'lucide-react';
import { GitCloneStatus, 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 { InstallResultMessage } from '../../settings/components/InstallResultMessage';
import { Badge } from '../../components/ui/badge';
import gitIcon from '../../assets/git-icon.png';

export const GitCloneStep: React.FC = () => {
  const { refreshStepStatus, refreshTrigger, scrollToTop, setStepWorking } = useSetupWizard();
  const [gitCloneStatus, setGitCloneStatus] = useState<GitCloneStatus>({
    configured: false,
    repositoryPath: null,
    exists: false,
    isValidRepo: false,
    isCanvasLmsRepo: false,
    remoteUrl: null,
    currentBranch: null,
    lastCommit: null
  });
  const [selectedFolder, setSelectedFolder] = useState<string | null>(null);
  const [folderName, setFolderName] = useState<string>('dev');
  const folderNameDebounceRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
  const checkStatusRef = React.useRef<(forceRefresh?: boolean) => Promise<void>>();
  const [cloning, setCloning] = useState(false);
  const [resetting, setResetting] = 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 [cloneOutput, setCloneOutput] = useState<string>('');
  const [showCloneOutput, setShowCloneOutput] = useState(false);
  const [resetOutput, setResetOutput] = useState<string>('');
  const [showResetOutput, setShowResetOutput] = useState(false);
  const [copiedCode, setCopiedCode] = useState<string | null>(null);
  const [copiedOutput, setCopiedOutput] = useState<string | null>(null);
  const outputEndRef = React.useRef<HTMLDivElement>(null);

  const checkStatus = async (forceRefresh = false) => {
    try {
      const status = await window.setupWizardAPI.getGitCloneStatus(forceRefresh);
      setGitCloneStatus(status);

      if (status.cloneFolder) {
        setSelectedFolder(status.cloneFolder);
      }
      // NOTE: folderName is intentionally NOT updated here.
      // It is only set on initial mount so user edits are never overwritten.

      // If we have a valid repository, mark step as configured
      if (status.configured && status.isValidRepo) {
        await window.setupWizardAPI.markGitCloneConfigured();
      }

      await refreshStepStatus('git-clone');
    } catch (error) {
      console.error('Failed to check Git clone status:', error);
    }
  };
  // Keep ref in sync so debounce timeouts always call the latest version
  checkStatusRef.current = checkStatus;

  useEffect(() => {
    const loadInitialStatus = async () => {
      try {
        const status = await window.setupWizardAPI.getGitCloneStatus(false);
        setGitCloneStatus(status);
        if (status.cloneFolder) setSelectedFolder(status.cloneFolder);
        if (status.folderName) setFolderName(status.folderName);
        if (status.configured && status.isValidRepo) {
          await window.setupWizardAPI.markGitCloneConfigured();
        }
        await refreshStepStatus('git-clone');
      } catch (error) {
        console.error('Failed to load initial Git clone status:', error);
      } finally {
        setRefreshing(false);
      }
    };
    loadInitialStatus();
  }, []);

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

  const handleSelectFolder = async () => {
    try {
      const folder = await window.setupWizardAPI.selectCloneFolder();
      if (folder) {
        setSelectedFolder(folder);
        await window.setupWizardAPI.saveCloneFolder(folder, folderName);
        await checkStatus(true);
      }
    } catch (error: any) {
      setResult({
        success: false,
        message: error.message || 'Failed to select folder'
      });
    }
  };

  const handleFolderNameChange = (value: string) => {
    const trimmed = value.trim() || 'dev';
    setFolderName(value);

    // Immediately reset configured state so the Clone button appears
    // and repositoryPath reflects the new folder name right away
    setGitCloneStatus(prev => ({
      ...prev,
      repositoryPath: selectedFolder ? `${selectedFolder}/${trimmed}` : null,
      configured: false,
      isValidRepo: false,
      isCanvasLmsRepo: false,
      lastCommit: null,
      currentBranch: null
    }));

    // Save immediately so any subsequent refresh reads the current value
    // and the sidebar updates right away (saveFolderName sets completed=false)
    window.setupWizardAPI.saveFolderName(trimmed)
      .then(() => refreshStepStatus('git-clone'))
      .catch(console.error);

    // Debounce the git status check — confirms actual state at new path
    // (e.g. repo may already exist there)
    if (folderNameDebounceRef.current) {
      clearTimeout(folderNameDebounceRef.current);
    }
    folderNameDebounceRef.current = setTimeout(async () => {
      if (trimmed !== value) setFolderName(trimmed);
      await checkStatusRef.current?.(true);
    }, 600);
  };

  const handleClone = async () => {
    if (!selectedFolder) {
      setResult({
        success: false,
        message: 'Please select a folder first'
      });
      return;
    }

    setStepWorking('git-clone', true);
    setCloning(true);
    setResult(null);
    setCloneOutput('');
    setShowCloneOutput(true);

    const cleanup = window.setupWizardAPI.onCloneOutput((output) => {
      setCloneOutput((prev) => prev + output);
      setTimeout(() => {
        outputEndRef.current?.scrollIntoView({ behavior: 'smooth' });
      }, 100);
    });

    try {
      const cloneResult = await window.setupWizardAPI.cloneCanvasLms(selectedFolder, folderName);
      setResult(cloneResult);

      if (cloneResult.success) {
        setTimeout(() => {
          scrollToTop();
          checkStatus(true);
        }, 500);
      }
    } catch (error: any) {
      setResult({
        success: false,
        message: error.message || 'Failed to clone repository'
      });
    } finally {
      setCloning(false);
      setStepWorking('git-clone', false);
      cleanup();
    }
  };

  const handleReset = async () => {
    if (!gitCloneStatus.repositoryPath) {
      return;
    }

    const confirmed = window.confirm(
      'This will:\n' +
      '1. Remove all untracked files (git clean -fdx)\n' +
      '2. Checkout master branch\n' +
      '3. Pull latest changes from origin\n\n' +
      'All local changes will be lost. Continue?'
    );

    if (!confirmed) {
      return;
    }

    setStepWorking('git-clone', true);
    setResetting(true);
    setResult(null);
    setResetOutput('');
    setShowResetOutput(true);

    const cleanup = window.setupWizardAPI.onResetOutput((output) => {
      setResetOutput((prev) => prev + output);
      setTimeout(() => {
        outputEndRef.current?.scrollIntoView({ behavior: 'smooth' });
      }, 100);
    });

    try {
      const resetResult = await window.setupWizardAPI.resetRepository(gitCloneStatus.repositoryPath);
      setResult(resetResult);

      if (resetResult.success) {
        setTimeout(() => {
          checkStatus(true);
        }, 2000);
      }
    } catch (error: any) {
      setResult({
        success: false,
        message: error.message || 'Failed to reset repository'
      });
    } finally {
      setResetting(false);
      setStepWorking('git-clone', false);
      cleanup();
    }
  };

  const handleRefresh = async () => {
    setRefreshing(true);
    setResult(null);
    await checkStatus(true);
    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">
            Clone canvas-lms repository
          </p>
          <Button
            onClick={handleRefresh}
            disabled={refreshing || cloning || resetting}
            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 does git clone do?
                </p>
                <p>
                  Git clone creates a local copy of the canvas-lms repository from Gerrit, including all files, history, and branches.
                </p>
              </div>

              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  Why is it needed?
                </p>
                <p>
                  You need a local copy of Canvas source code to develop features, fix bugs, and test changes. The clone command downloads the entire repository to your machine.
                </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>Allows you to select a folder where canvas-lms will be cloned</li>
                  <li>Checks if the repository is already cloned at the selected location</li>
                  <li>Executes git clone from the Gerrit remote repository</li>
                  <li>Monitors clone progress (can take 5-15 minutes)</li>
                  <li>Verifies the clone was successful</li>
                  <li>Displays last commit information</li>
                  <li>Provides option to reset repository if needed</li>
                </ul>
              </div>
            </div>
          )}
        </div>
      </Card>

      {result && (
        <InstallResultMessage
          result={result}
          onDismiss={() => setResult(null)}
        />
      )}

      {/* Repository Status Card */}
      <Card className="p-5">
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center space-x-3">
            <div className="w-12 h-12 rounded overflow-hidden flex-shrink-0">
              <img
                src={gitIcon}
                alt="Git"
                className="w-full h-full object-cover"
              />
            </div>
            <div>
              <h3 className="text-[15px] font-semibold text-foreground">
                canvas-lms Repository
              </h3>
              {gitCloneStatus.configured && gitCloneStatus.currentBranch && (
                <div className="flex items-center gap-2 mt-1">
                  <Badge
                    variant="outline"
                    className="text-xs"
                  >
                    <GitBranch className="h-3 w-3 mr-1" />
                    {gitCloneStatus.currentBranch}
                  </Badge>
                </div>
              )}
            </div>
          </div>
          <div
            className={`px-3 py-1 rounded-full text-sm font-medium ${
              gitCloneStatus.configured
                ? 'bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-400'
                : 'bg-yellow-100 dark:bg-yellow-900/30 text-yellow-800 dark:text-yellow-400'
            }`}
          >
            {gitCloneStatus.configured ? 'Configured' : 'Not Configured'}
          </div>
        </div>

        <div className="space-y-4">
          {/* Folder Selection */}
          <div className="space-y-3">
            <div>
              <label className="text-sm font-medium mb-2 block text-foreground">
                Clone Location
              </label>
              <p className="text-xs text-muted-foreground mb-3">
                The clone location is where we will store all cloned versions of canvas-lms. There may be more than one cloned version if you work on multiple changes at the same time and you are running multiple deployments at the same time. You can select any folder to store these cloned repositories, but usually developers choose <code className="bg-muted px-1 rounded">~/code/canvas</code>.
              </p>
              <div className="flex gap-2">
                <input
                  type="text"
                  readOnly
                  value={selectedFolder || 'No folder selected'}
                  className="flex-1 px-3 py-2 text-sm rounded border bg-muted text-muted-foreground"
                />
                <Button
                  onClick={handleSelectFolder}
                  disabled={cloning || resetting}
                  variant="outline"
                  size="sm"
                >
                  <FolderOpen className="h-4 w-4 mr-2" />
                  Select Folder
                </Button>
              </div>
            </div>

            <div>
              <label className="text-sm font-medium mb-1 block text-foreground">
                Folder Name
              </label>
              <p className="text-xs text-muted-foreground mb-2">
                The name of the folder where canvas-lms will be cloned. Defaults to <code className="bg-muted px-1 rounded">dev</code>.
              </p>
              <input
                type="text"
                value={folderName}
                onChange={(e) => handleFolderNameChange(e.target.value)}
                disabled={cloning || resetting}
                placeholder="dev"
                className="w-full px-3 py-2 text-sm rounded border bg-background text-foreground disabled:opacity-50 disabled:bg-muted"
              />
            </div>

            {selectedFolder && (
              <p className="text-xs text-muted-foreground">
                Repository will be cloned to:{' '}
                <code className="bg-muted px-1 rounded">
                  {selectedFolder}/{folderName || 'dev'}
                </code>
              </p>
            )}
          </div>

          {/* Last Commit Info */}
          {gitCloneStatus.lastCommit && (
            <div
              className="p-3 rounded-lg bg-muted"
            >
              <div className="flex items-start gap-2">
                <GitCommit className="h-4 w-4 mt-0.5 text-muted-foreground" />
                <div className="flex-1 min-w-0">
                  <p className="text-xs font-medium mb-1 text-foreground">
                    Last Commit
                  </p>
                  <p className="text-xs text-muted-foreground">
                    <span className="font-mono">{gitCloneStatus.lastCommit.hash}</span> - {gitCloneStatus.lastCommit.message}
                  </p>
                  <p className="text-xs mt-1 text-muted-foreground">
                    {gitCloneStatus.lastCommit.author} • {new Date(gitCloneStatus.lastCommit.date).toLocaleString()}
                  </p>
                </div>
              </div>
            </div>
          )}

          {/* Action Buttons */}
          <div className="space-y-2">
            {!gitCloneStatus.configured ? (
              <Button
                onClick={handleClone}
                disabled={!selectedFolder || cloning}
                className="w-full"
              >
                {cloning ? 'Cloning Repository...' : 'Clone Repository'}
              </Button>
            ) : (
              <Button
                onClick={handleReset}
                disabled={resetting}
                className="w-full"
                variant="outline"
              >
                {resetting ? 'Resetting...' : 'Reset Repository'}
              </Button>
            )}
          </div>

          {!selectedFolder && (
            <Alert variant="warning">
              <AlertDescription>
                <p className="text-xs">
                  Please select a folder where the canvas-lms repository will be cloned.
                </p>
              </AlertDescription>
            </Alert>
          )}
        </div>
      </Card>

      {showCloneOutput && (
        <Card className="p-4">
          <div className="flex items-center justify-between mb-2">
            <h4 className="text-sm font-semibold text-foreground">
              Clone Output
            </h4>
            <div className="flex items-center gap-1">
              <button
                onClick={() => { navigator.clipboard.writeText(cloneOutput); setCopiedOutput('clone'); setTimeout(() => setCopiedOutput(null), 2000); }}
                className="p-1 hover:bg-secondary rounded"
                title="Copy output"
              >
                {copiedOutput === 'clone' ? <Check className="h-3.5 w-3.5 text-green-600" /> : <Copy className="h-3.5 w-3.5 text-muted-foreground" />}
              </button>
              <Button
                onClick={() => setShowCloneOutput(false)}
                variant="ghost"
                size="sm"
                disabled={cloning}
              >
                Hide
              </Button>
            </div>
          </div>
          <div
            className="bg-[#1a1a1a] text-[#00ff00] font-mono text-xs p-4 rounded-md overflow-auto max-h-96"
            style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all' }}
          >
            {cloneOutput || 'Waiting for output...'}
            <div ref={outputEndRef} />
          </div>
        </Card>
      )}

      {showResetOutput && (
        <Card className="p-4">
          <div className="flex items-center justify-between mb-2">
            <h4 className="text-sm font-semibold text-foreground">
              Reset Output
            </h4>
            <div className="flex items-center gap-1">
              <button
                onClick={() => { navigator.clipboard.writeText(resetOutput); setCopiedOutput('reset'); setTimeout(() => setCopiedOutput(null), 2000); }}
                className="p-1 hover:bg-secondary rounded"
                title="Copy output"
              >
                {copiedOutput === 'reset' ? <Check className="h-3.5 w-3.5 text-green-600" /> : <Copy className="h-3.5 w-3.5 text-muted-foreground" />}
              </button>
              <Button
                onClick={() => setShowResetOutput(false)}
                variant="ghost"
                size="sm"
                disabled={resetting}
              >
                Hide
              </Button>
            </div>
          </div>
          <div
            className="bg-[#1a1a1a] text-[#00ff00] font-mono text-xs p-4 rounded-md overflow-auto max-h-96"
            style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all' }}
          >
            {resetOutput || 'Waiting for output...'}
            <div ref={outputEndRef} />
          </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">
                  Clone fails with authentication error
                </p>
                <p>
                  If you see "Permission denied (publickey)":
                </p>
                <ul className="list-disc list-inside space-y-1 ml-2">
                  <li>Verify your SSH key is added to Gerrit</li>
                  <li className="flex items-start gap-2">
                    <span className="flex-1">
                      Test SSH connection:
                      <div className="mt-1 flex items-center gap-2">
                        <code className="px-2 py-1 rounded text-xs bg-secondary text-foreground flex-1">
                          ssh -T gerrit.instructure.com
                        </code>
                        <button
                          onClick={() => handleCopyCode('ssh -T gerrit.instructure.com', 'ssh-test-gerrit')}
                          className="p-1 hover:bg-secondary rounded"
                          title="Copy to clipboard"
                        >
                          {copiedCode === 'ssh-test-gerrit' ? (
                            <Check className="h-3.5 w-3.5 text-green-600" />
                          ) : (
                            <Copy className="h-3.5 w-3.5 text-muted-foreground" />
                          )}
                        </button>
                      </div>
                    </span>
                  </li>
                  <li>Check SSH key permissions (should be 600 for private key)</li>
                  <li>Add your key to ssh-agent if using a passphrase</li>
                </ul>
              </div>

              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  Clone is very slow or stalls
                </p>
                <p>
                  The canvas-lms repository is large (can take 5-15 minutes):
                </p>
                <ul className="list-disc list-inside space-y-1 ml-2">
                  <li>Ensure you have a stable internet connection</li>
                  <li>Check you have enough disk space (at least 10GB free)</li>
                  <li>Let it complete - clone progress may appear to stall at times</li>
                </ul>
              </div>

              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  Manually cloning canvas-lms
                </p>
                <p>
                  To clone manually via terminal:
                </p>
                <div className="flex items-center gap-2">
                  <code className="px-2 py-1 rounded text-xs bg-secondary text-foreground flex-1">
                    cd /path/to/your/code/directory
                  </code>
                  <button
                    onClick={() => handleCopyCode('cd /path/to/your/code/directory', 'cd-directory')}
                    className="p-1 hover:bg-secondary rounded"
                    title="Copy to clipboard"
                  >
                    {copiedCode === 'cd-directory' ? (
                      <Check className="h-3.5 w-3.5 text-green-600" />
                    ) : (
                      <Copy className="h-3.5 w-3.5 text-muted-foreground" />
                    )}
                  </button>
                </div>
                <div className="flex items-center gap-2 mt-1">
                  <code className="px-2 py-1 rounded text-xs bg-secondary text-foreground flex-1">
                    git clone gerrit.instructure.com:canvas-lms
                  </code>
                  <button
                    onClick={() => handleCopyCode('git clone gerrit.instructure.com:canvas-lms', 'git-clone-canvas')}
                    className="p-1 hover:bg-secondary rounded"
                    title="Copy to clipboard"
                  >
                    {copiedCode === 'git-clone-canvas' ? (
                      <Check className="h-3.5 w-3.5 text-green-600" />
                    ) : (
                      <Copy className="h-3.5 w-3.5 text-muted-foreground" />
                    )}
                  </button>
                </div>
              </div>

              <div className="space-y-2">
                <p className="font-medium text-foreground">
                  Removing and re-cloning
                </p>
                <p>
                  If the clone is corrupted or incomplete:
                </p>
                <ul className="list-disc list-inside space-y-1 ml-2">
                  <li>Delete the canvas-lms directory</li>
                  <li>Click "Refresh Status" to verify it's gone</li>
                  <li>Try cloning again</li>
                </ul>
              </div>
            </div>
          )}
        </div>
      </Card>
    </div>
  );
};
