/**
 * BuildNode - Build target card component.
 * Displays build status, progress, stages, and actions.
 * Compact when not selected, expanded with details when selected.
 */

import { useState, useRef, useEffect, memo, useMemo } from 'react';
import {
  ChevronDown, ChevronRight, Play, Clock, X,
  AlertTriangle, AlertCircle, Circle,
  FileCode, Search, Grid3X3, Layout, Cuboid, Box, Square, Trash2
} from 'lucide-react';
import type { Selection, BuildTarget, ModuleDefinition } from './projectsTypes';
import { NameValidationDropdown } from './NameValidationDropdown';
import { validateName } from '../utils/nameValidation';
import { useStore } from '../store';
import { sendAction } from '../api/websocket';
import { postMessage } from '../api/vscodeApi';
import { StatusIcon } from './StatusIcon';
import './BuildNode.css';

// Format time in mm:ss or hh:mm:ss
export function formatBuildTime(seconds: number): string {
  if (seconds >= 0 && seconds < 1) {
    return `${seconds.toFixed(2)}s`;
  }
  if (seconds > 0 && seconds < 10) {
    return `${seconds.toFixed(1)}s`;
  }
  const hrs = Math.floor(seconds / 3600);
  const mins = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);
  if (hrs > 0) {
    return `${hrs}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
  }
  return `${mins}:${secs.toString().padStart(2, '0')}`;
}

// Parse timestamp that may be in format "YYYY-MM-DD_HH-MM-SS" or ISO format
function parseTimestamp(timestamp: string): Date {
  const normalized = timestamp.replace(/_/g, 'T').replace(/-(\d{2})-(\d{2})$/, ':$1:$2');
  return new Date(normalized);
}

// Format relative time (e.g., "2m ago", "1h ago", "yesterday")
export function formatRelativeTime(timestamp: string): string {
  const date = parseTimestamp(timestamp);
  if (isNaN(date.getTime())) return '';

  const now = new Date();
  const diffMs = now.getTime() - date.getTime();
  const diffSecs = Math.floor(diffMs / 1000);
  const diffMins = Math.floor(diffSecs / 60);
  const diffHours = Math.floor(diffMins / 60);
  const diffDays = Math.floor(diffHours / 24);

  if (diffSecs < 60) return 'just now';
  if (diffMins < 60) return `${diffMins}m ago`;
  if (diffHours < 24) return `${diffHours}h ago`;
  if (diffDays === 1) return 'yesterday';
  if (diffDays < 7) return `${diffDays}d ago`;
  return date.toLocaleDateString();
}


interface BuildNodeProps {
  build: BuildTarget;
  projectId: string;
  selection: Selection;
  onSelect: (selection: Selection) => void;
  onBuild: (level: 'project' | 'build' | 'symbol', id: string, label: string) => void;
  onCancelBuild?: (buildId: string) => void;
  onStageFilter?: (stageName: string, buildId?: string, projectId?: string) => void;
  onUpdateBuild?: (projectId: string, buildId: string, updates: Partial<BuildTarget>) => void;
  onDeleteBuild?: (projectId: string, buildId: string) => void;
  onOpenSource?: (projectId: string, entry: string) => void;
  onOpenKiCad?: (projectId: string, buildId: string) => void;
  onOpenLayout?: (projectId: string, buildId: string) => void;
  onOpen3D?: (projectId: string, buildId: string) => void;
  availableModules?: ModuleDefinition[];
  // All builds in the project (for duplicate entry validation)
  allBuilds?: BuildTarget[];
  // Read-only mode for packages: hides build/delete buttons, status icon, progress
  readOnly?: boolean;
}

export const BuildNode = memo(function BuildNode({
  build,
  projectId,
  selection,
  onSelect,
  onBuild,
  onCancelBuild,
  onStageFilter,
  onUpdateBuild,
  onDeleteBuild,
  onOpenSource,
  onOpenKiCad,
  onOpenLayout,
  onOpen3D,
  availableModules = [],
  allBuilds = [],
  readOnly = false
}: BuildNodeProps) {
  const [showStages, setShowStages] = useState(false);
  const [isEditingName, setIsEditingName] = useState(false);
  const [isEditingEntry, setIsEditingEntry] = useState(false);
  const [buildName, setBuildName] = useState(build.name);
  const [entryPoint, setEntryPoint] = useState(build.entry);
  const [searchQuery, setSearchQuery] = useState('');
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
  const [duplicateWarning, setDuplicateWarning] = useState<{ entry: string; usedBy: string } | null>(null);
  const searchInputRef = useRef<HTMLInputElement>(null);

  const elapsedTime = build.elapsedSeconds ?? 0;
  const isBuilding = build.status === 'building' || build.status === 'queued';

  // Track previous stage for animation
  const [prevStage, setPrevStage] = useState<string | null>(null);
  const [stageAnimating, setStageAnimating] = useState(false);


  // Progress calculation using totalStages from backend
  const getProgress = () => {
    if (!build.stages || build.stages.length === 0) return 0;

    let completedCount = 0;
    let runningCount = 0;

    for (const stage of build.stages) {
      const isComplete = stage.status === 'success' || stage.status === 'warning' ||
                        stage.status === 'error' || stage.status === 'skipped';
      const isRunning = stage.status === 'running';

      if (isComplete) {
        completedCount += 1;
      } else if (isRunning) {
        runningCount += 0.5;  // Running stage counts as half complete
      }
    }

    // Use actual totalStages from backend, or fall back to completed + 1 to avoid 100%
    const totalStages = build.totalStages || Math.max(completedCount + 1, 10);
    const progress = ((completedCount + runningCount) / totalStages) * 100;
    return Math.min(progress, 100);
  };

  // Get current running stage name
  const getCurrentStage = () => {
    if (build.currentStage) return build.currentStage;
    if (!build.stages) return null;
    const running = build.stages.find(s => s.status === 'running');
    return running?.displayName || running?.name || null;
  };

  // Trigger scroll-up animation when stage changes
  const currentStage = getCurrentStage();
  useEffect(() => {
    if (currentStage && currentStage !== prevStage) {
      setStageAnimating(true);
      setPrevStage(currentStage);
      const timer = setTimeout(() => setStageAnimating(false), 300);
      return () => clearTimeout(timer);
    }
  }, [currentStage, prevStage]);

  // Filter modules based on search
  const filteredModules = availableModules
    .filter(m => m.type === 'module' || m.type === 'component')
    .filter(m => {
      if (!searchQuery) return true;
      const query = searchQuery.toLowerCase();
      return (
        m.name.toLowerCase().includes(query) ||
        m.entry.toLowerCase().includes(query) ||
        m.file.toLowerCase().includes(query)
      );
    });

  // Focus search input when dropdown opens
  useEffect(() => {
    if (isEditingEntry && searchInputRef.current) {
      searchInputRef.current.focus();
    }
  }, [isEditingEntry]);

  // Validate build name as user types
  const nameValidation = useMemo(() => validateName(buildName), [buildName]);

  const handleNameSave = () => {
    // Only save if valid
    if (!nameValidation.isValid) {
      return; // Keep editing, don't close
    }
    setIsEditingName(false);
    if (onUpdateBuild) {
      onUpdateBuild(projectId, build.id, { name: buildName });
    }
  };

  const handleApplyNameSuggestion = (suggestion: string) => {
    setBuildName(suggestion);
  };

  const handleEntrySearch = (value: string) => {
    setSearchQuery(value);
  };

  const handleSelectModule = (module: ModuleDefinition) => {
    // Check if this entry is already used by another build in the project
    const existingBuild = allBuilds.find(
      b => b.id !== build.id && b.entry === module.entry
    );

    if (existingBuild) {
      // Show warning popup
      setDuplicateWarning({ entry: module.entry, usedBy: existingBuild.name });
      return;
    }

    // Clear any previous warning when selecting a valid entry
    setDuplicateWarning(null);
    setEntryPoint(module.entry);
    setIsEditingEntry(false);
    setSearchQuery('');
    if (onUpdateBuild) {
      onUpdateBuild(projectId, build.id, { entry: module.entry });
    }
  };

  const handleConfirmDuplicate = () => {
    if (!duplicateWarning) return;
    // User confirmed they want to use the duplicate entry
    setEntryPoint(duplicateWarning.entry);
    setIsEditingEntry(false);
    setSearchQuery('');
    setDuplicateWarning(null);
    if (onUpdateBuild) {
      onUpdateBuild(projectId, build.id, { entry: duplicateWarning.entry });
    }
  };

  const handleCancelDuplicate = () => {
    setDuplicateWarning(null);
  };

  const isSelected = selection.type === 'build' && selection.buildId === `${projectId}:${build.id}`;
  const hasStages = build.stages && build.stages.length > 0;

  return (
    <div
      className={`build-card ${isSelected ? 'selected' : ''} ${isBuilding ? 'building' : ''}`}
      onClick={(e) => {
        e.stopPropagation();
        onSelect({
          type: 'build',
          projectId,
          buildId: `${projectId}:${build.id}`,
          label: `${build.name}`
        });
      }}
    >
      {/* Header row - always visible */}
      <div
        className="build-card-header"
        onClick={(e) => {
          // If already selected and clicking on the header background, collapse
          if (isSelected) {
            e.stopPropagation();
            onSelect({ type: 'none' });
          }
        }}
      >
        <div className="build-header-left">
          {/* Status icon - hide in readOnly mode, show simple bullet instead */}
          {readOnly ? (
            <div className="build-status-icon">
              <Circle size={8} className="status-icon idle" />
            </div>
          ) : (
            <div className="build-status-icon">
              <StatusIcon status={build.status} size={14} queuePosition={build.queuePosition} />
            </div>
          )}

          {/* Editable build name - not editable in readOnly mode */}
          {isEditingName && isSelected && !readOnly ? (
            <div className="name-input-wrapper" onClick={(e) => e.stopPropagation()}>
              <input
                type="text"
                className={`build-name-input ${!nameValidation.isValid ? 'invalid' : ''}`}
                value={buildName}
                onChange={(e) => setBuildName(e.target.value)}
                onBlur={() => {
                  // Only close if valid, otherwise stay open
                  if (nameValidation.isValid) {
                    handleNameSave();
                  }
                }}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') handleNameSave();
                  if (e.key === 'Escape') {
                    setBuildName(build.name);
                    setIsEditingName(false);
                  }
                }}
                autoFocus
              />
              <NameValidationDropdown
                validation={nameValidation}
                onApplySuggestion={handleApplyNameSuggestion}
              />
            </div>
          ) : (
            <span
              className={`build-card-name ${isSelected && !readOnly ? 'editable' : ''}`}
              onClick={isSelected && !readOnly ? (e) => {
                e.stopPropagation();
                setIsEditingName(true);
              } : undefined}
              title={isSelected && !readOnly ? "Click to edit build name" : undefined}
            >
              {buildName}
            </span>
          )}

          {/* Current stage shown inline during building */}
          {isBuilding && currentStage && (
            <span className={`build-inline-stage ${stageAnimating ? 'animating' : ''}`}>
              {currentStage}
            </span>
          )}
        </div>

        <div className="build-header-right">
          {/* Indicators and buttons - hide in readOnly mode */}
          {!readOnly && (
            <>
              {/* Indicators wrapper */}
              <div className="build-indicators">
                {isBuilding && (
                  <span className="build-elapsed-time-inline">{formatBuildTime(elapsedTime)}</span>
                )}
                {!isBuilding && (
                  <>
                    {build.errors !== undefined && build.errors > 0 && (
                      <span
                        className="error-indicator clickable"
                        onClick={(e) => {
                          e.stopPropagation();
                          onStageFilter?.('', build.id, projectId);
                        }}
                        title="Click to filter problems for this build"
                      >
                        <AlertCircle size={12} />
                        <span>{build.errors}</span>
                      </span>
                    )}
                    {build.warnings !== undefined && build.warnings > 0 && (
                      <span
                        className="warning-indicator clickable"
                        onClick={(e) => {
                          e.stopPropagation();
                          onStageFilter?.('', build.id, projectId);
                        }}
                        title="Click to filter problems for this build"
                      >
                        <AlertTriangle size={12} />
                        <span>{build.warnings}</span>
                      </span>
                    )}

                    {build.elapsedSeconds ? (
                      <span className="build-duration">{build.elapsedSeconds.toFixed(1)}s</span>
                    ) : build.lastBuild ? (
                      <span className="last-build-info" title={`Last build: ${build.lastBuild.status}`}>
                        <StatusIcon status={build.lastBuild.status as any} size={10} dimmed />
                        <span className="last-build-time">{formatRelativeTime(build.lastBuild.timestamp)}</span>
                      </span>
                    ) : null}
                  </>
                )}
              </div>

              {/* Build play/cancel/delete button */}
              {isBuilding ? (
                <button
                  className="build-target-cancel-btn"
                  onClick={(e) => {
                    e.stopPropagation();
                    if (build.buildId && onCancelBuild) {
                      onCancelBuild(build.buildId);
                    }
                  }}
                  title={`Cancel build ${build.name}`}
                >
                  <Square size={10} fill="currentColor" />
                </button>
              ) : isSelected ? (
                <button
                  className="build-target-delete-btn"
                  onClick={(e) => {
                    e.stopPropagation();
                    setShowDeleteConfirm(true);
                  }}
                  title={`Delete build ${build.name}`}
                >
                  <Trash2 size={12} />
                </button>
              ) : (
                <button
                  className="build-target-play-btn"
                  onClick={(e) => {
                    e.stopPropagation();
                    onBuild('build', `${projectId}:${build.id}`, build.name);
                  }}
                  title={`Build ${build.name}`}
                >
                  <Play size={12} />
                </button>
              )}
            </>
          )}
        </div>
      </div>

      {/* Delete confirmation dialog - only in edit mode */}
      {!readOnly && showDeleteConfirm && (
        <div className="build-delete-confirm" onClick={(e) => e.stopPropagation()}>
          <span className="delete-confirm-text">Delete "{build.name}"?</span>
          <div className="delete-confirm-buttons">
            <button
              className="delete-confirm-btn cancel"
              onClick={() => setShowDeleteConfirm(false)}
            >
              Cancel
            </button>
            <button
              className="delete-confirm-btn confirm"
              onClick={() => {
                setShowDeleteConfirm(false);
                onDeleteBuild?.(projectId, build.id);
              }}
            >
              Delete
            </button>
          </div>
        </div>
      )}

      {/* Duplicate entry warning dialog */}
      {duplicateWarning && (
        <div className="build-duplicate-warning" onClick={(e) => e.stopPropagation()}>
          <div className="duplicate-warning-icon">
            <AlertTriangle size={16} />
          </div>
          <span className="duplicate-warning-text">
            This entry point is already used by "{duplicateWarning.usedBy}"
          </span>
          <div className="duplicate-warning-buttons">
            <button
              className="duplicate-warning-btn cancel"
              onClick={handleCancelDuplicate}
            >
              Cancel
            </button>
            <button
              className="duplicate-warning-btn confirm"
              onClick={handleConfirmDuplicate}
            >
              Use Anyway
            </button>
          </div>
        </div>
      )}

      {/* Build progress bar - only in edit mode */}
      {!readOnly && isBuilding && (
        <div className="build-progress-container">
          <div className="build-progress-bar">
            <div
              className="build-progress-fill"
              style={{ width: `${getProgress()}%` }}
            />
          </div>
        </div>
      )}

      {/* Expanded content - only when selected */}
      {isSelected && (
        <>
          {/* Entry point */}
          <div className="build-card-entry-row">
            <FileCode size={12} />
            {isEditingEntry && !readOnly ? (
              <div className="entry-picker" onClick={(e) => e.stopPropagation()}>
                <div className="entry-search-box">
                  <Search size={10} />
                  <input
                    ref={searchInputRef}
                    type="text"
                    className="entry-search-input"
                    value={searchQuery}
                    onChange={(e) => handleEntrySearch(e.target.value)}
                    onKeyDown={(e) => {
                      if (e.key === 'Escape') {
                        setSearchQuery('');
                        setIsEditingEntry(false);
                        setDuplicateWarning(null);
                      }
                      if (e.key === 'Enter' && filteredModules.length === 1) {
                        handleSelectModule(filteredModules[0]);
                      }
                    }}
                    placeholder="Search modules..."
                  />
                  <button
                    className="entry-close-btn"
                    onClick={() => {
                      setSearchQuery('');
                      setIsEditingEntry(false);
                      setDuplicateWarning(null);
                    }}
                  >
                    <X size={10} />
                  </button>
                </div>
                <div className="entry-dropdown">
                  {filteredModules.length > 0 ? (
                    filteredModules.map(module => (
                      <div
                        key={module.entry}
                        className={`entry-option ${module.entry === entryPoint ? 'selected' : ''}`}
                        onClick={() => handleSelectModule(module)}
                      >
                        <Box size={10} className={`module-type-icon ${module.type}`} />
                        <span className="entry-option-name">{module.name}</span>
                        <span className="entry-option-file">{module.file}</span>
                      </div>
                    ))
                  ) : availableModules.length === 0 ? (
                    <div className="entry-empty">
                      <span>No modules found in project</span>
                    </div>
                  ) : (
                    <div className="entry-empty">
                      <span>No matching modules for "{searchQuery}"</span>
                    </div>
                  )}
                </div>
              </div>
            ) : (
              <span
                className={`entry-path ${!readOnly ? 'editable' : ''}`}
                onClick={!readOnly ? (e) => {
                  e.stopPropagation();
                  setIsEditingEntry(true);
                  setSearchQuery('');
                } : undefined}
                title={!readOnly ? "Click to change entry point" : undefined}
              >
                {entryPoint}
              </span>
            )}
            {build.elapsedSeconds && (
              <span className="build-duration">
                <Clock size={10} />
                {build.elapsedSeconds.toFixed(1)}s
              </span>
            )}
          </div>

          {/* Build ID row */}
          {(build.buildId || build.lastBuild?.buildId) && (
            <div
              className="build-id-row"
              onClick={(e) => {
                e.stopPropagation();
                const id = build.buildId || build.lastBuild?.buildId;
                if (id) {
                  useStore.getState().setLogViewerBuildId(id);
                  sendAction('setLogViewCurrentId', { buildId: id });
                  // Open the ATOPILE LOGS panel (not the OUTPUT panel)
                  postMessage({ type: 'showBuildLogs' });
                }
              }}
              title="Click to view logs for this build"
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: 'var(--spacing-sm)',
                padding: '4px 8px 4px 24px',
                fontSize: 'var(--font-size-xs)',
                color: 'var(--text-muted)',
                cursor: 'pointer',
              }}
            >
              <span
                style={{
                  fontFamily: 'var(--font-mono)',
                  background: 'var(--bg-tertiary)',
                  padding: '1px 6px',
                  borderRadius: 'var(--radius-sm)',
                }}
              >
                {(build.buildId || build.lastBuild?.buildId)?.slice(0, 8)}
              </span>
              <span style={{ opacity: 0.7 }}>View logs</span>
            </div>
          )}

          {/* Build stages */}
          {hasStages && (
            <div className="build-stages-section">
              <button
                className="stages-toggle"
                onClick={(e) => {
                  e.stopPropagation();
                  setShowStages(!showStages);
                }}
              >
                {showStages ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
                <span>Build Stages</span>
                <span className="stages-summary">
                  {build.stages!.filter(s => s.status === 'success').length}/{build.stages!.length} complete
                </span>
              </button>

              {showStages && (
                <div className="build-stages-list">
                  {build.stages!.map((stage) => {
                    const isClickable = (stage.status === 'warning' || stage.status === 'error') && onStageFilter;
                    const stageDuration = stage.elapsedSeconds;
                    return (
                      <div
                        key={stage.name}
                        className={`stage-row ${stage.status} ${isClickable ? 'clickable' : ''}`}
                        onClick={isClickable ? (e) => {
                          e.stopPropagation();
                          onStageFilter(stage.name, build.id, projectId);
                        } : undefined}
                        title={isClickable ? `Filter problems to ${stage.displayName || stage.name} stage` : undefined}
                      >
                        <StatusIcon status={stage.status} size={12} />
                        <span className="stage-name">{stage.displayName || stage.name}</span>
                        {stage.message && (
                          <span className="stage-message">{stage.message}</span>
                        )}
                        <span className="stage-duration">
                          {stageDuration != null ? (
                            `${stageDuration.toFixed(1)}s`
                          ) : (
                            ''
                          )}
                        </span>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          )}

          {/* Action buttons - hide in readOnly mode */}
          {!readOnly && (
            <div className="build-card-actions">
              <button
                className="build-action-btn primary"
                onClick={(e) => {
                  e.stopPropagation();
                  onBuild('build', `${projectId}:${build.id}`, build.name);
                }}
                title={`Build ${build.name}`}
              >
                <Play size={12} />
                <span>Build</span>
              </button>
              <button
                className="build-action-btn"
                onClick={(e) => {
                  e.stopPropagation();
                  onOpenSource?.(projectId, build.entry);
                }}
                title="Open Source Code"
              >
                <FileCode size={12} />
                <span>ato</span>
              </button>
              <button
                className="build-action-btn"
                onClick={(e) => {
                  e.stopPropagation();
                  onOpenKiCad?.(projectId, build.id);
                }}
                title="Open in KiCad"
              >
                <Grid3X3 size={12} />
                <span>KiCad</span>
              </button>
              <button
                className="build-action-btn"
                onClick={(e) => {
                  e.stopPropagation();
                  onOpenLayout?.(projectId, build.id);
                }}
                title="Edit Layout"
              >
                <Layout size={12} />
                <span>Layout</span>
              </button>
              <button
                className="build-action-btn"
                onClick={(e) => {
                  e.stopPropagation();
                  onOpen3D?.(projectId, build.id);
                }}
                title="3D Preview"
              >
                <Cuboid size={12} />
                <span>3D</span>
              </button>
            </div>
          )}

        </>
      )}
    </div>
  );
});
