import 'dart:io';
import 'package:yaml/yaml.dart';

/// 品牌名允许的字符：小写字母、数字、下划线。
final RegExp _validBrandName = RegExp(r'^[a-z][a-z0-9_]*$');

Future<void> main(List<String> args) async {
  if (args.isEmpty) {
    print(
      '\x1B[31m用法：dart run tool/generate_app.dart <品牌名>\x1B[0m',
    );
    print('\x1B[33m示例：dart run tool/generate_app.dart quanxue\x1B[0m');
    exit(1);
  }

  final String brand = args.first;

  if (!_validBrandName.hasMatch(brand)) {
    print(
      '\x1B[31m[错误] 品牌名 "$brand" 格式无效，'
      '仅允许小写字母、数字和下划线（且必须以字母开头）。\x1B[0m',
    );
    exit(1);
  }

  final File configFile = File('flavors/$brand.yaml');

  if (!configFile.existsSync()) {
    print(
      '\x1B[31m[错误] 未找到配置文件：${configFile.path}\x1B[0m',
    );
    exit(1);
  }

  print('\x1B[34m[信息] 正在为品牌生成应用：$brand...\x1B[0m');

  // 1. 解析 YAML 配置
  final String yamlString = await configFile.readAsString();
  final YamlMap config = loadYaml(yamlString) as YamlMap;

  final String appName = config['app_name'] as String;
  final String applicationId = config['application_id'] as String;
  final String appKey = config['app_key'] as String;

  final YamlMap theme = config['theme'] as YamlMap;
  final String accentColor = theme['accent_color'] as String;
  final String bgColor = theme['bg_color'] as String;
  final String textColor = theme['text_color'] as String;
  final String mutedTextColor = theme['muted_text_color'] as String;

  final String appDir = 'apps/$brand';

  print('\x1B[32m✔ 配置加载完成。\x1B[0m');

  // 2. 创建 Flutter 应用
  await _createFlutterApp(brand, appDir, applicationId);

  // 3. 添加核心依赖
  await _addCoreDependency(appDir);

  // 4. 覆盖 MainActivity.java 以继承 CoreShellActivity
  await _overwriteMainActivity(appDir, applicationId);

  // 5. 覆盖 AndroidManifest.xml 中的应用名称
  await _overwriteManifestLabel(appDir, appName);

  // 6. 生成 lib/main.dart
  await _generateDartEntrypoint(
    appDir,
    appName,
    appKey,
    accentColor,
    bgColor,
    textColor,
    mutedTextColor,
  );

  // 7. 生成图标与启动页配置
  await _generateBrandingAssets(brand, appDir, config);

  print('\x1B[32m✔ 应用 $brand 已生成到 $appDir！\x1B[0m');
  print('\x1B[34m构建应用请执行：\x1B[0m');
  print('  cd $appDir && flutter build apk');
}

Future<void> _createFlutterApp(
  String brand,
  String appDir,
  String applicationId,
) async {
  print('\x1B[34m[信息] 正在执行 flutter create...\x1B[0m');
  final Directory dir = Directory(appDir);
  if (dir.existsSync()) {
    print(
      '\x1B[33m[警告] 目录 $appDir 已存在，正在清理...\x1B[0m',
    );
    dir.deleteSync(recursive: true);
  }

  // 提取组织名
  // 例如：com.wanmake.quanxue -> org: com.wanmake
  final List<String> segments = applicationId.split('.');
  final String org = segments.sublist(0, segments.length - 1).join('.');

  final ProcessResult result = await Process.run('flutter', [
    'create',
    '--org',
    org,
    '--project-name',
    brand.replaceAll('-', '_'),
    '--platforms',
    'android',
    '--android-language',
    'java',
    appDir,
  ]);

  if (result.exitCode != 0) {
    print('\x1B[31m[错误] flutter create 执行失败：\n${result.stderr}\x1B[0m');
    exit(1);
  }
}

Future<void> _addCoreDependency(String appDir) async {
  print('\x1B[34m[信息] 正在添加 web_shell_core 依赖...\x1B[0m');
  final ProcessResult result = await Process.run('flutter', [
    'pub',
    'add',
    'web_shell_core',
    '--path',
    '../../packages/web_shell_core',
  ], workingDirectory: appDir);

  if (result.exitCode != 0) {
    print(
      '\x1B[31m[错误] 添加依赖失败：\n${result.stderr}\x1B[0m',
    );
    exit(1);
  }
}

Future<void> _overwriteMainActivity(String appDir, String applicationId) async {
  print('\x1B[34m[信息] 正在注入 CoreShellActivity 继承关系...\x1B[0m');
  final String mainActivityPath =
      "$appDir/android/app/src/main/java/${applicationId.replaceAll('.', '/')}/MainActivity.java";

  // 准备 Java 文件内容
  final String javaContent =
      '''
package $applicationId;

import com.yuanxuan.webshell.core.web_shell_core.CoreShellActivity;

public class MainActivity extends CoreShellActivity {
}
''';

  await File(mainActivityPath).create(recursive: true);
  await File(mainActivityPath).writeAsString(javaContent);
}

Future<void> _overwriteManifestLabel(String appDir, String appName) async {
  print('\x1B[34m[信息] 正在更新 AndroidManifest.xml 应用名...\x1B[0m');
  final File manifestFile = File(
    '$appDir/android/app/src/main/AndroidManifest.xml',
  );
  String content = await manifestFile.readAsString();

  // 使用简单正则替换 android:label="..."
  content = content.replaceAll(
    RegExp(r'android:label="[^"]*"'),
    'android:label="$appName"',
  );

  await manifestFile.writeAsString(content);
}

