# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
#     https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
#     https://docs.fastlane.tools/plugins/available-plugins
#

# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane

default_platform(:android)

  platform :android do
  MIN_SCREENSHOT_FILE_SIZE_BYTES = 10_000 # 10KB

  # ==============================================================================
  # Android Platform
  # ==============================================================================
  lane :test do
    Dir.chdir("../src/android") do
      sh("../../gradlew", "test")
    end
  end

  desc "Build a new version for internal testing"
  lane :build_internal do
    UI.important("🔍 Validating build configuration...")

    # Validate environment variables
    validate_signing_config({})

    # Check if Flutter-generated AAB exists
    aab_path = File.expand_path('../src/build/app/outputs/bundle/release/app-release.aab', __dir__)
    unless File.exist?(aab_path)
      UI.error("❌ Flutter-generated AAB not found at: #{aab_path}")
      UI.error("Please ensure 'flutter build appbundle --release' was executed successfully")
      raise "AAB file not found"
    end

    UI.success("✅ Flutter-generated AAB found: #{aab_path}")

    # Get AAB file size for validation
    aab_size = File.size(aab_path)
    UI.important("📦 AAB file size: #{format_bytes(aab_size)}")

    if aab_size < 1_000_000 # Less than 1MB is suspicious
      UI.error("⚠️ AAB file size seems too small (#{format_bytes(aab_size)}), please verify the build")
    end

    UI.success("✅ Build validation completed successfully")
  end

  desc "Deploy a new version to the Google Play internal testing track"
  lane :deploy_internal do
    build_internal

    metadata_opts = metadata_options

    upload_to_play_store(
      track: 'internal',
      aab: File.expand_path('../src/build/app/outputs/bundle/release/app-release.aab', __dir__),
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      release_status: 'completed',
      changes_not_sent_for_review: true,
      **metadata_opts
    )
  end

  desc "Deploy a new version to the Google Play alpha track"
  lane :deploy_alpha do
    build_internal

    metadata_opts = metadata_options

    upload_to_play_store(
      track: 'alpha',
      aab: File.expand_path('../src/build/app/outputs/bundle/release/app-release.aab', __dir__),
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      release_status: 'completed',
      changes_not_sent_for_review: true,
      **metadata_opts
    )
  end

  desc "Deploy a new version to the Google Play beta track"
  lane :deploy_beta do
    build_internal

    metadata_opts = metadata_options

    upload_to_play_store(
      track: 'beta',
      aab: File.expand_path('../src/build/app/outputs/bundle/release/app-release.aab', __dir__),
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      release_status: 'completed',
      changes_not_sent_for_review: true,
      **metadata_opts
    )
  end

  desc "Deploy a new version to the Google Play production track"
  lane :deploy_production do
    build_internal

    metadata_opts = metadata_options

    upload_to_play_store(
      track: 'production',
      aab: File.expand_path('../src/build/app/outputs/bundle/release/app-release.aab', __dir__),
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      release_status: 'completed',
      rollout: '0.1', # Start with 10% rollout for production
      changes_not_sent_for_review: true,
      **metadata_opts
    )
  end

  desc "Deploy a new version to the Google Play production track with full rollout"
  lane :deploy_production_full do
    build_internal

    metadata_opts = metadata_options

    upload_to_play_store(
      track: 'production',
      aab: File.expand_path('../src/build/app/outputs/bundle/release/app-release.aab', __dir__),
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      release_status: 'completed',
      rollout: '1.0', # Full rollout
      changes_not_sent_for_review: true,
      **metadata_opts
    )
  end

  desc "Update metadata for Google Play Store"
  lane :update_metadata do
    metadata_opts = metadata_options(require_metadata: true)

    upload_to_play_store(
      track: 'production',
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_aab: true,
      skip_upload_images: false,
      skip_upload_screenshots: false,
      changes_not_sent_for_review: true,
      **metadata_opts
    )
  end

  desc "Promote from internal to alpha track"
  lane :promote_to_alpha do
    upload_to_play_store(
      track: 'alpha',
      track_promote_to: 'internal',
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_aab: true,
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      release_status: 'completed',
      changes_not_sent_for_review: true
    )
  end

  desc "Promote from internal to beta track"
  lane :promote_to_beta do
    upload_to_play_store(
      track: 'beta',
      track_promote_to: 'internal',
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_aab: true,
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      release_status: 'completed',
      changes_not_sent_for_review: true
    )
  end

  desc "Promote from beta to production track"
  lane :promote_to_production do
    upload_to_play_store(
      track: 'production',
      track_promote_to: 'beta',
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_aab: true,
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      release_status: 'completed',
      rollout: '0.1', # Start with 10% rollout
      changes_not_sent_for_review: true
    )
  end

  desc "Increase production rollout percentage"
  lane :increase_rollout do
    # Get current rollout status
    current_rollout = get_current_rollout_percentage
    
    # Calculate next rollout step
    next_rollout = calculate_next_rollout(current_rollout)
    
    upload_to_play_store(
      track: 'production',
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_aab: true,
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      rollout: next_rollout.to_s,
      release_status: 'completed',
      changes_not_sent_for_review: true
    )
    
    UI.message("Rollout increased from #{current_rollout * 100}% to #{next_rollout * 100}%")
  end

  desc "Halt production rollout"
  lane :halt_rollout do
    upload_to_play_store(
      track: 'production',
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_aab: true,
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      rollout: '0.0',
      release_status: 'halted',
      changes_not_sent_for_review: true
    )
  end

  desc "Resume production rollout"
  lane :resume_rollout do
    upload_to_play_store(
      track: 'production',
      json_key: ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"],
      skip_upload_apk: true,
      skip_upload_aab: true,
      skip_upload_metadata: true,
      skip_upload_images: true,
      skip_upload_screenshots: true,
      release_status: 'completed',
      changes_not_sent_for_review: true
    )
  end

  # ==============================================================================
  # Screenshot Automation
  # ==============================================================================

  desc "Capture Android screenshots using Flutter integration tests"
  lane :android_screenshots do
    capture_android_screenshots
  end

  desc "Capture Android screenshots for specified locales"
  lane :capture_android_screenshots do |options|
    UI.important("📸 Starting Android screenshot capture...")

    # Load configuration
    config = load_screenshot_config

    # Get locales to process
    locales = options[:locales] ? options[:locales].split(',') : config['locales'].map { |l| l['android'] }

    UI.message("🌍 Target locales: #{locales.join(', ')}")

    # Ensure emulator is running and get device ID
    device_id = validate_android_emulator

    locales.each do |locale|
      capture_android_screenshots_for_locale(locale: locale, config: config, device_id: device_id)
    end

    UI.success("✅ Android screenshot capture completed!")
  end

  private_lane :capture_android_screenshots_for_locale do |options|
    locale = options[:locale]
    config = options[:config]
    device_id = options[:device_id] || 'emulator-5554'

    UI.message("📱 Capturing Android screenshots for locale: #{locale} using device: #{device_id}")

    flutter_locale = get_flutter_locale(android_locale: locale, config: config)
    output_dir = File.expand_path("../metadata/android/#{locale}/images/phoneScreenshots", __dir__)

    # Ensure output directory exists
    FileUtils.mkdir_p(output_dir) unless Dir.exist?(output_dir)

    # Run Flutter integration test with screenshot capture
    Dir.chdir("../src") do
      # Set device locale if possible
      begin
        sh("adb", "shell", "settings", "put", "system", "system_locales", locale.gsub('-', '_'))
      rescue StandardError => e
        UI.message("⚠️ Could not set device locale: #{e.message}")
      end

      # Run the integration test
      sh(
        "fvm", "flutter", "drive",
        "--driver=test/integration/screenshot_grabbing/test_driver.dart",
        "--target=test/integration/screenshot_grabbing/screenshot_capture.dart",
        "--dart-define=DEMO_MODE=true",
        "--dart-define=SCREENSHOT_LOCALE=#{flutter_locale}",
        "--dart-define=SCREENSHOT_OUTPUT_DIR=#{output_dir}",
        "-d", device_id,
        "--no-pub"
      )
    end

    UI.message("📁 Screenshots saved to: #{output_dir}")
  end

  private_lane :validate_android_emulator do
    UI.message("🔍 Checking for Android emulator...")

    devices_output = `adb devices`.split("\n")
    devices = devices_output.select { |line| line.include?("emulator") && line.include?("device") }
    devices = devices.map { |line| line.split("\t").first }

    if devices.empty?
      UI.user_error!("❌ No Android emulator found. Please start an emulator first.")
    end

    device_id = devices.first
    UI.success("✅ Android emulator found: #{device_id}")
    device_id # Return the device ID for use in capture lane
  end

  # Error handling
  error do |lane, exception|
    UI.error("❌ Lane #{lane} failed with exception: #{exception}")
    UI.error("📍 Backtrace: #{exception.backtrace.join("\n")}")

    # Provide helpful troubleshooting information
    case lane
    when :deploy_internal, :build_internal
      UI.important("🔧 Troubleshooting tips for build failures:")
      UI.important("1. Verify Flutter build completed successfully")
      UI.important("2. Check signing configuration in key.properties")
      UI.important("3. Ensure keystore file exists and is accessible")
      UI.important("4. Verify environment variables are set correctly")
    else
      UI.important("🔧 Check Fastlane configuration and Google Play credentials")
    end
  end

  private_lane :extract_changelog do
    # Get version from pubspec.yaml
    pubspec_path = File.join(Dir.pwd, '..', 'src', 'pubspec.yaml')
    version_line = File.readlines(pubspec_path).find { |line| line.match(/^version:/) }
    version = version_line.split(' ')[1].strip
    
    # Extract version number (without build number)
    version_number = version.split('+')[0]
    
    # Look for changelog in metadata directory
    changelog_path = File.join(Dir.pwd, 'metadata', 'android', 'en-US', 'changelogs', "#{version_number}.txt")
    
    if File.exist?(changelog_path)
      File.read(changelog_path).strip
    else
      # Fallback to generic changelog
      "Bug fixes and performance improvements for version #{version_number}"
    end
  end

  def self.metadata_options(require_metadata: false)
    metadata_dir = File.expand_path('../metadata/android', __dir__)

    if Dir.exist?(metadata_dir)
      UI.message("📄 Metadata directory detected at #{metadata_dir}")
      {
        skip_upload_metadata: false,
        metadata_path: metadata_dir
      }
    elsif require_metadata
      UI.user_error!("Metadata directory not found at #{metadata_dir}. Provide Google Play Store metadata or create the directory before running this lane.")
    else
      UI.important("ℹ️ Metadata directory not found at #{metadata_dir}, skipping metadata upload")
      {
        skip_upload_metadata: true
      }
    end
  end

  private_lane :get_current_rollout_percentage do
    # This would require additional API calls to get current rollout status
    # For now, return a default value
    0.1
  end

  private_lane :calculate_next_rollout do |current_rollout|
    case current_rollout
    when 0.1
      0.2
    when 0.2
      0.5
    when 0.5
      1.0
    else
      1.0
    end
  end

  # Validate signing configuration
  private_lane :validate_signing_config do
    UI.important("🔐 Validating signing configuration...")

    required_vars = %w[KEYSTORE_FILE_PATH KEYSTORE_PASSWORD KEY_ALIAS KEY_PASSWORD GOOGLE_PLAY_SERVICE_ACCOUNT_KEY]
    missing_vars = required_vars.select { |var| ENV[var].nil? || ENV[var].empty? }

    unless missing_vars.empty?
      UI.error("❌ Missing required environment variables: #{missing_vars.join(', ')}")
      raise "Missing signing configuration"
    end

    # Validate keystore file exists
    keystore_path = ENV["KEYSTORE_FILE_PATH"]
    unless File.exist?(keystore_path)
      UI.error("❌ Keystore file not found: #{keystore_path}")
      raise "Keystore file not found"
    end

    # Validate Google Play service account file exists
    service_account_path = ENV["GOOGLE_PLAY_SERVICE_ACCOUNT_KEY"]
    unless File.exist?(service_account_path)
      UI.error("❌ Google Play service account file not found: #{service_account_path}")
      raise "Service account file not found"
    end

    # Validate keystore file size (should be more than a few KB)
    keystore_size = File.size(keystore_path)
    if keystore_size < 1024
      UI.error("⚠️ Keystore file seems too small: #{format_bytes(keystore_size)}")
    end

    UI.success("✅ Signing configuration validated successfully")
    UI.important("📁 Keystore: #{keystore_path} (#{format_bytes(keystore_size)})")
    UI.important("🔑 Key Alias: #{ENV["KEY_ALIAS"]}")
    UI.important("📄 Service Account: #{service_account_path}")
  end



  # Validate AAB file integrity
  private_lane :validate_aab_file do |aab_path|
    UI.important("🔍 Validating AAB file integrity...")

    unless File.exist?(aab_path)
      UI.error("❌ AAB file not found: #{aab_path}")
      raise "AAB file not found"
    end

    # Check file size
    file_size = File.size(aab_path)
    UI.important("📦 AAB file size: #{format_bytes(file_size)}")

    if file_size < 1_000_000 # Less than 1MB
      UI.error("⚠️ AAB file size seems too small: #{format_bytes(file_size)}")
      raise "AAB file too small"
    end

    if file_size > 200_000_000 # More than 200MB
      UI.error("⚠️ AAB file size seems too large: #{format_bytes(file_size)}")
      raise "AAB file too large"
    end

    # Check file extension
    unless aab_path.end_with?('.aab')
      UI.error("❌ Invalid file extension. Expected .aab file")
      raise "Invalid file extension"
    end

    UI.success("✅ AAB file validation passed")
  end
