import { SetupWizardStepConfig } from '../step-config';
import { checkDockerStatus, checkHomebrewStatus } from '../../system-manager';
import { checkArtifactoryStatus } from '../../services/artifactory-manager';
import { checkSshKeyStatus, testGitHubSshConnection, testGerritSshConnection, getGerritUsername } from '../../services/ssh-manager';
import { checkInstCliStatus } from '../../services/inst-cli-manager';
import { checkGitConfigStatus } from '../../services/git-manager';
import { checkFrpcStatus } from '../../services/frpc-manager';
import { checkFrpcConfigStatus } from '../../services/frpc-config-manager';
import { checkGitCloneStatus } from '../../services/git-clone-manager';
import { checkInstConfigStatus } from '../../services/inst-config-manager';
import { checkInstCliProxyStatus } from '../../services/inst-cli-proxy-manager';
import { checkBuildRunStatus } from '../../services/build-run-manager';
import { settingsStore } from '../../store';
import log from 'electron-log';

/**
 * Setup Wizard steps registry
 * Add new steps here to extend the setup wizard
 */
export const SETUP_WIZARD_STEPS: SetupWizardStepConfig[] = [
  {
    id: 'homebrew-setup',
    title: 'Homebrew',
    description: 'Ensure Homebrew package manager is installed',
    componentName: 'HomebrewSetupStep',
    order: 0,
    required: true,
    validate: async () => {
      const homebrewStatus = await checkHomebrewStatus();

      // Check for warnings
      const hasWarnings = homebrewStatus.installed && homebrewStatus.updateAvailable;

      let message = homebrewStatus.installed
        ? hasWarnings
          ? `Homebrew ${homebrewStatus.version} installed (Update available)`
          : `Homebrew ${homebrewStatus.version} is installed`
        : 'Homebrew needs to be installed';

      return {
        isComplete: homebrewStatus.installed,
        canProceed: true,
        hasWarnings,
        message,
        details: homebrewStatus
      };
    },
    icon: 'Package2'
  },
  {
    id: 'docker-setup',
    title: 'Docker',
    description: 'Ensure Docker is installed and running',
    componentName: 'DockerSetupStep',
    order: 1,
    required: true,
    validate: async () => {
      const dockerStatus = await checkDockerStatus();

      // Check for warnings
      let hasWarnings = false;
      const warnings: string[] = [];

      if (dockerStatus.installed && dockerStatus.daemonRunning) {
        // Check if update is available
        if (dockerStatus.updateAvailable) {
          hasWarnings = true;
          warnings.push('Update available');
        }

        // Check if settings are below recommended
        if (dockerStatus.settings) {
          const { cpus, cpusRecommended, memoryMiB, memoryRecommended, swapMiB, swapRecommended, diskSizeMiB, diskSizeRecommended } = dockerStatus.settings;

          if (cpus < cpusRecommended || memoryMiB < memoryRecommended || swapMiB < swapRecommended || diskSizeMiB < diskSizeRecommended) {
            hasWarnings = true;
            warnings.push('Settings below recommended');
          }
        }
      }

      let message = dockerStatus.installed
        ? dockerStatus.daemonRunning
          ? hasWarnings
            ? `Docker is running (${warnings.join(', ')})`
            : 'Docker is installed and running'
          : 'Docker is installed but daemon is not running'
        : 'Docker needs to be installed';

      return {
        isComplete: dockerStatus.installed && dockerStatus.daemonRunning,
        canProceed: dockerStatus.installed,
        hasWarnings,
        message,
        details: dockerStatus
      };
    },
    icon: 'Container'
  },
  {
    id: 'artifactory-setup',
    title: 'Artifactory',
    description: 'Configure JFrog Artifactory credentials',
    componentName: 'ArtifactorySetupStep',
    order: 2,
    required: true,
    validate: async () => {
      const artifactoryStatus = await checkArtifactoryStatus();
      const gemrcOk = artifactoryStatus.gemrcExists && artifactoryStatus.credentialsValid === true;
      const npmrcOk = artifactoryStatus.npmrcConfigured;
      const isComplete = gemrcOk && npmrcOk;

      let message = 'Needs configuration';
      if (gemrcOk && npmrcOk) {
        message = 'Artifactory is configured with valid credentials';
      } else if (gemrcOk && !npmrcOk) {
        message = '~/.npmrc not configured for @inst registry';
      } else if (artifactoryStatus.gemrcExists && artifactoryStatus.credentialsValid === false) {
        message = `Invalid credentials${artifactoryStatus.credentialsValidationError ? ': ' + artifactoryStatus.credentialsValidationError : ''}`;
      }

      return {
        isComplete,
        canProceed: true,
        message,
        details: artifactoryStatus
      };
    },
    icon: 'Package'
  },
  {
    id: 'ssh-keys-setup',
    title: 'SSH Keys',
    description: 'Configure SSH keys for Git authentication',
    componentName: 'SshKeysSetupStep',
    order: 3,
    required: true,
    validate: async () => {
      const sshKeyStatus = await checkSshKeyStatus();

      // Check if keys exist, are valid, AND SSH config is correct
      const keysValid = sshKeyStatus.keysExist && sshKeyStatus.valid;
      const configValid = sshKeyStatus.configCorrect === true;
      const isComplete = keysValid && configValid;

      let message = 'SSH keys need to be configured';
      if (keysValid && !configValid) {
        message = 'SSH keys exist but config needs to be updated';
      } else if (isComplete) {
        message = 'SSH keys and config are properly configured';
      }

      return {
        isComplete,
        canProceed: true,
        message,
        details: sshKeyStatus
      };
    },
    icon: 'Key'
  },
  {
    id: 'gerrit-setup',
    title: 'Gerrit',
    description: 'Add SSH key to Gerrit for repository access',
    componentName: 'GerritSetupStep',
    order: 4,
    required: true,
    validate: async () => {
      // First check if SSH keys exist - don't waste time testing connection if no keys
      const sshKeyStatus = await checkSshKeyStatus();

      if (!sshKeyStatus.keysExist || !sshKeyStatus.valid) {
        return {
          isComplete: false,
          canProceed: true,
          message: 'SSH keys need to be configured first',
          details: {
            connected: false,
            sshKeyStatus
          }
        };
      }

      // Check if username is configured in step data or SSH config
      const onboardingState = settingsStore.get('onboarding');
      const stepData = onboardingState.stepStatus['gerrit-setup'];
      let username = stepData?.data?.username;

      // If not in step data, try to get from SSH config
      if (!username) {
        username = await getGerritUsername();
      }

      if (!username) {
        return {
          isComplete: false,
          canProceed: true,
          message: 'Gerrit username is required',
          details: {
            connected: false
          }
        };
      }

      // Test actual SSH connection to Gerrit using the configured private key
      const connectionTest = await testGerritSshConnection(sshKeyStatus.privateKeyPath);

      return {
        isComplete: connectionTest.connected,
        canProceed: true,
        message: connectionTest.message,
        details: {
          connected: connectionTest.connected,
          username: connectionTest.username
        }
      };
    },
    icon: 'Share2'
  },
  {
    id: 'github-setup',
    title: 'GitHub',
    description: 'Add SSH key to GitHub for repository access',
    componentName: 'GitHubSetupStep',
    order: 5,
    required: true,
    validate: async () => {
      // First check if SSH keys exist - don't waste time testing connection if no keys
      const sshKeyStatus = await checkSshKeyStatus();

      if (!sshKeyStatus.keysExist || !sshKeyStatus.valid) {
        return {
          isComplete: false,
          canProceed: true,
          message: 'SSH keys need to be configured first',
          details: {
            connected: false,
            sshKeyStatus
          }
        };
      }

      // Test actual SSH connection to GitHub using the configured private key
      const connectionTest = await testGitHubSshConnection(sshKeyStatus.privateKeyPath);

      return {
        isComplete: connectionTest.connected,
        canProceed: true,
        message: connectionTest.message,
        details: {
          connected: connectionTest.connected,
          username: connectionTest.username
        }
      };
    },
    icon: 'Github'
  },
  {
    id: 'git-setup',
    title: 'Git Config',
    description: 'Configure Git user name and email',
    componentName: 'GitSetupStep',
    order: 6,
    required: true,
    validate: async () => {
      const gitStatus = await checkGitConfigStatus();
      const hasNameAndEmail = !!(gitStatus.gitInstalled && gitStatus.gitconfigExists && gitStatus.name && gitStatus.email);
      return {
        isComplete: hasNameAndEmail,
        canProceed: true,
        message: hasNameAndEmail
          ? 'Git is configured'
          : gitStatus.gitInstalled
          ? 'Git configuration needs to be set'
          : 'Git needs to be installed',
        details: gitStatus
      };
    },
    icon: 'GitBranch'
  },
  {
    id: 'git-clone',
    title: 'Git Clone',
    description: 'Clone canvas-lms repository',
    componentName: 'GitCloneStep',
    order: 7,
    required: true,
    validate: async () => {
      const onboardingState = settingsStore.get('onboarding');
      const stepData = onboardingState.stepStatus['git-clone'];
      const cloneFolder = stepData?.data?.cloneFolder;
      const folderName = stepData?.data?.folderName || 'dev';

      log.debug('Validating git-clone step:', { cloneFolder, folderName, stepData });

      const gitCloneStatus = await checkGitCloneStatus(cloneFolder, folderName);
      log.debug('Git clone validation result:', {
        configured: gitCloneStatus.configured,
        isValidRepo: gitCloneStatus.isValidRepo,
        isComplete: gitCloneStatus.configured && gitCloneStatus.isValidRepo
      });

      return {
        isComplete: gitCloneStatus.configured && gitCloneStatus.isValidRepo,
        canProceed: true,
        message: gitCloneStatus.configured
          ? `canvas-lms repository is cloned at ${gitCloneStatus.repositoryPath}`
          : 'canvas-lms repository needs to be cloned',
        details: gitCloneStatus
      };
    },
    icon: 'GitBranch'
  },
  {
    id: 'inst-cli-install',
    title: 'inst-cli Install',
    description: 'Build the inst-cli Docker image',
    componentName: 'InstallInstCliStep',
    order: 8,
    required: true,
    validate: async () => {
      const instCliStatus = await checkInstCliStatus();

      let message = 'inst-cli image needs to be built';
      let hasWarnings = false;

      if (instCliStatus.imageExists) {
        if (instCliStatus.updateAvailable) {
          hasWarnings = true;
          const updates: string[] = [];
          if (instCliStatus.instUpdateAvailable) {
            updates.push('inst');
          }
          if (instCliStatus.instCliQuizzesUpdateAvailable) {
            updates.push('inst-cli-quizzes');
          }
          message = `inst-cli image is built (Updates available: ${updates.join(', ')})`;
        } else {
          message = 'inst-cli image is built';
        }
      }

      return {
        isComplete: instCliStatus.imageExists,
        canProceed: true,
        hasWarnings,
        message,
        details: instCliStatus
      };
    },
    icon: 'Terminal'
  },
  {
    id: 'inst-cli-config-file',
    title: 'inst-cli Config',
    description: 'Configure inst-cli configuration file',
    componentName: 'InstCliConfigFileStep',
    order: 9,
    required: true,
    validate: async () => {
      const onboardingState = settingsStore.get('onboarding');
      const gitCloneStepData = onboardingState.stepStatus['git-clone'];
      const cloneFolder = gitCloneStepData?.data?.cloneFolder;
      const folderName = gitCloneStepData?.data?.folderName || 'dev';

      const instConfigStatus = await checkInstConfigStatus(cloneFolder, folderName);

      // Check if step is marked as configured (saved successfully)
      const stepData = onboardingState.stepStatus['inst-cli-config-file'];
      const isConfigured = stepData?.completed === true && instConfigStatus.exists;

      return {
        isComplete: isConfigured,
        canProceed: true,
        message: isConfigured
          ? `inst.yml is configured at ${instConfigStatus.path}`
          : instConfigStatus.exists
          ? 'inst.yml exists but needs to be saved with valid configuration'
          : 'inst.yml needs to be configured',
        details: instConfigStatus
      };
    },
    icon: 'Terminal'
  },
  {
    id: 'inst-cli-proxy',
    title: 'inst-cli Proxy',
    description: 'Configure inst-cli proxy with Dozzle',
    componentName: 'InstCliProxyStep',
    order: 10,
    required: true,
    validate: async () => {
      const instCliProxyStatus = await checkInstCliProxyStatus();

      return {
        isComplete: instCliProxyStatus.configured,
        canProceed: true,
        message: instCliProxyStatus.configured
          ? 'inst-cli proxy is configured'
          : instCliProxyStatus.instDomain
          ? 'inst-cli proxy needs configuration'
          : 'inst_domain not found in inst.yml',
        details: instCliProxyStatus
      };
    },
    icon: 'Network'
  },
  {
    id: 'build-run',
    title: 'Build and Run',
    description: 'Build and run Canvas',
    componentName: 'BuildRunStep',
    order: 11,
    required: true,
    validate: async () => {
      const multiDeploy = settingsStore.get('multiDeploy');
      const buildRunStatus = await checkBuildRunStatus(multiDeploy);
      return {
        isComplete: buildRunStatus.configured,
        canProceed: true,
        message: buildRunStatus.configured
          ? 'Canvas is running'
          : buildRunStatus.instDomain
          ? 'Canvas needs to be built and run'
          : 'inst_domain not found in inst.yml',
        details: buildRunStatus
      };
    },
    icon: 'Play'
  },
  {
    id: 'frpc-setup',
    title: 'FRPC Install',
    description: 'Install FRPC (Fast Reverse Proxy Client)',
    componentName: 'FrpcSetupStep',
    order: 12,
    required: false,
    validate: async () => {
      const frpcStatus = await checkFrpcStatus();

      // Check for warnings
      const hasWarnings = frpcStatus.installed && frpcStatus.updateAvailable;

      let message = frpcStatus.installed
        ? hasWarnings
          ? `FRPC ${frpcStatus.version} installed (Update available)`
          : `FRPC ${frpcStatus.version} is installed`
        : 'FRPC is not installed (Optional)';

      return {
        isComplete: frpcStatus.installed,
        canProceed: true,
        hasWarnings,
        message,
        details: frpcStatus
      };
    },
    icon: 'Network'
  },
  {
    id: 'frpc-config',
    title: 'FRPC Config',
    description: 'Configure FRPC as a system service',
    componentName: 'FrpcConfigStep',
    order: 13,
    required: false,
    validate: async () => {
      const frpcConfigStatus = await checkFrpcConfigStatus();

      let message = frpcConfigStatus.configured
        ? 'FRPC service is running'
        : frpcConfigStatus.serviceFileExists && frpcConfigStatus.configFileExists
        ? 'FRPC service is configured but not running'
        : 'FRPC service is not configured (Optional)';

      return {
        isComplete: frpcConfigStatus.configured,
        canProceed: true,
        message,
        details: frpcConfigStatus
      };
    },
    icon: 'Network'
  },
  {
    id: 'chrome-extension',
    title: 'Instructure Agent Chrome Extension',
    description: 'Install the Instructure Agent Chrome Extension',
    componentName: 'ChromeExtensionStep',
    order: 14,
    required: false,
    validate: async () => {
      return {
        isComplete: true,
        canProceed: true,
        message: 'Instructure Agent Chrome Extension'
      };
    },
    icon: 'Chrome'
  }
];
