use std::ops::Range;

use crate::{ParseError, Parser, ParserErrorKind, ast::Path, lexer::Token};

#[derive(Debug)]
pub struct PrimaryKey<'a> {
    pub span: Range<usize>,
    pub columns: Vec<Path<'a>>,
}

impl<'a> Parser<'a> {
    pub(crate) fn parse_primary_key(&mut self) -> Result<PrimaryKey<'a>, ParseError> {
        let span_start = self.consume(&[Token::Primary])?.span.start;
        self.consume(&[Token::Key])?;
        self.consume(&[Token::LParen])?;

        let mut columns = Vec::new();
        loop {
            let tok = self.lexer.peek();
            match &tok.token {
                Token::Identifier(_) | Token::IntegerLiteral(_) => {
                    match self.parse_path() {
                        Ok(path) => columns.push(path),
                        Err(err) => {
                            self.errors.push(err);
                            self.sync();
                        }
                    }
                    self.maybe_skip_comma();
                }
                Token::RParen => break,
                _ => {
                    let err = ParseError {
                        span: tok.span.clone(),
                        kind: ParserErrorKind::unexpected_token(
                            &[Token::empty_ident(), Token::RParen],
                            &tok.token,
                        ),
                    };
                    if tok.token == Token::Eof {
                        return Err(err);
                    }
                    self.errors.push(err);
                    self.lexer.advance();
                    self.sync();
                }
            }
        }

        let span_end = self.consume(&[Token::RParen])?.span.end;

        Ok(PrimaryKey {
            span: span_start..span_end,
            columns,
        })
    }
}