end

# ==============================================================================
# iOS Platform
# ==============================================================================
platform :ios do
  desc "Capture iOS screenshots using Flutter integration tests"
  lane :ios_screenshots do
    capture_ios_screenshots
  end

  desc "Capture iOS screenshots for specified locales"
  lane :capture_ios_screenshots do |options|
    UI.important("📸 Starting iOS screenshot capture...")
    build_ios_app
    run_ios_screenshots
  end

  private_lane :build_ios_app do
     # iOS build is often handled by specific actions or pre-built app for simulator
     # For this setup regarding integration tests on simulator:
     sh("fvm flutter build ios --simulator --debug --flavor production")
  end

  private_lane :run_ios_screenshots do
     # Ensure a simulator is booted
     device_name = `xcrun simctl list devices | grep '(Booted)' | grep -v 'Watch' | grep -v 'TV' | awk -F ' (' '{print $1}' | xargs`.strip
     if device_name.empty?
       UI.user_error!("No iOS simulator booted. Please start a simulator first.")
     end
     UI.message("Using iOS simulator: #{device_name}")

     Dir.chdir("../src") do
       screenshot_config = YAML.load_file("../fastlane/screenshot_config.yaml")
       output_dir = File.expand_path("../fastlane/metadata/ios", __dir__)
       
       screenshot_config['locales'].each do |locale_entry|
         locale = locale_entry['ios']
         flutter_locale = locale_entry['flutter']
         UI.message("Generating iOS screenshots for locale: #{locale}")

         # Run integration test
         sh(
            "fvm", "flutter", "drive",
            "--driver=test/integration/screenshot_grabbing/test_driver.dart",
            "--target=test/integration/screenshot_grabbing/screenshot_capture.dart",
            "--dart-define=DEMO_MODE=true",
            "--dart-define=SCREENSHOT_LOCALE=#{flutter_locale}",
            "--dart-define=SCREENSHOT_OUTPUT_DIR=#{output_dir}/#{locale}",
            "-d", device_name,
            "--no-pub"
         )
       end
     end
  end
