Documentation
pub mod msgs {
    use cosmwasm_schema::{cw_serde, QueryResponses};

    use crate::pool::msgs::LoanInfoResponse;

    use super::definitions::{Config, LoanBaseInfo, LoanKey};

    #[cw_serde]
    pub struct InstantiateMsg {
        pub owner: String,
    }

    #[cw_serde]
    pub enum ExecuteMsg {
        RegisterPool { address: String },
        AddLoanPosition(AddLoanPositionMsg),
        RemoveLoanPosition(RemoveLoanPositionMsg),
        RemoveLoanPositions(RemoveLoanPositionsMsg),
        UpdateConfig(UpdateConfigMsg),
    }

    #[cw_serde]
    #[derive(QueryResponses)]
    pub enum QueryMsg {
        #[returns(UserLoansBaseInfoResponse)]
        UsersLoansBaseInfo {
            user: String,
            limit: Option<u32>,
            start_after: Option<LoanKey>,
        },
        
        #[returns(UserLoansBaseFullResponse)]
        UsersLoansFullInfo {
            user: String,
            limit: Option<u32>,
            start_after: Option<LoanKey>,
        },

        #[returns(Config)]
        Config {},
    }

    #[cw_serde]
    pub struct MigrateMsg {}

    #[cw_serde]
    pub struct AddLoanPositionMsg {
        pub owner: String,
        pub id: u64,
    }

    #[cw_serde]
    pub struct RemoveLoanPositionMsg {
        pub id: u64,
    }
    #[cw_serde]
    pub struct RemoveLoanPositionsMsg {
        pub ids: Vec<u64>,
    }

    #[cw_serde]
    pub struct UpdateConfigMsg {
        pub owner: Option<String>,
        pub factory: Option<String>,
    }

    #[cw_serde]
    pub struct UserLoansBaseInfoResponse {
        pub loans: Vec<(LoanKey, LoanBaseInfo)>,
    }

    impl From<Vec<(LoanKey, LoanBaseInfo)>> for UserLoansBaseInfoResponse {
        fn from(value: Vec<(LoanKey, LoanBaseInfo)>) -> Self {
            UserLoansBaseInfoResponse { loans: value }
        }
    }

    #[cw_serde]
    pub struct UserLoansBaseFullResponse {
        pub loans: Vec<(LoanKey, LoanInfoResponse)>,
    }

    impl From<Vec<(LoanKey, LoanInfoResponse)>> for UserLoansBaseFullResponse {
        fn from(value: Vec<(LoanKey, LoanInfoResponse)>) -> Self {
            UserLoansBaseFullResponse { loans: value }
        }
    }
}

pub mod definitions {
    use cosmwasm_schema::cw_serde;
    use cosmwasm_std::Addr;

    use crate::traits::AssertOwner;

    pub type LoanKey = (Addr, u64);

    #[cw_serde]
    pub struct Config {
        pub owner: Addr,
        pub factory: Addr,
    }

    impl AssertOwner for Config {
        fn get_admin(&self) -> Addr {
            self.owner.clone()
        }
    }

    #[cw_serde]
    pub struct LoanBaseInfo {
        pub owner: Addr,
        pub id: u64,
    }
}