use std::fmt;

/// The main AST (Abstract Syntax Tree) structure for the Liquid language.
/// Contains the list of imported libraries and declared component classes.
#[derive(Debug, PartialEq, Clone)]
pub struct LiquidAST {
    pub imports: Vec<ImportStmt>,
    pub classes: Vec<ClassDecl>,
}

/// Representation of an import statement (e.g. `import 'liquid:ui';`).
#[derive(Debug, PartialEq, Clone)]
pub struct ImportStmt {
    pub path: String,
}

/// Representation of a component class declaration (e.g. `class Counter extends Component { ... }`).
#[derive(Debug, PartialEq, Clone)]
pub struct ClassDecl {
    pub name: String,
    pub extends_class: String,
    pub properties: Vec<PropertyDecl>,
    pub methods: Vec<MethodDecl>,
    pub render: RenderDecl,
}

/// Representation of a property/state declaration (e.g. `int count = 0;`).
#[derive(Debug, PartialEq, Clone)]
pub struct PropertyDecl {
    pub type_name: String,
    pub name: String,
    pub value: Value,
}

/// Representation of a method/logic function declaration (e.g. `void increment() { count++; }`).
#[derive(Debug, PartialEq, Clone)]
pub struct MethodDecl {
    pub type_name: String,
    pub name: String,
    pub statements: Vec<Statement>,
}

/// Representation of a statement inside a method.
#[derive(Debug, PartialEq, Clone)]
pub enum Statement {
    Expr(StatementExpr),
    Return(Value),
}

/// Representation of a simple statement expression (e.g. `count++` or `count`).
#[derive(Debug, PartialEq, Clone)]
pub struct StatementExpr {
    pub name: String,
    pub args: Option<Vec<Value>>,
    pub op: Option<String>, // Stores "++", "--" or None
}

/// Representation of literal values, arrays, elements, or identifiers.
#[derive(Debug, PartialEq, Clone)]
pub enum Value {
    StringLit(String),
    NumberLit(String),
    Array(Vec<Value>),
    Element(Box<Element>),
    Identifier(String),
}

/// Representation of a UI element property (e.g. `label: "Add Data"` or `spacing: 16.0`).
#[derive(Debug, PartialEq, Clone)]
pub struct Prop {
    pub name: String,
    pub value: Value,
}

/// Representation of a declarative UI element (e.g. `Column(alignment: center, children: [...])`).
#[derive(Debug, PartialEq, Clone)]
pub struct Element {
    pub name: String,
    pub props: Vec<Prop>,
}

/// Representation of the main UI render/build function declaration (e.g. `@override Widget build() { return ...; }`).
#[derive(Debug, PartialEq, Clone)]
pub struct RenderDecl {
    pub annotation: Option<String>, // Stores "@override" or None
    pub type_name: String,           // Typically "Widget"
    pub name: String,                // Typically "build"
    pub element: Element,            // The root element returned
}

/// Definition of errors that can occur during compilation.
#[derive(Debug, PartialEq)]
pub enum CompilerError {
    ParseError(String),
    AstConversionError(String),
}

impl fmt::Display for CompilerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            CompilerError::ParseError(msg) => write!(f, "Parse Error: {}", msg),
            CompilerError::AstConversionError(msg) => write!(f, "AST Conversion Error: {}", msg),
        }
    }
}

impl std::error::Error for CompilerError {}
