use std::{error::Error, rc::Rc};

use common::{net::tools::Packet, tools::time_utils};
use proto::{PlayerLogoutReason, ServerDisconnectClientNotify, SetPlayerBornDataRsp};

use crate::player::Player;

use super::get_proto;

pub fn on_set_player_born_data_req(
    player: &Rc<Player>,
    packet: Packet,
) -> Result<(), Box<dyn Error>> {
    let req = get_proto!(packet, SetPlayerBornDataReq);

    let retcode = player.set_player_born_data(req).err().unwrap_or_default();

    player.send_proto(SetPlayerBornDataRsp {
        retcode: retcode.into(),
    });

    Ok(())
}

pub fn on_player_logout_req(player: &Rc<Player>, packet: Packet) -> Result<(), Box<dyn Error>> {
    let req = get_proto!(packet, PlayerLogoutReq);

    tracing::info!("on_player_logout, uid: {}", player.uid);

    if player.block_stop_coroutine().is_err() {
        return Ok(());
    }

    player.save_to_db();
    if req.reason == PlayerLogoutReason::ClientReq as i32 {
        player.send_proto(ServerDisconnectClientNotify { data: 1 });
    }

    Ok(())
}

pub fn on_union_cmd_notify(player: &Rc<Player>, packet: Packet) -> Result<(), Box<dyn Error>> {
    // TODO: PlayerHandler::checkUnionFrequent

    let notify = get_proto!(packet, UnionCmdNotify);
    for cmd in notify.cmd_list {
        let last_time = time_utils::get_now_ms();

        let err = super::process_packet(
            player,
            Packet {
                cmd_id: cmd.message_id as u16,
                recv_vec: cmd.body,
                head: proto::PacketHead::default(),
            },
        )
        .err();

        let time = time_utils::get_now_ms();
        tracing::info!(
            "|UnionSubCmd|{}|{}|{}|",
            player.uid,
            cmd.message_id,
            time - last_time
        );

        if let Some(err) = err {
            tracing::warn!("UnionSubCmd process failed: {err:?}");
        }
    }

    Ok(())
}
