import SFSafeSymbols
import SwiftUI

/// Consent prompts for device history, presented as sheets like the receiver
/// approval modal.
///
/// Both are dismissable by answering only. An incoming offer in particular must
/// not be acceptable by accident, and a swipe-away would leave the sender
/// waiting on a decision that never comes.
struct ContactPromptHost: View {
	/// Driven by the host so a prompt is never presented while another sheet is
	/// still animating out — macOS silently drops the second one.
	@Binding var isPresented: Bool
	let state: ContactsState
	let onPairingResponse: (String, Bool) -> Void
	let onOfferResponse: (String, Bool) -> Void
	let onSuggestionResponse: (PairingSuggestion, Bool) -> Void

	var body: some View {
		Color.clear
			.sheet(isPresented: $isPresented) {
				// Ordered by who is waiting: a sender is blocked on an offer, a
				// pairing request keeps until its consent window lapses, and a
				// post-transfer suggestion has nobody waiting at all.
				if let offer = state.currentOffer {
					OfferSheet(
						offer: offer,
						busy: state.busyOfferIds.contains(offer.offerId),
						onRespond: onOfferResponse
					)
					.interactiveDismissDisabled(true)
					.modifier(ContactPromptDetents())
				} else if let pairing = state.currentPairing {
					PairingSheet(
						pairing: pairing,
						busy: state.busyEndpoints.contains(pairing.endpointId),
						onRespond: onPairingResponse
					)
					.interactiveDismissDisabled(true)
					.modifier(ContactPromptDetents())
				} else if let suggestion = state.currentSuggestion {
					// Lowest priority: nobody is waiting on this answer, it just
					// follows a transfer that already finished.
					SuggestionSheet(
						suggestion: suggestion,
						busy: state.busyEndpoints.contains(suggestion.endpointId),
						onRespond: onSuggestionResponse
					)
					.interactiveDismissDisabled(true)
					.modifier(ContactPromptDetents())
				}
			}
	}
}

private struct ContactPromptDetents: ViewModifier {
	func body(content: Content) -> some View {
		#if os(iOS)
		content.presentationDetents([.medium])
		#else
		content.frame(minWidth: 420, minHeight: 300)
		#endif
	}
}

/// "A remembered device wants to send you files."
private struct OfferSheet: View {
	let offer: IncomingOfferModel
	let busy: Bool
	let onRespond: (String, Bool) -> Void

	var body: some View {
		VStack(spacing: 16) {
			Image(systemSymbol: .trayAndArrowDownFill)
				.font(.system(size: 44))
				.foregroundStyle(.tint)
				.padding(.top, 12)
			Text(String(localized: L10n.Offer.title))
				.font(.title2).fontWeight(.semibold)
			Text(L10n.Offer.body(device: offer.resolvedSenderName, transferName: offer.transferName))
				.multilineTextAlignment(.center)
			Text(L10n.Transfer.fileCount(count: Int(offer.fileCount)))
				.font(.caption)
				.foregroundStyle(.secondary)
			Spacer(minLength: 0)
			HStack(spacing: 12) {
				Button(role: .cancel) {
					onRespond(offer.offerId, false)
				} label: {
					Text(String(localized: L10n.Offer.decline)).frame(maxWidth: .infinity)
				}
				Button {
					onRespond(offer.offerId, true)
				} label: {
					Text(String(localized: L10n.Offer.accept)).frame(maxWidth: .infinity)
				}
				.buttonStyle(.borderedProminent)
			}
			.disabled(busy)
		}
		.padding(20)
	}
}

/// "This device offered to let you reach it. Remember it?"
private struct PairingSheet: View {
	let pairing: PendingPairingModel
	let busy: Bool
	let onRespond: (String, Bool) -> Void

	var body: some View {
		VStack(spacing: 16) {
			Image(systemSymbol: .macbookAndIphone)
				.font(.system(size: 44))
				.foregroundStyle(.tint)
				.padding(.top, 12)
			Text(String(localized: L10n.Pairing.requestTitle))
				.font(.title2).fontWeight(.semibold)
			Text(L10n.Pairing.requestBody(device: pairing.resolvedName))
				.multilineTextAlignment(.center)
			// Names are peer-supplied; the endpoint id is what actually identifies
			// the device.
			Text(L10n.Approval.endpointId(deviceId: pairing.endpointId))
				.font(.caption)
				.foregroundStyle(.secondary)
				.multilineTextAlignment(.center)
			Spacer(minLength: 0)
			HStack(spacing: 12) {
				Button(role: .cancel) {
					onRespond(pairing.endpointId, false)
				} label: {
					Text(String(localized: L10n.Pairing.decline)).frame(maxWidth: .infinity)
				}
				Button {
					onRespond(pairing.endpointId, true)
				} label: {
					Text(String(localized: L10n.Pairing.accept)).frame(maxWidth: .infinity)
				}
				.buttonStyle(.borderedProminent)
			}
			.disabled(busy)
		}
		.padding(20)
	}
}

/// "You just transferred with this device. Let it reach you next time?"
private struct SuggestionSheet: View {
	let suggestion: PairingSuggestion
	let busy: Bool
	let onRespond: (PairingSuggestion, Bool) -> Void

	var body: some View {
		VStack(spacing: 16) {
			Image(systemSymbol: .clockArrowCirclepath)
				.font(.system(size: 44))
				.foregroundStyle(.tint)
				.padding(.top, 12)
			Text(String(localized: L10n.Pairing.allowTitle))
				.font(.title2).fontWeight(.semibold)
			Text(L10n.Pairing.requestBody(device: suggestion.resolvedName))
				.multilineTextAlignment(.center)
			Text(String(localized: L10n.Pairing.allowBody))
				.font(.caption)
				.foregroundStyle(.secondary)
				.multilineTextAlignment(.center)
			Spacer(minLength: 0)
			HStack(spacing: 12) {
				Button(role: .cancel) {
					onRespond(suggestion, false)
				} label: {
					Text(String(localized: L10n.Pairing.decline)).frame(maxWidth: .infinity)
				}
				Button {
					onRespond(suggestion, true)
				} label: {
					Text(String(localized: L10n.Pairing.allowConfirm)).frame(maxWidth: .infinity)
				}
				.buttonStyle(.borderedProminent)
			}
			.disabled(busy)
		}
		.padding(20)
	}
}
