use crate::planner::multi_fact_join_groups::MultiFactJoinGroups;
use crate::planner::{MemberSymbol, SqlCall};
use std::fmt::Debug;
use std::rc::Rc;

#[derive(Clone, Debug)]
pub struct PreAggregationJoinItem {
    pub from: Rc<PreAggregationSource>,
    pub to: Rc<PreAggregationSource>,
    pub from_members: Vec<Rc<MemberSymbol>>,
    pub to_members: Vec<Rc<MemberSymbol>>,
    pub on_sql: Rc<SqlCall>,
}

#[derive(Clone, Debug)]
pub struct PreAggregationJoin {
    pub root: Rc<PreAggregationSource>,
    pub items: Vec<PreAggregationJoinItem>,
}

#[derive(Clone, Debug)]
pub struct PreAggregationUnion {
    pub items: Vec<PreAggregationUnionItem>,
}

/// A single member rollup of a `rollupLambda` union, paired with the
/// member symbols of *that* rollup. The lambda exposes the first member
/// rollup's symbols, but each branch stores its columns under its own
/// cube aliases (e.g. `requests_stream__tenant_id` vs `requests__tenant_id`),
/// so the physical builder needs each branch's own symbols to read the
/// right column while projecting the lambda's unified alias.
#[derive(Clone, Debug)]
pub struct PreAggregationUnionItem {
    pub table: Rc<PreAggregationTable>,
    pub measures: Vec<Rc<MemberSymbol>>,
    pub dimensions: Vec<Rc<MemberSymbol>>,
    pub time_dimensions: Vec<Rc<MemberSymbol>>,
}

#[derive(Clone, Debug)]
pub struct PreAggregationTable {
    pub cube_name: String,
    pub cube_alias: String,
    pub name: String,
    pub alias: Option<String>,
    pub usage_index: Option<usize>,
}

#[derive(Clone, Debug)]
pub enum PreAggregationSource {
    Single(PreAggregationTable),
    Join(PreAggregationJoin),
    Union(PreAggregationUnion),
}

#[derive(Clone)]
pub struct CompiledPreAggregation {
    pub cube_name: String,
    pub name: String,
    pub source: Rc<PreAggregationSource>,
    pub granularity: Option<String>,
    pub external: Option<bool>,
    pub measures: Vec<Rc<MemberSymbol>>,
    pub dimensions: Vec<Rc<MemberSymbol>>,
    pub time_dimensions: Vec<Rc<MemberSymbol>>,
    pub segments: Vec<Rc<MemberSymbol>>,
    pub allow_non_strict_date_range_match: bool,
    pub multi_fact_join_groups: MultiFactJoinGroups,
}

impl Debug for CompiledPreAggregation {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("CompiledPreAggregation")
            .field("cube_name", &self.cube_name)
            .field("name", &self.name)
            .field("granularity", &self.granularity)
            .field("external", &self.external)
            .field("measures", &self.measures)
            .field("dimensions", &self.dimensions)
            .field("time_dimensions", &self.time_dimensions)
            .field("segments", &self.segments)
            .field(
                "allow_non_strict_date_range_match",
                &self.allow_non_strict_date_range_match,
            )
            .finish()
    }
}
