use std::path::PathBuf;
use bytes::Bytes;
use iroh_base::hash::Hash;
use nested_enum_utils::enum_conversions;
use quic_rpc_derive::rpc_requests;
use serde::{Deserialize, Serialize};
use super::{RpcError, RpcResult, RpcService};
use crate::{
    export::ExportProgress,
    format::collection::Collection,
    get::db::DownloadProgress,
    net_protocol::{BatchId, BlobDownloadRequest},
    provider::{AddProgress, BatchAddPathProgress},
    rpc::client::blobs::{BlobInfo, BlobStatus, IncompleteBlobInfo, ReadAtLen, WrapOption},
    store::{
        BaoBlobSize, ConsistencyCheckProgress, ExportFormat, ExportMode, ImportMode,
        ValidateProgress,
    },
    util::SetTagOption,
    BlobFormat, HashAndFormat, Tag,
};
#[allow(missing_docs)]
#[derive(strum::Display, Debug, Serialize, Deserialize)]
#[enum_conversions(super::Request)]
#[rpc_requests(RpcService)]
pub enum Request {
    #[server_streaming(response = RpcResult<ReadAtResponse>)]
    ReadAt(ReadAtRequest),
    #[bidi_streaming(update = AddStreamUpdate, response = AddStreamResponse)]
    AddStream(AddStreamRequest),
    AddStreamUpdate(AddStreamUpdate),
    #[server_streaming(response = AddPathResponse)]
    AddPath(AddPathRequest),
    #[server_streaming(response = DownloadResponse)]
    Download(BlobDownloadRequest),
    #[server_streaming(response = ExportResponse)]
    Export(ExportRequest),
    #[server_streaming(response = RpcResult<BlobInfo>)]
    List(ListRequest),
    #[server_streaming(response = RpcResult<IncompleteBlobInfo>)]
    ListIncomplete(ListIncompleteRequest),
    #[rpc(response = RpcResult<()>)]
    Delete(DeleteRequest),
    #[server_streaming(response = ValidateProgress)]
    Validate(ValidateRequest),
    #[server_streaming(response = ConsistencyCheckProgress)]
    Fsck(ConsistencyCheckRequest),
    #[rpc(response = RpcResult<CreateCollectionResponse>)]
    CreateCollection(CreateCollectionRequest),
    #[rpc(response = RpcResult<BlobStatusResponse>)]
    BlobStatus(BlobStatusRequest),
    #[bidi_streaming(update = BatchUpdate, response = BatchCreateResponse)]
    BatchCreate(BatchCreateRequest),
    BatchUpdate(BatchUpdate),
    #[bidi_streaming(update = BatchAddStreamUpdate, response = BatchAddStreamResponse)]
    BatchAddStream(BatchAddStreamRequest),
    BatchAddStreamUpdate(BatchAddStreamUpdate),
    #[server_streaming(response = BatchAddPathResponse)]
    BatchAddPath(BatchAddPathRequest),
    #[rpc(response = RpcResult<()>)]
    BatchCreateTempTag(BatchCreateTempTagRequest),
}
#[allow(missing_docs)]
#[derive(strum::Display, Debug, Serialize, Deserialize)]
#[enum_conversions(super::Response)]
pub enum Response {
    ReadAt(RpcResult<ReadAtResponse>),
    AddStream(AddStreamResponse),
    AddPath(AddPathResponse),
    List(RpcResult<BlobInfo>),
    ListIncomplete(RpcResult<IncompleteBlobInfo>),
    Download(DownloadResponse),
    Fsck(ConsistencyCheckProgress),
    Export(ExportResponse),
    Validate(ValidateProgress),
    CreateCollection(RpcResult<CreateCollectionResponse>),
    BlobStatus(RpcResult<BlobStatusResponse>),
    BatchCreate(BatchCreateResponse),
    BatchAddStream(BatchAddStreamResponse),
    BatchAddPath(BatchAddPathResponse),
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AddPathRequest {
    pub path: PathBuf,
    pub in_place: bool,
    pub tag: SetTagOption,
    pub wrap: WrapOption,
}
#[derive(Debug, Serialize, Deserialize, derive_more::Into)]
pub struct AddPathResponse(pub AddProgress);
#[derive(Debug, Clone, Serialize, Deserialize, derive_more::From, derive_more::Into)]
pub struct DownloadResponse(pub DownloadProgress);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExportRequest {
    pub hash: Hash,
    pub path: PathBuf,
    pub format: ExportFormat,
    pub mode: ExportMode,
}
#[derive(Debug, Clone, Serialize, Deserialize, derive_more::From, derive_more::Into)]
pub struct ExportResponse(pub ExportProgress);
#[derive(Debug, Serialize, Deserialize)]
pub struct ConsistencyCheckRequest {
    pub repair: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ValidateRequest {
    pub repair: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ListRequest;
#[derive(Debug, Serialize, Deserialize)]
pub struct ListIncompleteRequest;
#[derive(Serialize, Deserialize, Debug)]
pub struct ReadAtRequest {
    pub hash: Hash,
    pub offset: u64,
    pub len: ReadAtLen,
}
#[derive(Serialize, Deserialize, Debug)]
pub enum ReadAtResponse {
    Entry {
        size: BaoBlobSize,
        is_complete: bool,
    },
    Data {
        chunk: Bytes,
    },
}
#[derive(Serialize, Deserialize, Debug)]
pub struct AddStreamRequest {
    pub tag: SetTagOption,
}
#[derive(Serialize, Deserialize, Debug)]
pub enum AddStreamUpdate {
    Chunk(Bytes),
    Abort,
}
#[derive(Debug, Serialize, Deserialize, derive_more::Into)]
pub struct AddStreamResponse(pub AddProgress);
#[derive(Debug, Serialize, Deserialize)]
pub struct DeleteRequest {
    pub hash: Hash,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct CreateCollectionRequest {
    pub collection: Collection,
    pub tag: SetTagOption,
    pub tags_to_delete: Vec<Tag>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct CreateCollectionResponse {
    pub hash: Hash,
    pub tag: Tag,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BlobStatusRequest {
    pub hash: Hash,
}
#[derive(Debug, Serialize, Deserialize, derive_more::From, derive_more::Into)]
pub struct BlobStatusResponse(pub BlobStatus);
#[derive(Debug, Serialize, Deserialize)]
pub struct BatchCreateRequest;
#[derive(Debug, Serialize, Deserialize)]
pub enum BatchUpdate {
    Drop(HashAndFormat),
    Ping,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum BatchCreateResponse {
    Id(BatchId),
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BatchCreateTempTagRequest {
    pub content: HashAndFormat,
    pub batch: BatchId,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct BatchAddStreamRequest {
    pub format: BlobFormat,
    pub batch: BatchId,
}
#[derive(Serialize, Deserialize, Debug)]
pub enum BatchAddStreamUpdate {
    Chunk(Bytes),
    Abort,
}
#[allow(missing_docs)]
#[derive(Debug, Serialize, Deserialize)]
pub enum BatchAddStreamResponse {
    Abort(RpcError),
    OutboardProgress { offset: u64 },
    Result { hash: Hash },
}
#[derive(Serialize, Deserialize, Debug)]
pub struct BatchAddPathRequest {
    pub path: PathBuf,
    pub import_mode: ImportMode,
    pub format: BlobFormat,
    pub batch: BatchId,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct BatchAddPathResponse(pub BatchAddPathProgress);