import AppIntents
import NucleicProtocol

// MARK: - Open a session (deep-link intent, §4.4)

/// Open a specific session in the app. Reuses the existing `nucleic://session/<id>` route via
/// `RemoteStore.route(to:)` — so a Spotlight result, a Siri phrase, or a Shortcut jumps straight
/// into the waiting session. `openAppWhenRun` foregrounds the app (this is a navigation action).
struct OpenSessionIntent: AppIntent {
    static let title: LocalizedStringResource = "Open Session"
    static let description = IntentDescription("Open a Nucleic agent session.")
    static let openAppWhenRun = true

    @Parameter(title: "Session")
    var session: SessionEntity

    init() {}
    init(session: SessionEntity) { self.session = session }

    @MainActor
    func perform() async throws -> some IntentResult {
        RemoteStore.shared.route(to: SessionID(rawValue: session.id))
        return .result()
    }

    static var parameterSummary: some ParameterSummary {
        Summary("Open \(\.$session)")
    }
}

// MARK: - Unblock with a follow-up (§4.2, approve-scope)

/// Send a follow-up prompt to a paused agent — the "type the next step to unblock it" flow that
/// stays at `approve` scope (docs/UX_IOS §2). Runs in the background over the app's live channel
/// (no foregrounding); if the Mac isn't reachable it fails clean with a spoken error (§3.1).
struct SendFollowUpIntent: AppIntent {
    static let title: LocalizedStringResource = "Send Follow-Up"
    static let description = IntentDescription(
        "Send a follow-up prompt to a Nucleic agent to unblock or steer it.")

    @Parameter(title: "Session")
    var session: SessionEntity

    @Parameter(title: "Message", requestValueDialog: "What should the agent do next?")
    var text: String

    init() {}
    init(session: SessionEntity, text: String) {
        self.session = session
        self.text = text
    }

    @MainActor
    func perform() async throws -> some IntentResult & ProvidesDialog {
        let store = RemoteStore.shared
        guard store.isPaired else { throw IntentError.notPaired }
        let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty else { return .result(dialog: "That message was empty.") }
        guard await store.awaitLiveConnection() else { throw IntentError.macUnreachable }
        store.sendInput(trimmed, to: SessionID(rawValue: session.id))
        return .result(dialog: "Sent to \(session.title).")
    }

    static var parameterSummary: some ParameterSummary {
        Summary("Tell \(\.$session) to \(\.$text)")
    }
}

// MARK: - "What needs me?" (§4.3)

/// List the agents waiting on the user — for approval, or a next prompt — using the same attention
/// rule as the badge and NEEDS YOU section (`SessionStatus.needsYou`). Answers Siri's "what needs me
/// in Nucleic?" and feeds Shortcuts automations. Runs in the background; returns the list plus a
/// spoken summary.
struct SessionsNeedingMeIntent: AppIntent {
    static let title: LocalizedStringResource = "Sessions Needing Me"
    static let description = IntentDescription(
        "List the Nucleic agents waiting on you — for approval or your next prompt.")

    @MainActor
    func perform() async throws -> some IntentResult & ReturnsValue<[SessionEntity]> & ProvidesDialog {
        let store = RemoteStore.shared
        guard store.isPaired else { throw IntentError.notPaired }
        store.bootstrapForIntent()
        // Give a cold process a brief moment to bring a channel up so the answer is current; fall
        // back to the persisted list if the Mac stays unreachable.
        _ = await store.awaitLiveConnection(timeout: 4)
        let needy = store.liveSessions
            .filter { $0.status.needsYou($0.disposition) }
            .sorted(by: StatusStyle.attentionThenRecency)
            .map(SessionEntity.init)

        let dialog: IntentDialog
        switch needy.count {
        case 0: dialog = "Nothing needs you right now."
        case 1: dialog = "One agent needs you: \(needy[0].title)."
        default: dialog = "\(needy.count) agents need you."
        }
        return .result(value: needy, dialog: dialog)
    }
}
