import SwiftUI

struct WatchInboxView: View {
    var store: WatchInboxStore
    var onAction: ((WatchPromptAction) -> Void)?
    var onExecApprovalDecision: ((String, WatchExecApprovalDecision) -> Void)?
    var onRefreshExecApprovalReview: (() -> Void)?

    var body: some View {
        NavigationStack {
            if self.store.sortedExecApprovals.count == 1,
               let record = self.store.activeExecApproval
            {
                WatchExecApprovalDetailView(
                    store: self.store,
                    record: record,
                    onDecision: self.onExecApprovalDecision)
            } else if !self.store.sortedExecApprovals.isEmpty {
                WatchExecApprovalListView(
                    store: self.store,
                    onDecision: self.onExecApprovalDecision)
            } else if self.store.shouldShowExecApprovalReviewStatus {
                WatchExecApprovalLoadingView(
                    store: self.store,
                    onRetry: self.onRefreshExecApprovalReview)
            } else {
                WatchGenericInboxView(store: self.store, onAction: self.onAction)
            }
        }
    }
}

private struct WatchExecApprovalLoadingView: View {
    var store: WatchInboxStore
    var onRetry: (() -> Void)?

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 10) {
                Text("Exec approval")
                    .font(.headline)

                if self.store.isExecApprovalReviewLoading {
                    ProgressView()
                        .frame(maxWidth: .infinity, alignment: .leading)
                }

                if let statusText = self.store.execApprovalReviewStatusText, !statusText.isEmpty {
                    Text(statusText)
                        .font(.body)
                        .fixedSize(horizontal: false, vertical: true)
                }

                if !self.store.isExecApprovalReviewLoading {
                    Button("Retry") {
                        self.onRetry?()
                    }
                }

                Text("Keep your iPhone nearby and unlocked if review details take a moment to appear.")
                    .font(.footnote)
                    .foregroundStyle(.secondary)
                    .fixedSize(horizontal: false, vertical: true)
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding()
        }
        .navigationTitle("Exec approval")
    }
}

private struct WatchExecApprovalListView: View {
    var store: WatchInboxStore
    var onDecision: ((String, WatchExecApprovalDecision) -> Void)?

    var body: some View {
        List {
            Section("Exec approvals") {
                ForEach(self.store.sortedExecApprovals) { record in
                    NavigationLink {
                        WatchExecApprovalDetailView(
                            store: self.store,
                            record: record,
                            onDecision: self.onDecision)
                    } label: {
                        VStack(alignment: .leading, spacing: 4) {
                            Text(record.approval.commandPreview ?? record.approval.commandText)
                                .font(.headline)
                                .lineLimit(2)
                            Text(self.metadataLine(for: record))
                                .font(.footnote)
                                .foregroundStyle(.secondary)
                                .lineLimit(2)
                            if let statusText = record.statusText, !statusText.isEmpty {
                                Text(statusText)
                                    .font(.footnote)
                                    .foregroundStyle(record.isResolving ? Color.secondary : Color.red)
                                    .lineLimit(2)
                            }
                        }
                    }
                }
            }

            if let outcome = self.store.lastExecApprovalOutcomeText, !outcome.isEmpty {
                Section("Last result") {
                    Text(outcome)
                        .font(.footnote)
                        .foregroundStyle(.secondary)
                }
            }
        }
        .navigationTitle("Approvals")
    }

    private func metadataLine(for record: WatchExecApprovalRecord) -> String {
        var parts: [String] = []
        if let host = record.approval.host, !host.isEmpty {
            parts.append(host)
        }
        if let nodeId = record.approval.nodeId, !nodeId.isEmpty {
            parts.append(nodeId)
        }
        if let expiresText = Self.expiresText(record.approval.expiresAtMs) {
            parts.append(expiresText)
        }
        return parts.isEmpty ? "Pending review" : parts.joined(separator: " · ")
    }

    private static func expiresText(_ expiresAtMs: Int?) -> String? {
        guard let expiresAtMs else { return nil }
        let deltaSeconds = max(0, (expiresAtMs - Int(Date().timeIntervalSince1970 * 1000)) / 1000)
        if deltaSeconds < 60 {
            return "Expires in <1m"
        }
        return "Expires in \(deltaSeconds / 60)m"
    }
}

