import APIClient
import ComposableArchitecture
import Foundation
import SnippetPlayerClient

@Reducer
public struct HookSnippetSelectionReducer {
    @ObservableState
    public struct State: Equatable {
        public var duration: TimeInterval
        public var snippetStartTime: TimeInterval
        public let showCancelButton: Bool
        public var selectedSnippetStartTime: TimeInterval?
        public var pendingSnippetStartTime: TimeInterval?

        public init(
            duration: TimeInterval,
            snippetStartTime: TimeInterval,
            showCancelButton: Bool,
            selectedSnippetStartTime: TimeInterval? = nil,
            pendingSnippetStartTime: TimeInterval? = nil
        ) {
            self.duration = max(0, duration)
            self.snippetStartTime = max(0, snippetStartTime)
            self.showCancelButton = showCancelButton
            self.selectedSnippetStartTime = selectedSnippetStartTime.map { max(0, $0) }
            self.pendingSnippetStartTime = pendingSnippetStartTime.map { max(0, $0) }
        }
    }

    public enum Action {
        public enum Delegate {
            case cancelTapped
            case saveTapped
            case snippetStartTimeChanged(TimeInterval)
        }

        case delegate(Delegate)
        case snippetStartTimeChanged(TimeInterval)
        case cancelTapped
        case saveTapped
        case seekToTime(TimeInterval)
    }

    @Dependency(SnippetPlayerClient.self) var playerClient

    public init() {}

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .snippetStartTimeChanged(let newTime):
                let validatedTime = max(0, min(newTime, state.duration))
                state.snippetStartTime = validatedTime
                state.pendingSnippetStartTime = validatedTime
                return .merge(
                    .send(.seekToTime(validatedTime)),
                    .send(.delegate(.snippetStartTimeChanged(validatedTime)))
                )

            case .cancelTapped:
                state.pendingSnippetStartTime = nil
                state.snippetStartTime = state.selectedSnippetStartTime ?? state.snippetStartTime
                return .send(.delegate(.cancelTapped))

            case .saveTapped:
                state.selectedSnippetStartTime = state.pendingSnippetStartTime ?? state.selectedSnippetStartTime
                state.pendingSnippetStartTime = nil
                return .send(.delegate(.saveTapped))

            case .seekToTime(let time):
                playerClient.seekTo(.init(seconds: time, preferredTimescale: 1000))
                return .none

            case .delegate:
                return .none
            }
        }
    }
}