end

# ==============================================================================
# Cross-Platform Screenshot Lanes
# ==============================================================================
desc "Capture screenshots for all platforms and locales"
lane :screenshots do |options|
  platform = options[:platform]
  
  if platform.nil? || platform == 'android'
    android_screenshots(options)
  end
  
  if platform.nil? || platform == 'ios'
    ios_screenshots(options)
  end
  
  validate_screenshots
  
  UI.success("🎉 Screenshot capture completed!")
end

desc "Validate captured screenshots for quality and completeness"
lane :validate_screenshots do
  UI.important("🔍 Validating screenshots...")

  config = load_screenshot_config
  issues = []

  # Check Android screenshots
  android_metadata = File.expand_path('../metadata/android', __dir__)
  config['locales'].each do |locale_config|
    android_locale = locale_config['android']
    screenshot_dir = File.join(android_metadata, android_locale, 'images', 'phoneScreenshots')

    if Dir.exist?(screenshot_dir)
      expected_count = config['scenarios'].length
      actual_files = Dir.glob(File.join(screenshot_dir, '*.png'))
      actual_count = actual_files.length

      if actual_count < expected_count
        issues << "#{android_locale}: Missing screenshots (#{actual_count}/#{expected_count})"
      end

      # Check file sizes
      actual_files.each do |file|
        size = File.size(file)
        if size < MIN_SCREENSHOT_FILE_SIZE_BYTES # Less than 10KB is suspicious
          issues << "#{android_locale}: #{File.basename(file)} seems too small (#{format_bytes(size)})"
        end
      end
    else
      issues << "#{android_locale}: Screenshot directory not found"
    end
  end

  if issues.empty?
    UI.success("✅ All screenshots validated successfully!")
  else
    UI.important("⚠️ Screenshot validation issues found:")
    issues.each { |issue| UI.message("  - #{issue}") }
  end

  # Generate validation report
  generate_screenshot_report(issues: issues)
