/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as vscode from 'vscode';
import * as path from 'path';
import { getDefaultShell, getProjectType } from './utils';
import { resolveKeelsCommand } from './cjmpSdk';

export interface BuildPrompt {
  pickBuildType(items: readonly string[], options: vscode.QuickPickOptions): Promise<string | undefined>;
  pickBuildMode(items: readonly string[], options: vscode.QuickPickOptions): Promise<string | undefined>;
}

export interface TerminalFactory {
  create(options: vscode.TerminalOptions): vscode.Terminal;
}

export interface BuildDependencies {
  prompt: BuildPrompt;
  terminalFactory: TerminalFactory;
}

const defaultBuildDependencies: BuildDependencies = {
  prompt: {
    pickBuildType: async (items, options) => vscode.window.showQuickPick(items, options),
    pickBuildMode: async (items, options) => vscode.window.showQuickPick(items, options),
  },
  terminalFactory: {
    create: (options) => vscode.window.createTerminal(options),
  },
};

export async function buildCjmpProject(
  dependencies: BuildDependencies = defaultBuildDependencies,
): Promise<void> {
  const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;

  if (workspaceRoot) {
    console.log('The root directory of the workspace: ', workspaceRoot);
  } else {
    vscode.window.showErrorMessage('No folder or workspace is opened.');
    return;
  }

  const projectType = getProjectType();

  if (projectType === 'app') {
    await buildAppProject(workspaceRoot, dependencies);
  } else if (
    projectType === 'library'
    || projectType === 'logic-module'
    || projectType === 'module'
  ) {
    await buildPackageProject(workspaceRoot, dependencies);
  } else {
    return;
  }
}

function resolveTargetPlatform(type: string): string | undefined {
  const platformMap = new Map<string, string>([
    ['apk', 'android-arm64'],
    ['hap', 'ohos-arm64'],
    ['ios', 'ios-arm64'],
    ['ipa', 'ios-arm64'],
    ['ios-sim', 'ios-sim-arm64'],

    ['aar', 'android-arm64'],
    ['har', 'ohos-arm64'],
    ['framework', 'ios-arm64'],
    ['framework-sim', 'ios-sim-arm64'],
  ]);

  return platformMap.get(type);
}

async function buildAppProject(workspaceRoot: string, dependencies: BuildDependencies) {
  const modeOptions = ['debug', 'release'];
  const types = process.platform === 'darwin' ? ['apk', 'hap', 'ios', 'ipa', 'ios-sim'] : ['apk', 'hap'];

  const type = await dependencies.prompt.pickBuildType(types, {
    placeHolder: 'Select the app type',
  });

  if (!type) {
    vscode.window.showWarningMessage('Build canceled: No type selected.');
    return;
  }

  const targetPlatform = resolveTargetPlatform(type);
  if (!targetPlatform) {
    vscode.window.showWarningMessage('Build canceled: No target platform is available for this artifact type.');
    return;
  }

  const mode = await dependencies.prompt.pickBuildMode(modeOptions, {
    placeHolder: 'Select the build mode',
  });

  if (!mode) {
    vscode.window.showWarningMessage('Build canceled: No build mode selected.');
    return;
  }

  await cjmpBuildWithSpawn(workspaceRoot, type, targetPlatform, mode, dependencies.terminalFactory);
}

async function buildPackageProject(workspaceRoot: string, dependencies: BuildDependencies) {
  const modeOptions = ['debug', 'release'];
  const types = process.platform === 'darwin' ? ['aar', 'har', 'framework', 'framework-sim'] : ['aar', 'har'];

  const type = await dependencies.prompt.pickBuildType(types, {
    placeHolder: 'Select the package type',
  });

  if (!type) {
    vscode.window.showWarningMessage('Build canceled: No type selected.');
    return;
  }

  const targetPlatform = resolveTargetPlatform(type);
  if (!targetPlatform) {
    vscode.window.showWarningMessage('Build canceled: No target platform is available for this artifact type.');
    return;
  }

  const mode = await dependencies.prompt.pickBuildMode(modeOptions, {
    placeHolder: 'Select the build mode',
  });

  if (!mode) {
    vscode.window.showWarningMessage('Build canceled: No build mode selected.');
    return;
  }

  await cjmpBuildWithSpawn(workspaceRoot, type, targetPlatform, mode, dependencies.terminalFactory);
}

const cjmpBuildWithSpawn = async (
  localPath: string | undefined,
  type: string,
  target_platform: string,
  mode: string,
  terminalFactory: TerminalFactory,
): Promise<void> => {
  return new Promise((resolve, reject) => {
    try {
      const keelsCommand = resolveKeelsCommand();
      if (!keelsCommand) {
        resolve();
        return;
      }

      const isWindows = process.platform === 'win32';
      const shellPath = isWindows ? 'cmd.exe' : getDefaultShell();

      const buildCommand = `${keelsCommand.executablePath} build ${type} --platform ${target_platform} --${mode} -v`;

      const terminal = terminalFactory.create({
        name: 'CJMP Build Terminal',
        shellPath: shellPath,
        cwd: localPath,
        env: keelsCommand.environment,
      });
      terminal.show();
      terminal.sendText(`${buildCommand}`);
      resolve();

    } catch (error) {
      vscode.window.showErrorMessage(`Error building ${type}. : ${error instanceof Error ? error.message : String(error)}`);
      reject(error);
    }
  });
};