use crate::serial_core::frame::TactileAFrame;
use crate::serial_core::record::{RecordedFrame, Recording};
use serde::Serialize;
use std::sync::{Arc, Mutex};

#[derive(Debug, Clone, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum CalibrationState {
    Idle,
    CollectingData,
    ExportingData,
    WaitingForWeight,
    Completed,
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CalibrationSession {
    pub state: CalibrationState,
    pub target_frame: usize,
    pub collected_frames: usize,
    pub current_round: usize,
    pub max_rounds: usize,
    pub data: Vec<RecordedFrame<TactileAFrame>>,
}

impl CalibrationSession {
    pub fn new(targt_frame: usize, max_round: usize) -> Self {
        Self {
            state: CalibrationState::Idle,
            target_frame: targt_frame,
            collected_frames: 0,
            current_round: 1,
            max_rounds: max_round,
            data: Vec::new(),
        }
    }

    pub fn start(&mut self) {
        self.state = CalibrationState::CollectingData;
        self.collected_frames = 0;
        self.data.clear();
        println!(
            "标定第 {} 轮开始，目标收集 {} 个有效帧",
            self.current_round, self.target_frame
        );
    }

    pub fn add_frame(&mut self, frame: RecordedFrame<TactileAFrame>) -> bool {
        if self.state != CalibrationState::CollectingData {
            return false;
        }

        self.data.push(frame);
        self.collected_frames += 1;

        if self.collected_frames >= self.target_frame {
            self.state = CalibrationState::ExportingData;
            return true;
        }

        return false;
    }

    pub fn export_completed(&mut self) {
        self.state = CalibrationState::WaitingForWeight;
        println!("请修改配重，继续标定");
    }

    pub fn weight_added(&mut self) -> Result<(), String> {
        if self.current_round >= self.max_rounds {
            self.state = CalibrationState::Completed;
            println!("标定完成，共 {} 轮", self.current_round);
        } else {
            self.current_round += 1;
            self.start();
        }

        Ok(())
    }

    pub fn get_progress(&self) -> CalibrationProgress {
        CalibrationProgress {
            state: self.state.clone(),
            current_round: self.current_round,
            max_rounds: self.max_rounds,
            collected_frames: self.collected_frames,
            target_frames: self.target_frame,
            progress_percentage: if self.target_frame > 0 {
                (self.collected_frames as f32 / self.target_frame as f32) * 100.0
            } else {
                0.0
            },
        }
    }
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CalibrationProgress {
    pub state: CalibrationState,
    pub current_round: usize,
    pub max_rounds: usize,
    pub collected_frames: usize,
    pub target_frames: usize,
    pub progress_percentage: f32,
}

pub type SharedCalibrationSession = Arc<Mutex<Option<CalibrationSession>>>;
