use std::sync::Arc;

use anyhow::Ok;
use sea_orm::{DatabaseConnection, EntityTrait, QuerySelect};
use serde::{Deserialize, Serialize};

use crate::models::{
    prelude::{StoreArea, StoreTable},
    store_area, store_table,
};

pub struct Table {
    conn: Arc<DatabaseConnection>,
}

#[derive(Deserialize, Serialize)]
struct QueryTable {
    id: i32,
    table_no: String,
    capacity: Option<i32>,
}

#[derive(Deserialize, Serialize)]
pub struct AreaWithTable {
    id: i32,
    name: String,
    description: Option<String>,
    tables: Vec<QueryTable>,
}

impl Table {
    pub fn new(conn: Arc<DatabaseConnection>) -> Self {
        return Self { conn };
    }
    pub async fn get_table_area(&self) -> anyhow::Result<Vec<AreaWithTable>> {
        let area_with_table = StoreArea::find()
            .find_with_related(StoreTable)
            .column(store_area::Column::Id)
            .column(store_area::Column::Name)
            .column(store_area::Column::Description)
            .column(store_table::Column::Id)
            .column(store_table::Column::TableNo)
            .column(store_table::Column::Capacity)
            .all(&*self.conn)
            .await?;
        Ok(area_with_table
            .into_iter()
            .map(|(area, tables)| AreaWithTable {
                id: area.id,
                name: area.name,
                description: area.description,
                tables: tables
                    .iter()
                    .map(|table| QueryTable {
                        id: table.id,
                        table_no: table.table_no.clone(),
                        capacity: table.capacity,
                    })
                    .collect(),
            })
            .collect())
    }
}
