import { buildTmuxAutoInstallCapability } from '@features/tmux-installer/core/domain/policies/buildTmuxAutoInstallCapability';
import { buildEnrichedEnv } from '@main/utils/cliEnv';
import { getShellPreferredHome } from '@main/utils/shellEnv';

import { TmuxPackageManagerResolver } from '../platform/TmuxPackageManagerResolver';
import { TmuxPlatformResolver } from '../platform/TmuxPlatformResolver';
import { TmuxWslService } from '../wsl/TmuxWslService';

import { TmuxInstallTerminalSession } from './TmuxInstallTerminalSession';

import type {
  TmuxAutoInstallCapability,
  TmuxEffectiveAvailability,
  TmuxInstallStrategy,
  TmuxWslStatus,
} from '@features/tmux-installer/contracts';

export interface TmuxInstallPlan {
  capability: TmuxAutoInstallCapability;
  command: {
    command: string;
    args: string[];
    env: NodeJS.ProcessEnv;
    cwd: string;
    requiresPty: boolean;
    displayCommand?: string | null;
  } | null;
  retryWithUpdateCommand: {
    command: string;
    args: string[];
    env: NodeJS.ProcessEnv;
    cwd: string;
    requiresPty: boolean;
    displayCommand?: string | null;
  } | null;
}

export class TmuxInstallStrategyResolver {
  readonly #platformResolver: TmuxPlatformResolver;
  readonly #packageManagerResolver: TmuxPackageManagerResolver;
  readonly #wslService: TmuxWslService;

  constructor(
    platformResolver = new TmuxPlatformResolver(),
    packageManagerResolver = new TmuxPackageManagerResolver(),
    wslService = new TmuxWslService()
  ) {
    this.#platformResolver = platformResolver;
    this.#packageManagerResolver = packageManagerResolver;
    this.#wslService = wslService;
  }

