// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/io.dart';

import '../../bin/xcode_backend.dart';
import '../src/common.dart';
import '../src/fake_process_manager.dart';

void main() {
  late MemoryFileSystem fileSystem;

  setUp(() {
    fileSystem = MemoryFileSystem();
  });

  group('build', () {
    test('exits with useful error message when build mode not set', () {
      final Directory buildDir = fileSystem.directory('/path/to/builds')
        ..createSync(recursive: true);
      final Directory flutterRoot = fileSystem.directory('/path/to/flutter')
        ..createSync(recursive: true);
      final File pipe = fileSystem.file('/tmp/pipe')
        ..createSync(recursive: true);
      const String buildMode = 'Debug';
      final TestContext context = TestContext(
        <String>['build'],
        <String, String>{
          'BUILT_PRODUCTS_DIR': buildDir.path,
          'ENABLE_BITCODE': 'YES',
          'FLUTTER_ROOT': flutterRoot.path,
          'INFOPLIST_PATH': 'Info.plist',
        },
        commands: <FakeCommand>[
          FakeCommand(
            command: <String>[
              '${flutterRoot.path}/bin/flutter',
              'assemble',
              '--no-version-check',
              '--output=${buildDir.path}/',
              '-dTargetPlatform=ios',
              '-dTargetFile=lib/main.dart',
              '-dBuildMode=${buildMode.toLowerCase()}',
              '-dIosArchs=',
              '-dSdkRoot=',
              '-dSplitDebugInfo=',
              '-dTreeShakeIcons=',
              '-dTrackWidgetCreation=',
              '-dDartObfuscation=',
              '-dEnableBitcode=',
              '--ExtraGenSnapshotOptions=',
              '--DartDefines=',
              '--ExtraFrontEndOptions=',
              'debug_ios_bundle_flutter_assets',
            ],
          ),
        ],
        fileSystem: fileSystem,
        scriptOutputStreamFile: pipe,
      );
      expect(
          () => context.run(),
          throwsException,
      );
      expect(
        context.stderr,
        contains('ERROR: Unknown FLUTTER_BUILD_MODE: null.\n'),
      );
    });
    test('calls flutter assemble', () {
      final Directory buildDir = fileSystem.directory('/path/to/builds')
        ..createSync(recursive: true);
      final Directory flutterRoot = fileSystem.directory('/path/to/flutter')
        ..createSync(recursive: true);
      final File pipe = fileSystem.file('/tmp/pipe')
        ..createSync(recursive: true);
      const String buildMode = 'Debug';
      final TestContext context = TestContext(
        <String>['build'],
        <String, String>{
          'BUILT_PRODUCTS_DIR': buildDir.path,
          'CONFIGURATION': buildMode,
          'ENABLE_BITCODE': 'YES',
          'FLUTTER_ROOT': flutterRoot.path,
          'INFOPLIST_PATH': 'Info.plist',
        },
        commands: <FakeCommand>[
          FakeCommand(
            command: <String>[
              '${flutterRoot.path}/bin/flutter',
              'assemble',
              '--no-version-check',
              '--output=${buildDir.path}/',
              '-dTargetPlatform=ios',
              '-dTargetFile=lib/main.dart',
              '-dBuildMode=${buildMode.toLowerCase()}',
              '-dIosArchs=',
              '-dSdkRoot=',
              '-dSplitDebugInfo=',
              '-dTreeShakeIcons=',
              '-dTrackWidgetCreation=',
              '-dDartObfuscation=',
              '-dEnableBitcode=',
              '--ExtraGenSnapshotOptions=',
              '--DartDefines=',
              '--ExtraFrontEndOptions=',
              'debug_ios_bundle_flutter_assets',
            ],
          ),
        ],
        fileSystem: fileSystem,
        scriptOutputStreamFile: pipe,
      )..run();
      final List<String> streamedLines = pipe.readAsLinesSync();
      // Ensure after line splitting, the exact string 'done' appears
      expect(streamedLines, contains('done'));
      expect(streamedLines, contains(' └─Compiling, linking and signing...'));
      expect(
        context.stdout,
        contains('built and packaged successfully.'),
      );
      expect(context.stderr, isEmpty);
    });

    test('forwards all env variables to flutter assemble', () {
      final Directory buildDir = fileSystem.directory('/path/to/builds')
        ..createSync(recursive: true);
      final Directory flutterRoot = fileSystem.directory('/path/to/flutter')
        ..createSync(recursive: true);
      const String archs = 'arm64 armv7';
      const String buildMode = 'Release';
      const String dartObfuscation = 'false';
      const String dartDefines = 'flutter.inspector.structuredErrors%3Dtrue';
      const String expandedCodeSignIdentity = 'F1326572E0B71C3C8442805230CB4B33B708A2E2';
      const String extraFrontEndOptions = '--some-option';
      const String extraGenSnapshotOptions = '--obfuscate';
      const String sdkRoot = '/path/to/sdk';
      const String splitDebugInfo = '/path/to/split/debug/info';
      const String trackWidgetCreation = 'true';
      const String treeShake = 'true';
      final TestContext context = TestContext(
        <String>['build'],
        <String, String>{
          'ACTION': 'install',
          'ARCHS': archs,
          'BUILT_PRODUCTS_DIR': buildDir.path,
          'CODE_SIGNING_REQUIRED': 'YES',
          'CONFIGURATION': buildMode,
          'DART_DEFINES': dartDefines,
          'DART_OBFUSCATION': dartObfuscation,
          'ENABLE_BITCODE': 'YES',
          'EXPANDED_CODE_SIGN_IDENTITY': expandedCodeSignIdentity,
          'EXTRA_FRONT_END_OPTIONS': extraFrontEndOptions,
          'EXTRA_GEN_SNAPSHOT_OPTIONS': extraGenSnapshotOptions,
          'FLUTTER_ROOT': flutterRoot.path,
          'INFOPLIST_PATH': 'Info.plist',
          'SDKROOT': sdkRoot,
          'SPLIT_DEBUG_INFO': splitDebugInfo,
          'TRACK_WIDGET_CREATION': trackWidgetCreation,
          'TREE_SHAKE_ICONS': treeShake,
        },
        commands: <FakeCommand>[
          FakeCommand(
            command: <String>[
              '${flutterRoot.path}/bin/flutter',
              'assemble',
              '--no-version-check',
              '--output=${buildDir.path}/',
              '-dTargetPlatform=ios',
              '-dTargetFile=lib/main.dart',
              '-dBuildMode=${buildMode.toLowerCase()}',
              '-dIosArchs=$archs',
              '-dSdkRoot=$sdkRoot',
              '-dSplitDebugInfo=$splitDebugInfo',
              '-dTreeShakeIcons=$treeShake',
              '-dTrackWidgetCreation=$trackWidgetCreation',
              '-dDartObfuscation=$dartObfuscation',
              '-dEnableBitcode=true',
              '--ExtraGenSnapshotOptions=$extraGenSnapshotOptions',
              '--DartDefines=$dartDefines',
              '--ExtraFrontEndOptions=$extraFrontEndOptions',
              '-dCodesignIdentity=$expandedCodeSignIdentity',
              'release_ios_bundle_flutter_assets',
            ],
          ),
        ],
        fileSystem: fileSystem,
      )..run();
      expect(
        context.stdout,
        contains('built and packaged successfully.'),
      );
      expect(context.stderr, isEmpty);
    });
  });

  group('test_observatory_bonjour_service', () {
    test('handles when the Info.plist is missing', () {
      final Directory buildDir = fileSystem.directory('/path/to/builds');
      buildDir.createSync(recursive: true);
      final TestContext context = TestContext(
        <String>['test_observatory_bonjour_service'],
        <String, String>{
          'CONFIGURATION': 'Debug',
          'BUILT_PRODUCTS_DIR': buildDir.path,
          'INFOPLIST_PATH': 'Info.plist',
        },
        commands: <FakeCommand>[],
        fileSystem: fileSystem,
      )..run();
      expect(
        context.stdout,
        contains(
            'Info.plist does not exist. Skipping _dartobservatory._tcp NSBonjourServices insertion.'),
      );
    });
  });
}

