// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use bt_common::PeerId;
use futures::channel::oneshot;
use futures::FutureExt;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

use crate::types::*;

/// Confirms the updated track position to store in local state and notify to
/// clients.
/// It is safe to drop without responding to ignore the update or if the value
/// has not changed.
pub type SetTrackPositionResponder = SetValueResponder<TrackPosition>;

/// Confirms the updated playback speed to store in local state and notify to
/// clients.
/// It is safe to drop without responding to ignore the update or if the value
/// has not changed.
pub type SetPlaybackSpeedResponder = SetValueResponder<PlaybackSpeed>;

/// Confirms the updated playing order to store in local state and notify to
/// clients.
/// It is safe to drop without responding to ignore the update or if the value
/// has not changed.
pub type SetPlayingOrderResponder = SetValueResponder<PlayingOrder>;

/// Confirms the media control command result code to notify to the client.
/// A response is expected to confirm the result. If no response is provided,
/// then it is assumed that the Control Point request has failed and
/// `ControlPointResultCode::CommandCannotBeCompleted` will be sent to the peer.
pub type ControlPointWriteResponder = SetValueResponder<ControlPointResultCode>;

/// Responder for an asynchronous characteristic write or control point command.
///
/// Calling [`send`](Self::send) confirms the new value or command result to
/// update local state and notify clients. It is safe to drop the responder
/// without responding to cancel the update (or report command failure).
pub struct SetValueResponder<T> {
    response_tx: oneshot::Sender<T>,
}

impl<T: std::fmt::Debug> SetValueResponder<T> {
    /// Confirms the value or result code determined by the media player
    /// application and dispatches the corresponding GATT notification.
    pub fn send(self, value: T) {
        if let Err(result) = self.response_tx.send(value) {
            log::warn!("Failed to send response: server dropped or closed: {result:?}");
        }
    }
}

impl<T> std::fmt::Debug for SetValueResponder<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("SetValueResponder").finish_non_exhaustive()
    }
}

/// An in-flight handler for a single-value asynchronous write response.
pub(crate) struct SetValueResponseFut<T> {
    rx: oneshot::Receiver<T>,
}

impl<T> SetValueResponseFut<T> {
    pub(crate) fn create() -> (Self, SetValueResponder<T>) {
        let (tx, rx) = oneshot::channel();
        (Self { rx }, SetValueResponder { response_tx: tx })
    }
}

impl<T> Future for SetValueResponseFut<T> {
    type Output = Option<T>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.rx.poll_unpin(cx).map(Result::ok)
    }
}

/// Responses produced when an in-flight asynchronous write response completes.
#[derive(Debug)]
pub(crate) enum PendingWriteResponse {
    ControlPoint {
        peer_id: PeerId,
        opcode: MediaControlOpcode,
        result_code: ControlPointResultCode,
    },
    TrackPosition(TrackPosition),
    PlaybackSpeed(PlaybackSpeed),
    PlayingOrder(PlayingOrder),
}

/// An in-flight asynchronous write response future.
pub(crate) enum PendingWriteResponseFut {
    ControlPoint {
        peer_id: PeerId,
        opcode: MediaControlOpcode,
        fut: SetValueResponseFut<ControlPointResultCode>,
    },
    TrackPosition(SetValueResponseFut<TrackPosition>),
    PlaybackSpeed(SetValueResponseFut<PlaybackSpeed>),
    PlayingOrder(SetValueResponseFut<PlayingOrder>),
}

impl Future for PendingWriteResponseFut {
    type Output = Option<PendingWriteResponse>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match self.as_mut().get_mut() {
            Self::ControlPoint { peer_id, opcode, fut } => fut.poll_unpin(cx).map(|res| {
                let code = res.unwrap_or(ControlPointResultCode::CommandCannotBeCompleted);
                Some(PendingWriteResponse::ControlPoint {
                    peer_id: *peer_id,
                    opcode: opcode.clone(),
                    result_code: code,
                })
            }),
            Self::TrackPosition(fut) => {
                fut.poll_unpin(cx).map(|res| res.map(PendingWriteResponse::TrackPosition))
            }
            Self::PlaybackSpeed(fut) => {
                fut.poll_unpin(cx).map(|res| res.map(PendingWriteResponse::PlaybackSpeed))
            }
            Self::PlayingOrder(fut) => {
                fut.poll_unpin(cx).map(|res| res.map(PendingWriteResponse::PlayingOrder))
            }
        }
    }
}

/// Events produced by an [`McsServer`] stream representing client actions that
/// require additional upper-layer application processing.
#[derive(Debug)]
pub enum McsServerEvent {
    /// Request to set the track playback position.
    SetTrackPosition {
        peer_id: PeerId,
        position: TrackPosition,
        responder: SetValueResponder<TrackPosition>,
    },
    /// Request to set the playback speed.
    SetPlaybackSpeed {
        peer_id: PeerId,
        speed: PlaybackSpeed,
        responder: SetValueResponder<PlaybackSpeed>,
    },
    /// Request to set the playing order.
    SetPlayingOrder {
        peer_id: PeerId,
        order: PlayingOrder,
        responder: SetValueResponder<PlayingOrder>,
    },
    /// Request to execute a media control command.
    ControlPointCommand {
        opcode: MediaControlOpcode,
        responder: SetValueResponder<ControlPointResultCode>,
    },
}

#[cfg(test)]
mod tests {
    use super::*;
    use assert_matches::assert_matches;

    #[test]
    fn set_value_responder_and_fut() {
        let (mut fut, responder) = SetValueResponseFut::<PlaybackSpeed>::create();
        let mut cx = Context::from_waker(futures::task::noop_waker_ref());

        assert!(fut.poll_unpin(&mut cx).is_pending());

        responder.send(PlaybackSpeed::DOUBLE);
        assert_eq!(fut.poll_unpin(&mut cx), Poll::Ready(Some(PlaybackSpeed::DOUBLE)));
    }

    #[test]
    fn set_value_responder_dropped_results_in_none() {
        let (mut fut, responder) = SetValueResponseFut::<TrackPosition>::create();
        let mut cx = Context::from_waker(futures::task::noop_waker_ref());

        assert!(fut.poll_unpin(&mut cx).is_pending());

        drop(responder);
        assert_eq!(fut.poll_unpin(&mut cx), Poll::Ready(None));
    }

    #[test]
    fn pending_write_response_control_point_dropped_defaults_to_cannot_be_completed() {
        let (fut, responder) = SetValueResponseFut::<ControlPointResultCode>::create();
        let peer_id = PeerId(1);
        let mut pending = PendingWriteResponseFut::ControlPoint {
            peer_id,
            opcode: MediaControlOpcode::Play,
            fut,
        };
        let mut cx = Context::from_waker(futures::task::noop_waker_ref());

        assert!(pending.poll_unpin(&mut cx).is_pending());

        drop(responder);
        assert_matches!(
            pending.poll_unpin(&mut cx),
            Poll::Ready(Some(PendingWriteResponse::ControlPoint {
                peer_id: p,
                opcode: MediaControlOpcode::Play,
                result_code: ControlPointResultCode::CommandCannotBeCompleted,
            })) if p == peer_id
        );
    }
}
