#![allow(unused_assignments)] // False positives in error enum fields used by thiserror

pub mod ast;
pub mod keywords;
pub mod lexer;

// Parser is generated by LALRPOP
#[allow(clippy::all)]
#[allow(unused)]
mod parser;

pub use parser::FileParser;

#[cfg(test)]
mod prop_tests;

#[cfg(test)]
mod resource_linking_tests;

#[cfg(test)]
mod schedule_composition_tests;

#[cfg(test)]
mod type_system_tests;

use miette::Diagnostic;
use thiserror::Error;

#[derive(Error, Debug, Diagnostic)]
pub enum ParseError {
    #[error("Unexpected token: {token}")]
    #[diagnostic(help("Check for syntax errors like missing braces, colons, or semicolons. Common issues: forgetting ':' after field names, missing '}}' to close a block, or using reserved keywords as names."))]
    UnexpectedToken {
        #[allow(dead_code)]
        #[allow(unused_assignments)]
        token: String,
        #[label("unexpected token here")]
        span: miette::SourceSpan,
    },

    #[error("Unexpected end of file")]
    #[diagnostic(help("The file ended before a declaration was complete. Check that all blocks are properly closed with '}}', all strings are closed with quotes, and all prose blocks end with '---'."))]
    UnexpectedEof {
        #[label("file ended here, but expected more input")]
        span: miette::SourceSpan,
    },

    #[error("Invalid token")]
    #[diagnostic(help("This character or sequence is not valid in Storybook syntax. Common issues: special characters in names (use letters, numbers, and underscores only), unescaped quotes in strings, or invalid time formats."))]
    InvalidToken {
        #[label("invalid token here")]
        span: miette::SourceSpan,
    },

    #[error("Unclosed prose block starting with ---{tag}")]
    #[diagnostic(help("Prose blocks must be closed with '---' on its own line. Make sure the closing '---' is at the start of a line with no other text before it."))]
    UnclosedProseBlock {
        #[allow(dead_code)]
        #[allow(unused_assignments)]
        tag: String,
        #[label("prose block starts here but never closes")]
        span: miette::SourceSpan,
    },
}

pub type ParseResult<T> = Result<T, ParseError>;