end



# ==============================================================================
# Helper Methods
# ==============================================================================

# Load screenshot configuration from YAML
def load_screenshot_config
  require 'yaml'
  config_path = File.expand_path('screenshot_config.yaml', __dir__)

  unless File.exist?(config_path)
    UI.user_error!("Screenshot config not found at: #{config_path}")
  end

  YAML.load_file(config_path)
end

# Format bytes for human readable output
def format_bytes(bytes)
  units = ['B', 'KB', 'MB', 'GB']
  size = bytes.to_f
  unit_index = 0

  while size >= 1024 && unit_index < units.length - 1
    size /= 1024
    unit_index += 1
  end

  "#{size.round(2)} #{units[unit_index]}"
end

# Get Flutter locale from Android/iOS locale code
def get_flutter_locale(android_locale: nil, ios_locale: nil, config:)
  config['locales'].each do |locale_config|
    if android_locale && locale_config['android'] == android_locale
      return locale_config['flutter']
    end
    if ios_locale && locale_config['ios'] == ios_locale
      return locale_config['flutter']
    end
  end
  'en' # Default fallback
end



# Generate screenshot validation report
def generate_screenshot_report(issues:)
  report_path = File.expand_path('../metadata/screenshot_report.md', __dir__)

  report_content = <<~REPORT
    # Screenshot Validation Report
    Generated: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}

    ## Summary
    - Total issues: #{issues.length}

    ## Issues
    #{issues.empty? ? 'No issues found!' : issues.map { |i| "- #{i}" }.join("\n")}
  REPORT

  File.write(report_path, report_content)
  UI.message("📄 Report generated: #{report_path}")
end