  async resolve(): Promise<TmuxInstallPlan> {
    const env = buildEnrichedEnv();
    const cwd = getShellPreferredHome();
    const resolvedPlatform = await this.#platformResolver.resolve();

    if (resolvedPlatform.platform === 'darwin') {
      const manager = await this.#packageManagerResolver.resolveForMac(env);
      const canRunNonInteractiveSudo =
        manager.strategy === 'macports'
          ? await this.#packageManagerResolver.canRunNonInteractiveSudo(env)
          : true;
      const interactiveTerminalAvailable = TmuxInstallTerminalSession.isSupported();
      const capability = buildTmuxAutoInstallCapability({
        platform: resolvedPlatform.platform,
        strategy: manager.strategy,
        packageManagerLabel: manager.label,
        nonInteractivePrivilegeAvailable: canRunNonInteractiveSudo,
        interactiveTerminalAvailable,
      });
      return {
        capability,
        command: this.#buildCommand(manager.strategy, env, cwd, {
          requiresPty: manager.strategy === 'macports' && !canRunNonInteractiveSudo,
        }),
        retryWithUpdateCommand: null,
      };
    }

    if (resolvedPlatform.platform === 'linux') {
      const manager = await this.#packageManagerResolver.resolveForLinux(
        env,
        resolvedPlatform.linux
      );
      const canRunNonInteractiveSudo =
        manager.strategy === 'manual'
          ? false
          : await this.#packageManagerResolver.canRunNonInteractiveSudo(env);
      const interactiveTerminalAvailable = TmuxInstallTerminalSession.isSupported();
      const capability = buildTmuxAutoInstallCapability({
        platform: resolvedPlatform.platform,
        strategy: manager.strategy,
        packageManagerLabel: manager.label,
        immutableHost: resolvedPlatform.linux?.immutableHost ?? false,
        nonInteractivePrivilegeAvailable: canRunNonInteractiveSudo,
        interactiveTerminalAvailable,
      });
      return {
        capability,
        command: this.#buildCommand(manager.strategy, env, cwd, {
          requiresPty: manager.strategy !== 'manual' && !canRunNonInteractiveSudo,
        }),
        retryWithUpdateCommand:
          manager.strategy === 'apt' && canRunNonInteractiveSudo
            ? {
                command: 'sudo',
                args: ['-n', 'apt-get', 'update'],
                env,
                cwd,
                requiresPty: false,
              }
            : null,
      };
    }

    if (resolvedPlatform.platform === 'win32') {
      const wslProbe = await this.#wslService.probe();
      const interactiveTerminalAvailable = TmuxInstallTerminalSession.isSupported();
      if (
        wslProbe.status.wslInstalled &&
        !wslProbe.status.rebootRequired &&
        wslProbe.status.distroBootstrapped &&
        wslProbe.status.distroName &&
        wslProbe.status.innerPackageManager &&
        interactiveTerminalAvailable
      ) {
        return {
          capability: this.#buildWindowsCapability(wslProbe.status, interactiveTerminalAvailable),
          command: this.#buildWslCommand(
            wslProbe.status.distroName,
            wslProbe.status.innerPackageManager,
            env,
            cwd
          ),
          retryWithUpdateCommand: null,
        };
      }

      return {
        capability: this.#buildWindowsCapability(wslProbe.status, interactiveTerminalAvailable),
        command: null,
        retryWithUpdateCommand: null,
      };
    }

    const capability = buildTmuxAutoInstallCapability({
      platform: resolvedPlatform.platform,
      strategy: 'manual',
      packageManagerLabel: null,
      nonInteractivePrivilegeAvailable: false,
    });
    return {
      capability,
      command: null,
      retryWithUpdateCommand: null,
    };
  }

  buildStatusDetail(input: {
    platform: 'darwin' | 'linux' | 'win32' | 'unknown';
    effective: TmuxEffectiveAvailability;
    autoInstall: TmuxAutoInstallCapability;
    wsl: TmuxWslStatus | null;
  }): string | null {
    if (input.effective.detail) {
      return input.effective.detail;
    }

    if (input.effective.available) {
      return input.effective.location === 'wsl'
        ? 'tmux is available inside WSL on Windows.'
        : 'tmux is available.';
    }

    if (input.platform === 'darwin') {
      return 'You can keep using the app without tmux. Install tmux only if you want optional pane transport.';
    }
    if (input.platform === 'linux') {
      return 'You can keep using the app without tmux. Install tmux only if you want optional pane transport.';
    }
    if (input.platform === 'win32') {
      return (
        input.wsl?.statusDetail ??
        'You can keep using the app without tmux. On Windows, tmux setup uses WSL and is only needed for optional pane transport.'
      );
    }
    return 'You can keep using the app without tmux. Install tmux only if you want optional pane transport.';
  }

  #buildCommand(
    strategy: TmuxInstallStrategy,
    env: NodeJS.ProcessEnv,
    cwd: string,
    options: { requiresPty: boolean }
  ): TmuxInstallPlan['command'] {
    if (strategy === 'homebrew') {
      return { command: 'brew', args: ['install', 'tmux'], env, cwd, requiresPty: false };
    }
    if (strategy === 'macports') {
      return {
        command: 'sudo',
        args: options.requiresPty ? ['port', 'install', 'tmux'] : ['-n', 'port', 'install', 'tmux'],
        env,
        cwd,
        requiresPty: options.requiresPty,
      };
    }
    if (strategy === 'apt') {
      return {
        command: 'sudo',
        args: options.requiresPty
          ? ['apt-get', 'install', '-y', 'tmux']
          : ['-n', 'apt-get', 'install', '-y', 'tmux'],
        env,
        cwd,
        requiresPty: options.requiresPty,
      };
    }
    if (strategy === 'dnf') {
      return {
        command: 'sudo',
        args: options.requiresPty
          ? ['dnf', 'install', '-y', 'tmux']
          : ['-n', 'dnf', 'install', '-y', 'tmux'],
        env,
        cwd,
        requiresPty: options.requiresPty,
      };
    }
    if (strategy === 'yum') {
      return {
        command: 'sudo',
        args: options.requiresPty
          ? ['yum', 'install', '-y', 'tmux']
          : ['-n', 'yum', 'install', '-y', 'tmux'],
        env,
        cwd,
        requiresPty: options.requiresPty,
      };
    }
    if (strategy === 'zypper') {
      return {
        command: 'sudo',
        args: options.requiresPty
          ? ['zypper', '--non-interactive', 'install', 'tmux']
          : ['-n', 'zypper', '--non-interactive', 'install', 'tmux'],
        env,
        cwd,
        requiresPty: options.requiresPty,
      };
    }
    if (strategy === 'pacman') {
      return {
        command: 'sudo',
        args: options.requiresPty
          ? ['pacman', '-S', '--noconfirm', 'tmux']
          : ['-n', 'pacman', '-S', '--noconfirm', 'tmux'],
        env,
        cwd,
        requiresPty: options.requiresPty,
      };
    }
    return null;
  }

  #buildWslCommand(
    distroName: string,
    strategy: TmuxInstallStrategy,
    env: NodeJS.ProcessEnv,
    cwd: string
  ): TmuxInstallPlan['command'] {
    return {
      command: 'wsl.exe',
      args: ['-d', distroName, '--', 'sh', '-lc', this.#buildWslInstallShellCommand(strategy)],
      env,
      cwd,
      requiresPty: true,
      displayCommand: this.#buildWslDisplayCommand(distroName, strategy),
    };
  }

  #buildWslInstallShellCommand(strategy: TmuxInstallStrategy): string {
    if (strategy === 'apt') {
      return 'sudo apt-get install -y tmux';
    }
    if (strategy === 'dnf') {
      return 'sudo dnf install -y tmux';
    }
    if (strategy === 'yum') {
      return 'sudo yum install -y tmux';
    }
    if (strategy === 'zypper') {
      return 'sudo zypper --non-interactive install tmux';
    }
    if (strategy === 'pacman') {
      return 'sudo pacman -S --noconfirm tmux';
    }
    return 'sudo apt-get install -y tmux';
  }

  #buildWslDisplayCommand(distroName: string, strategy: TmuxInstallStrategy): string {
    return `wsl -d ${distroName} -- sh -lc "${this.#buildWslInstallShellCommand(strategy)}"`;
  }

  #buildWindowsCapability(
    status: TmuxWslStatus,
    interactiveTerminalAvailable: boolean
  ): TmuxAutoInstallCapability {
    const baseCapability = buildTmuxAutoInstallCapability({
      platform: 'win32',
      strategy: 'wsl',
      packageManagerLabel: 'WSL',
      nonInteractivePrivilegeAvailable: false,
      interactiveTerminalAvailable,
    });
    const manualHints = [...baseCapability.manualHints];

    if (status.distroName && status.innerPackageManager) {
      this.#prependUniqueHint(manualHints, {
        title: `Install tmux in ${status.distroName}`,
        description:
          'The app can run this inside WSL and forward Linux terminal input if sudo prompts for the distro password.',
        command: this.#buildWslDisplayCommand(status.distroName, status.innerPackageManager),
      });
    }

    if (status.wslInstalled && !status.distroName) {
      this.#prependUniqueHint(manualHints, {
        title: 'Install Ubuntu',
        description: 'Recommended WSL distro for optional tmux pane transport.',
        command: 'wsl --install -d Ubuntu --no-launch',
      });
    }

    if (!status.wslInstalled) {
      return {
        ...baseCapability,
        supported: true,
        requiresAdmin: true,
        requiresRestart: false,
        requiresTerminalInput: false,
        mayOpenExternalWindow: true,
        reasonIfUnsupported: null,
        manualHints,
      };
    }

    if (status.rebootRequired) {
      return {
        ...baseCapability,
        supported: false,
        requiresAdmin: false,
        requiresRestart: true,
        mayOpenExternalWindow: false,
        reasonIfUnsupported:
          'WSL was installed, but Windows still needs a restart before tmux setup can continue.',
        manualHints,
      };
    }

    if (!status.distroName) {
      return {
        ...baseCapability,
        supported: true,
        requiresAdmin: false,
        requiresRestart: false,
        requiresTerminalInput: false,
        mayOpenExternalWindow: true,
        reasonIfUnsupported: null,
        manualHints,
      };
    }

    if (!status.distroBootstrapped) {
      return {
        ...baseCapability,
        supported: false,
        requiresAdmin: false,
        requiresRestart: false,
        requiresTerminalInput: false,
        mayOpenExternalWindow: true,
        reasonIfUnsupported: `${status.distroName} still needs its first Linux user setup before tmux can be installed there.`,
        manualHints,
      };
    }

    if (!status.innerPackageManager) {
      return {
        ...baseCapability,
        supported: false,
        requiresAdmin: false,
        requiresRestart: false,
        requiresTerminalInput: false,
        mayOpenExternalWindow: false,
        reasonIfUnsupported: `${status.distroName} is available in WSL, but the app could not determine its package manager.`,
        manualHints,
      };
    }

    if (!interactiveTerminalAvailable) {
      return {
        ...baseCapability,
        supported: false,
        requiresAdmin: false,
        requiresRestart: false,
        requiresTerminalInput: true,
        mayOpenExternalWindow: false,
        reasonIfUnsupported:
          'Interactive installer terminal support is unavailable in this build, so WSL tmux install must be finished manually.',
        manualHints,
      };
    }

    return {
      ...baseCapability,
      supported: true,
      requiresAdmin: false,
      requiresRestart: false,
      requiresTerminalInput: true,
      mayOpenExternalWindow: false,
      reasonIfUnsupported: null,
      manualHints,
    };
  }

  #prependUniqueHint(
    manualHints: TmuxAutoInstallCapability['manualHints'],
    nextHint: TmuxAutoInstallCapability['manualHints'][number]
  ): void {
    if (
      manualHints.some(
        (hint) =>
          hint.title === nextHint.title ||
          (hint.command && nextHint.command && hint.command === nextHint.command)
      )
    ) {
      return;
    }
    manualHints.unshift(nextHint);
  }
}
