// 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/logger.dart';
import 'package:flutter_tools/src/ios/plist_parser.dart';
import 'package:flutter_tools/src/macos/migrations/flutter_application_migration.dart';
import 'package:flutter_tools/src/macos/migrations/macos_deployment_target_migration.dart';
import 'package:flutter_tools/src/macos/migrations/nsapplicationmain_deprecation_migration.dart';
import 'package:flutter_tools/src/macos/migrations/remove_macos_framework_link_and_embedding_migration.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';

import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fakes.dart';

void main() {
  group('remove link and embed migration', () {
    late TestUsage testUsage;
    late FakeAnalytics fakeAnalytics;
    late MemoryFileSystem memoryFileSystem;
    late BufferLogger testLogger;
    late FakeMacOSProject macOSProject;
    late File xcodeProjectInfoFile;

    setUp(() {
      testUsage = TestUsage();
      memoryFileSystem = MemoryFileSystem.test();
      fakeAnalytics = getInitializedFakeAnalyticsInstance(
        fs: memoryFileSystem,
        fakeFlutterVersion: FakeFlutterVersion(),
      );
      xcodeProjectInfoFile = memoryFileSystem.file('project.pbxproj');
      testLogger = BufferLogger.test();
      macOSProject = FakeMacOSProject();
      macOSProject.xcodeProjectInfoFile = xcodeProjectInfoFile;
    });

    testWithoutContext('skipped if files are missing', () async {
      final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration =
          RemoveMacOSFrameworkLinkAndEmbeddingMigration(
        macOSProject,
        testLogger,
        testUsage,
        fakeAnalytics,
      );
      await macosProjectMigration.migrate();
      expect(testUsage.events, isEmpty);
      expect(fakeAnalytics.sentEvents, isEmpty);

      expect(xcodeProjectInfoFile.existsSync(), isFalse);

      expect(
          testLogger.traceText,
          contains(
              'Xcode project not found, skipping framework link and embedding migration'));
      expect(testLogger.statusText, isEmpty);
    });

    testWithoutContext('skipped if nothing to upgrade', () async {
      const String contents = 'Nothing to upgrade';
      xcodeProjectInfoFile.writeAsStringSync(contents);
      final DateTime projectLastModified =
          xcodeProjectInfoFile.lastModifiedSync();

      final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration =
          RemoveMacOSFrameworkLinkAndEmbeddingMigration(
        macOSProject,
        testLogger,
        testUsage,
        fakeAnalytics,
      );
      await macosProjectMigration.migrate();
      expect(testUsage.events, isEmpty);
      expect(fakeAnalytics.sentEvents, isEmpty);

      expect(xcodeProjectInfoFile.lastModifiedSync(), projectLastModified);
      expect(xcodeProjectInfoFile.readAsStringSync(), contents);

      expect(testLogger.statusText, isEmpty);
    });

    testWithoutContext('skips migrating script with embed', () async {
      const String contents = r'''
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
			''';
      xcodeProjectInfoFile.writeAsStringSync(contents);

      final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration =
          RemoveMacOSFrameworkLinkAndEmbeddingMigration(
        macOSProject,
        testLogger,
        testUsage,
        fakeAnalytics,
      );
      await macosProjectMigration.migrate();
      expect(xcodeProjectInfoFile.readAsStringSync(), contents);
      expect(testLogger.statusText, isEmpty);
    });

    testWithoutContext('Xcode project is migrated', () async {
      xcodeProjectInfoFile.writeAsStringSync(r'''
prefix D73912F022F37F9E000D13A0
D73912F222F3801D000D13A0 suffix
D73912EF22F37F9E000D13A0
keep this 1
  33D1A10422148B71006C7A3E spaces
33D1A10522148B93006C7A3E
			shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename\n";
keep this 2
''');

      final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration =
          RemoveMacOSFrameworkLinkAndEmbeddingMigration(
        macOSProject,
        testLogger,
        testUsage,
        fakeAnalytics,
      );
      await macosProjectMigration.migrate();
      expect(testUsage.events, isEmpty);
      expect(fakeAnalytics.sentEvents, isEmpty);

      expect(xcodeProjectInfoFile.readAsStringSync(), r'''
keep this 1
			shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
keep this 2
''');
      expect(testLogger.statusText, contains('Upgrading project.pbxproj'));
    });

    testWithoutContext('migration fails with leftover App.framework reference', () {
      xcodeProjectInfoFile.writeAsStringSync('''
		D73912F022F37F9bogus /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73912F022F37F9bogus /* App.framework */; };
''');

      final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration =
          RemoveMacOSFrameworkLinkAndEmbeddingMigration(
        macOSProject,
        testLogger,
        testUsage,
        fakeAnalytics,
      );

      expect(macosProjectMigration.migrate,
          throwsToolExit(message: 'Your Xcode project requires migration'));
      expect(testUsage.events, contains(
        const TestUsageEvent('macos-migration', 'remove-frameworks', label: 'failure'),
      ));
      expect(fakeAnalytics.sentEvents, contains(
        Event.appleUsageEvent(
            workflow: 'macos-migration',
            parameter: 'remove-frameworks',
            result: 'failure',
          )
      ));
    });

    testWithoutContext(
        'migration fails with leftover FlutterMacOS.framework reference', () {
      xcodeProjectInfoFile.writeAsStringSync('''
				33D1A10522148B93bogus /* FlutterMacOS.framework in Bundle Framework */,
''');

      final RemoveMacOSFrameworkLinkAndEmbeddingMigration macosProjectMigration =
          RemoveMacOSFrameworkLinkAndEmbeddingMigration(
        macOSProject,
        testLogger,
        testUsage,
        fakeAnalytics,
      );
      expect(macosProjectMigration.migrate,
          throwsToolExit(message: 'Your Xcode project requires migration'));
      expect(testUsage.events, contains(
        const TestUsageEvent('macos-migration', 'remove-frameworks', label: 'failure'),
      ));
      expect(fakeAnalytics.sentEvents, contains(
        Event.appleUsageEvent(
            workflow: 'macos-migration',
            parameter: 'remove-frameworks',
            result: 'failure',
          )
      ));
    });
  });

  group('update deployment target version', () {
    late MemoryFileSystem memoryFileSystem;
    late BufferLogger testLogger;
    late FakeMacOSProject project;
    late File xcodeProjectInfoFile;
    late File podfile;

    setUp(() {
      memoryFileSystem = MemoryFileSystem();
      testLogger = BufferLogger.test();
      project = FakeMacOSProject();
      xcodeProjectInfoFile = memoryFileSystem.file('project.pbxproj');
      project.xcodeProjectInfoFile = xcodeProjectInfoFile;

      podfile = memoryFileSystem.file('Podfile');
      project.podfile = podfile;
    });

    testWithoutContext('skipped if files are missing', () async {
      final MacOSDeploymentTargetMigration macOSProjectMigration = MacOSDeploymentTargetMigration(
        project,
        testLogger,
      );
      await macOSProjectMigration.migrate();
      expect(xcodeProjectInfoFile.existsSync(), isFalse);
      expect(podfile.existsSync(), isFalse);

      expect(testLogger.traceText, contains('Xcode project not found, skipping macOS deployment target version migration'));
      expect(testLogger.traceText, contains('Podfile not found, skipping global platform macOS version migration'));
      expect(testLogger.statusText, isEmpty);
    });

    testWithoutContext('skipped if nothing to upgrade', () async {
      const String xcodeProjectInfoFileContents = 'MACOSX_DEPLOYMENT_TARGET = 10.14;';
      xcodeProjectInfoFile.writeAsStringSync(xcodeProjectInfoFileContents);

      final DateTime projectLastModified = xcodeProjectInfoFile.lastModifiedSync();

      const String podfileFileContents = "# platform :osx, '10.14'";
      podfile.writeAsStringSync(podfileFileContents);
      final DateTime podfileLastModified = podfile.lastModifiedSync();

      final MacOSDeploymentTargetMigration macOSProjectMigration = MacOSDeploymentTargetMigration(
        project,
        testLogger,
      );
      await macOSProjectMigration.migrate();

      expect(xcodeProjectInfoFile.lastModifiedSync(), projectLastModified);
      expect(xcodeProjectInfoFile.readAsStringSync(), xcodeProjectInfoFileContents);
      expect(podfile.lastModifiedSync(), podfileLastModified);
      expect(podfile.readAsStringSync(), podfileFileContents);

      expect(testLogger.statusText, isEmpty);
    });

    testWithoutContext('Xcode project is migrated from 10.11 to 10.14', () async {
      xcodeProjectInfoFile.writeAsStringSync('''
 				GCC_WARN_UNUSED_VARIABLE = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.11;
 				MTL_ENABLE_DEBUG_INFO = YES;
''');

      podfile.writeAsStringSync('''
# platform :osx, '10.11'
platform :osx, '10.11'
''');

      final MacOSDeploymentTargetMigration macOSProjectMigration = MacOSDeploymentTargetMigration(
        project,
        testLogger,
      );
      await macOSProjectMigration.migrate();

      expect(xcodeProjectInfoFile.readAsStringSync(), '''
 				GCC_WARN_UNUSED_VARIABLE = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				MTL_ENABLE_DEBUG_INFO = YES;
''');

      expect(podfile.readAsStringSync(), '''
# platform :osx, '10.14'
platform :osx, '10.14'
''');
      // Only print once even though 2 lines were changed.
      expect('Updating minimum macOS deployment target to 10.14'.allMatches(testLogger.statusText).length, 1);
    });

    testWithoutContext('Xcode project is migrated from 10.13 to 10.14', () async {
      xcodeProjectInfoFile.writeAsStringSync('''
 				GCC_WARN_UNUSED_VARIABLE = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.13;
 				MTL_ENABLE_DEBUG_INFO = YES;
''');

      podfile.writeAsStringSync('''
# platform :osx, '10.13'
platform :osx, '10.13'
''');

      final MacOSDeploymentTargetMigration macOSProjectMigration = MacOSDeploymentTargetMigration(
        project,
        testLogger,
      );
      await macOSProjectMigration.migrate();

      expect(xcodeProjectInfoFile.readAsStringSync(), '''
 				GCC_WARN_UNUSED_VARIABLE = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				MTL_ENABLE_DEBUG_INFO = YES;
''');

      expect(podfile.readAsStringSync(), '''
# platform :osx, '10.14'
platform :osx, '10.14'
''');
      // Only print once even though 2 lines were changed.
      expect('Updating minimum macOS deployment target to 10.14'.allMatches(testLogger.statusText).length, 1);
    });
  });

  group('update NSPrincipalClass from FlutterApplication to NSApplication', () {
    late MemoryFileSystem memoryFileSystem;
    late BufferLogger testLogger;
    late FakeMacOSProject project;
    late File infoPlistFile;
    late FakePlistParser fakePlistParser;
    late FlutterProjectFactory flutterProjectFactory;

    setUp(() {
      memoryFileSystem = MemoryFileSystem();
      fakePlistParser = FakePlistParser();
      testLogger = BufferLogger.test();
      project = FakeMacOSProject();
      infoPlistFile = memoryFileSystem.file('Info.plist');
      project.defaultHostInfoPlist = infoPlistFile;
      flutterProjectFactory = FlutterProjectFactory(
        fileSystem: memoryFileSystem,
        logger: testLogger,
      );
    });

    void testWithMocks(String description, Future<void> Function() testMethod) {
      testUsingContext(description, testMethod, overrides: <Type, Generator>{
        FileSystem: () => memoryFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        PlistParser: () => fakePlistParser,
        FlutterProjectFactory: () => flutterProjectFactory,
      });
    }

    testWithMocks('skipped if files are missing', () async {
      final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration(
        project,
        testLogger,
      );
      await macOSProjectMigration.migrate();
      expect(infoPlistFile.existsSync(), isFalse);

      expect(testLogger.traceText, isEmpty);
      expect(testLogger.statusText, isEmpty);
    });

    testWithMocks('skipped if no NSPrincipalClass key exists to upgrade', () async {
      final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration(
        project,
        testLogger,
      );
      infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake.
      await macOSProjectMigration.migrate();
      expect(fakePlistParser.getValueFromFile<String>(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), isNull);
      expect(testLogger.statusText, isEmpty);
    });

    testWithMocks('skipped if already de-upgraded (or never migrated)', () async {
      fakePlistParser.setProperty(PlistParser.kNSPrincipalClassKey, 'NSApplication');
      final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration(
        project,
        testLogger,
      );
      infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake.
      await macOSProjectMigration.migrate();
      expect(fakePlistParser.getValueFromFile<String>(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'NSApplication');
      expect(testLogger.statusText, isEmpty);
    });

    testWithMocks('Info.plist migrated to use NSApplication', () async {
      fakePlistParser.setProperty(PlistParser.kNSPrincipalClassKey, 'FlutterApplication');
      final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration(
        project,
        testLogger,
      );
      infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake.
      await macOSProjectMigration.migrate();
      expect(fakePlistParser.getValueFromFile<String>(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'NSApplication');
      // Only print once.
      expect('Updating ${infoPlistFile.basename} to use NSApplication instead of FlutterApplication.'.allMatches(testLogger.statusText).length, 1);
    });

    testWithMocks('Skip if NSPrincipalClass is not NSApplication', () async {
      const String differentApp = 'DIFFERENTApplication';
      fakePlistParser.setProperty(PlistParser.kNSPrincipalClassKey, differentApp);
      final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration(
        project,
        testLogger,
      );
      infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake.
      await macOSProjectMigration.migrate();
      expect(fakePlistParser.getValueFromFile<String>(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), differentApp);
      expect(testLogger.traceText, isEmpty);
    });
  });

  group('migrate @NSApplicationMain attribute to @main', () {
    late MemoryFileSystem memoryFileSystem;
    late BufferLogger testLogger;
    late FakeMacOSProject project;
    late File appDelegateFile;

    setUp(() {
      memoryFileSystem = MemoryFileSystem();
      testLogger = BufferLogger.test();
      project = FakeMacOSProject();
      appDelegateFile = memoryFileSystem.file('AppDelegate.swift');
      project.appDelegateSwift = appDelegateFile;
    });

    testWithoutContext('skipped if files are missing', () async {
      final NSApplicationMainDeprecationMigration migration = NSApplicationMainDeprecationMigration(
        project,
        testLogger,
      );
      await migration.migrate();
      expect(appDelegateFile.existsSync(), isFalse);

      expect(testLogger.statusText, isEmpty);
    });

    testWithoutContext('skipped if nothing to upgrade', () async {
      const String appDelegateContents = '''
import Cocoa
import FlutterMacOS

@main
class AppDelegate: FlutterAppDelegate {
  override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
    return true
  }
}
''';
      appDelegateFile.writeAsStringSync(appDelegateContents);
      final DateTime lastModified = appDelegateFile.lastModifiedSync();

      final NSApplicationMainDeprecationMigration migration = NSApplicationMainDeprecationMigration(
        project,
        testLogger,
      );
      await migration.migrate();

      expect(appDelegateFile.lastModifiedSync(), lastModified);
      expect(appDelegateFile.readAsStringSync(), appDelegateContents);

      expect(testLogger.statusText, isEmpty);
    });

    testWithoutContext('updates AppDelegate.swift', () async {
      appDelegateFile.writeAsStringSync('''
import Cocoa
import FlutterMacOS

@NSApplicationMain
class AppDelegate: FlutterAppDelegate {
  override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
    return true
  }
}
''');

      final NSApplicationMainDeprecationMigration migration = NSApplicationMainDeprecationMigration(
        project,
        testLogger,
      );
      await migration.migrate();

      expect(appDelegateFile.readAsStringSync(), '''
import Cocoa
import FlutterMacOS

@main
class AppDelegate: FlutterAppDelegate {
  override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
    return true
  }
}
''');
      expect(testLogger.warningText, contains('uses the deprecated @NSApplicationMain attribute, updating'));
    });
  });
}

class FakeMacOSProject extends Fake implements MacOSProject {
  @override
  File xcodeProjectInfoFile = MemoryFileSystem.test().file('xcodeProjectInfoFile');

  @override
  File defaultHostInfoPlist = MemoryFileSystem.test().file('InfoplistFile');

  @override
  File podfile = MemoryFileSystem.test().file('Podfile');

  @override
  File appDelegateSwift = MemoryFileSystem.test().file('AppDelegate.swift');
}