private struct WatchExecApprovalDetailView: View {
    var store: WatchInboxStore
    let record: WatchExecApprovalRecord
    var onDecision: ((String, WatchExecApprovalDecision) -> Void)?

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 10) {
                Text(self.record.approval.commandText)
                    .font(.headline)
                    .fixedSize(horizontal: false, vertical: true)

                if let host = self.record.approval.host, !host.isEmpty {
                    self.metadataRow(label: "Host", value: host)
                }
                if let nodeId = self.record.approval.nodeId, !nodeId.isEmpty {
                    self.metadataRow(label: "Node", value: nodeId)
                }
                if let agentId = self.record.approval.agentId, !agentId.isEmpty {
                    self.metadataRow(label: "Agent", value: agentId)
                }
                if let expiresText = Self.expiresText(self.record.approval.expiresAtMs) {
                    self.metadataRow(label: "Expires", value: expiresText)
                }
                if let riskText = self.riskText(self.record.approval.risk) {
                    self.metadataRow(label: "Risk", value: riskText)
                }

                if let statusText = self.currentRecord?.statusText, !statusText.isEmpty {
                    Text(statusText)
                        .font(.footnote)
                        .foregroundStyle((self.currentRecord?.isResolving ?? false) ? Color.secondary : Color.red)
                }

                if let currentRecord,
                   currentRecord.approval.allowedDecisions.contains(.allowOnce)
                {
                    Button("Allow Once") {
                        self.onDecision?(currentRecord.id, .allowOnce)
                    }
                    .disabled(currentRecord.isResolving)
                }

                if let currentRecord,
                   currentRecord.approval.allowedDecisions.contains(.deny)
                {
                    Button(role: .destructive) {
                        self.onDecision?(currentRecord.id, .deny)
                    } label: {
                        Text("Deny")
                            .frame(maxWidth: .infinity)
                    }
                    .disabled(currentRecord.isResolving)
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding()
        }
        .navigationTitle("Exec approval")
        .onAppear {
            self.store.selectExecApproval(id: self.record.id)
        }
    }

    private var currentRecord: WatchExecApprovalRecord? {
        self.store.execApprovals.first(where: { $0.id == self.record.id })
    }

    private func metadataRow(label: String, value: String) -> some View {
        VStack(alignment: .leading, spacing: 2) {
            Text(label)
                .font(.caption2)
                .foregroundStyle(.secondary)
            Text(value)
                .font(.footnote)
                .fixedSize(horizontal: false, vertical: true)
        }
    }

    private func riskText(_ risk: WatchRiskLevel?) -> String? {
        switch risk {
        case .high:
            return "High"
        case .medium:
            return "Medium"
        case .low:
            return "Low"
        case nil:
            return nil
        }
    }

    private static func expiresText(_ expiresAtMs: Int?) -> String? {
        guard let expiresAtMs else { return nil }
        let deltaSeconds = max(0, (expiresAtMs - Int(Date().timeIntervalSince1970 * 1000)) / 1000)
        if deltaSeconds < 60 {
            return "<1 minute"
        }
        return "\(deltaSeconds / 60) minutes"
    }
}

private struct WatchGenericInboxView: View {
    var store: WatchInboxStore
    var onAction: ((WatchPromptAction) -> Void)?

    private func role(for action: WatchPromptAction) -> ButtonRole? {
        switch action.style?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() {
        case "destructive":
            return .destructive
        case "cancel":
            return .cancel
        default:
            return nil
        }
    }

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 8) {
                Text(self.store.title)
                    .font(.headline)
                    .lineLimit(2)

                Text(self.store.body)
                    .font(.body)
                    .fixedSize(horizontal: false, vertical: true)

                if let details = self.store.details, !details.isEmpty {
                    Text(details)
                        .font(.footnote)
                        .foregroundStyle(.secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }

                if let outcome = self.store.lastExecApprovalOutcomeText, !outcome.isEmpty {
                    Text(outcome)
                        .font(.footnote)
                        .foregroundStyle(.secondary)
                }

                if !self.store.actions.isEmpty {
                    ForEach(self.store.actions) { action in
                        Button(role: self.role(for: action)) {
                            self.onAction?(action)
                        } label: {
                            Text(action.label)
                                .frame(maxWidth: .infinity)
                        }
                        .disabled(self.store.isReplySending)
                    }
                }

                if let replyStatusText = self.store.replyStatusText, !replyStatusText.isEmpty {
                    Text(replyStatusText)
                        .font(.footnote)
                        .foregroundStyle(.secondary)
                }

                if let updatedAt = self.store.updatedAt {
                    Text("Updated \(updatedAt.formatted(date: .omitted, time: .shortened))")
                        .font(.footnote)
                        .foregroundStyle(.secondary)
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding()
        }
        .navigationTitle("OpenClaw")
    }
}