Future<void> _generateDartEntrypoint(
  String appDir,
  String appName,
  String appKey,
  String accentColor,
  String bgColor,
  String textColor,
  String mutedTextColor,
) async {
  print('\x1B[34m[信息] 正在生成 lib/main.dart...\x1B[0m');
  final File mainFile = File('$appDir/lib/main.dart');

  final String dartContent =
      '''
import 'package:flutter/material.dart';
import 'package:web_shell_core/web_shell_core.dart';

void main() {
  runShellApp(
    ShellEnvironment(
      appName: '$appName',
      appKey: '$appKey',
      accentColor: const Color($accentColor),
      backgroundColor: const Color($bgColor),
      textColor: const Color($textColor),
      mutedTextColor: const Color($mutedTextColor),
    ),
  );
}
''';

  await mainFile.writeAsString(dartContent);

  // 清理 flutter create 默认生成的测试文件（因为它依赖已删除的 MyApp 类）
  final File defaultTestFile = File('$appDir/test/widget_test.dart');
  if (defaultTestFile.existsSync()) {
    await defaultTestFile.delete();
  }
}

Future<void> _generateBrandingAssets(
  String brand,
  String appDir,
  YamlMap config,
) async {
  print('\x1B[34m[信息] 正在配置图标与启动页...\x1B[0m');
  if (config['branding'] == null) {
    print(
      '\x1B[33m[警告] 配置中未找到 branding 段，跳过资源生成。\x1B[0m',
    );
    return;
  }
  final YamlMap branding = config['branding'] as YamlMap;

  // ── 1. 复制品牌资源到生成的应用目录 ──
  final Directory brandSourceDir = Directory('flavors/$brand');
  final Directory brandTargetDir = Directory('$appDir/assets/branding');
  if (!brandSourceDir.existsSync()) {
    print(
      '\x1B[31m[错误] 品牌资源目录不存在：${brandSourceDir.path}\x1B[0m',
    );
    print(
      '\x1B[33m请在 flavors/$brand/ 目录下放置 icon.png、'
      'icon_foreground.png、splash.png 等资源文件。\x1B[0m',
    );
    exit(1);
  }

  await brandTargetDir.create(recursive: true);
  for (final entity in brandSourceDir.listSync(recursive: true)) {
    if (entity is File) {
      final relativePath = entity.path.substring(
        brandSourceDir.path.length + 1,
      );
      final targetFile = File('${brandTargetDir.path}/$relativePath');
      await targetFile.parent.create(recursive: true);
      await entity.copy(targetFile.path);
    }
  }
  print('\x1B[32m✔ 品牌资源已复制到 ${brandTargetDir.path}\x1B[0m');

  // ── 2. 添加资源生成器的 dev 依赖 ──
  print('\x1B[34m[信息] 正在添加资源生成器依赖...\x1B[0m');
  final ProcessResult addDevDepsResult = await Process.run('flutter', [
    'pub',
    'add',
    '--dev',
    'flutter_launcher_icons',
    'flutter_native_splash',
  ], workingDirectory: appDir);

  if (addDevDepsResult.exitCode != 0) {
    print(
      '\x1B[31m[错误] 添加资源生成器依赖失败：'
      '\n${addDevDepsResult.stderr}\x1B[0m',
    );
    exit(1);
  }

  // ── 3. 生成 flutter_launcher_icons 配置 ──
  // 资源路径指向复制后的位置（相对于 appDir）
  final String iconPath = 'assets/branding/${branding['icon']}';
  final String iconForeground = 'assets/branding/${branding['icon_foreground']}';
  final String iconBackground = branding['icon_background'] as String;

  final String iconsYaml = '''
flutter_launcher_icons:
  android: true
  image_path: "$iconPath"
  adaptive_icon_background: "$iconBackground"
  adaptive_icon_foreground: "$iconForeground"
''';
  await File('$appDir/flutter_launcher_icons.yaml').writeAsString(iconsYaml);

  // ── 4. 生成 flutter_native_splash 配置 ──
  final String splashPath = 'assets/branding/${branding['splash']}';
  final String splashColor = branding['splash_color'] as String;

  final String splashYaml = '''
flutter_native_splash:
  color: "$splashColor"
  image: "$splashPath"
  android_12:
    image: "$splashPath"
    icon_background_color: "$splashColor"
''';
  await File('$appDir/flutter_native_splash.yaml').writeAsString(splashYaml);

  // ── 5. 执行资源生成器 ──
  print('\x1B[34m[信息] 正在生成应用图标...\x1B[0m');
  final ProcessResult iconsResult = await Process.run('dart', [
    'run',
    'flutter_launcher_icons',
    '-f',
    'flutter_launcher_icons.yaml',
  ], workingDirectory: appDir);

  if (iconsResult.exitCode != 0) {
    print(
      '\x1B[31m[错误] 图标生成失败：\n${iconsResult.stderr}\x1B[0m',
    );
    print('\x1B[33mstdout:\n${iconsResult.stdout}\x1B[0m');
    exit(1);
  }
  print('\x1B[32m✔ 应用图标已生成。\x1B[0m');

  print('\x1B[34m[信息] 正在生成启动页...\x1B[0m');
  final ProcessResult splashResult = await Process.run('dart', [
    'run',
    'flutter_native_splash:create',
    '--path=flutter_native_splash.yaml',
  ], workingDirectory: appDir);

  if (splashResult.exitCode != 0) {
    print(
      '\x1B[31m[错误] 启动页生成失败：\n${splashResult.stderr}\x1B[0m',
    );
    print('\x1B[33mstdout:\n${splashResult.stdout}\x1B[0m');
    exit(1);
  }
  print('\x1B[32m✔ 启动页已生成。\x1B[0m');
}