class TestContext extends Context {
  TestContext(
    List<String> arguments,
    Map<String, String> environment, {
    required this.fileSystem,
    required List<FakeCommand> commands,
    File? scriptOutputStreamFile,
  })  : processManager = FakeProcessManager.list(commands),
        super(arguments: arguments, environment: environment, scriptOutputStreamFile: scriptOutputStreamFile);

  final FileSystem fileSystem;
  final FakeProcessManager processManager;

  String stdout = '';
  String stderr = '';

  @override
  bool existsDir(String path) {
    return fileSystem.directory(path).existsSync();
  }

  @override
  bool existsFile(String path) {
    return fileSystem.file(path).existsSync();
  }

  @override
  ProcessResult runSync(
    String bin,
    List<String> args, {
    bool verbose = false,
    bool allowFail = false,
    String? workingDirectory,
  }) {
    return processManager.runSync(
      <dynamic>[bin, ...args],
      workingDirectory: workingDirectory,
      environment: environment,
    );
  }

  @override
  void echoError(String message) {
    stderr += '$message\n';
  }

  @override
  void echo(String message) {
    stdout += message;
  }

  @override
  Never exitApp(int code) {
    // This is an exception for the benefit of unit tests.
    // The real implementation calls `exit(code)`.
    throw Exception('App exited with code $code');
  }
}
