import ExpoModulesCore
import UIKit

public class ScreenRecordingDetectorIosModule: Module {
  // MARK: - Public API

  public func definition() -> ModuleDefinition {
    Name("ScreenRecordingDetectorIos")
    Events("onScreenRecordingChanged")

    // アプリ起動時に現在の録画状態を通知し、遅延チェックも実行
    OnCreate {
      let initial = UIScreen.main.isCaptured
      self.sendEvent("onScreenRecordingChanged", ["isCaptured": initial])
      self.scheduleDelayedChecks(initialCaptured: initial, attempts: 3, interval: 5.0)
    }

    // リスナー開始時に画面録画状態の変化を監視
    OnStartObserving {
      let nc = NotificationCenter.default

      // 録画開始／停止の通知
      nc.addObserver(
        forName: UIScreen.capturedDidChangeNotification,
        object: nil,
        queue: .main
      ) { [weak self] _ in
        guard let self = self else { return }
        let isCaptured = UIScreen.main.isCaptured
        self.sendEvent("onScreenRecordingChanged", ["isCaptured": isCaptured])
      }

      // アプリがフォアグラウンドに戻ったときにも再チェック
      nc.addObserver(
        forName: UIApplication.didBecomeActiveNotification,
        object: nil,
        queue: .main
      ) { [weak self] _ in
        guard let self = self else { return }
        let isCaptured = UIScreen.main.isCaptured
        self.sendEvent("onScreenRecordingChanged", ["isCaptured": isCaptured])
      }
    }

    // リスナー停止時は通知を解除
    OnStopObserving {
      NotificationCenter.default.removeObserver(self)
    }

    // JS から現在状態を問い合わせられるように
    Function("getCapturedStatus") { () -> Bool in
      UIScreen.main.isCaptured
    }
  }

  // MARK: - Private Helpers

  /// 遅延チェックを繰り返し実行し、初回起動時の状態変化を取りこぼさない
  private func scheduleDelayedChecks(
    initialCaptured: Bool,
    attempts: Int,
    interval: TimeInterval
  ) {
    guard attempts > 0 else { return }
    DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
      let current = UIScreen.main.isCaptured
      if current != initialCaptured {
        self.sendEvent("onScreenRecordingChanged", ["isCaptured": current])
      }
      self.scheduleDelayedChecks(
        initialCaptured: initialCaptured,
        attempts: attempts - 1,
        interval: interval
      )
    }
  }
}
