use crate::span::Span;

/// Arithmetic / symbolic operators.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Operator {
    Add,
    Subtract,
    Multiply,
    Divide,
    Power,
    Modulo,
}

/// The kind of a token (payload).
#[derive(Debug, Clone, PartialEq)]
pub enum TokenKind {
    /// Numeric literal.
    Number(f64),
    /// Arithmetic operator.
    Op(Operator),
    /// Opening parenthesis `(`.
    LParen,
    /// Closing parenthesis `)`.
    RParen,
    /// An identifier (variable name, constant like `pi`).
    Identifier(String),
    /// A unit suffix such as `kg`, `g`, `m`, `lb`.
    Unit(String),
    /// A currency symbol prefix such as `$`, `€`, `£`.
    CurrencySymbol(String),
    /// The keyword `in` (for conversions).
    In,
    /// A percentage literal, e.g. `5%` → stores `5.0`.
    Percent(f64),
    /// Comparison `>`.
    Greater,
    /// Comparison `<`.
    Less,
    /// Comparison `>=`.
    GreaterEq,
    /// Comparison `<=`.
    LessEq,
    /// Comparison `==`.
    Equal,
    /// Comparison `!=`.
    NotEqual,
    /// Assignment `=`.
    Assign,
    /// Line reference: `line1`, `#1` (stores the 1-indexed line number).
    LineRef(usize),
    /// Previous-line reference: `prev` or `ans`.
    PrevRef,
    /// A generic keyword (discount, off, etc.).
    Keyword(String),
    /// A comment token.
    Comment(String),
    /// Plain text (non-calculable).
    Text(String),
    /// End of input sentinel.
    Eof,
}

/// A token produced by the lexer, pairing a kind with its source span.
#[derive(Debug, Clone, PartialEq)]
pub struct Token {
    pub kind: TokenKind,
    pub span: Span,
}

impl Token {
    pub fn new(kind: TokenKind, span: Span) -> Self {
        Self { kind, span }
    }
}
