use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{ExprKind, LitIntType, LitKind, StrStyle, UintTy, token};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
use rustc_session::errors::report_lit_error;
use rustc_span::{ErrorGuaranteed, Span};

use crate::errors;
use crate::util::get_exprs_from_tts;

/// Emits errors for literal expressions that are invalid inside and outside of an array.
fn invalid_type_err(
    cx: &ExtCtxt<'_>,
    token_lit: token::Lit,
    span: Span,
    is_nested: bool,
) -> ErrorGuaranteed {
    use errors::{
        ConcatBytesInvalid, ConcatBytesInvalidSuggestion, ConcatBytesNonU8, ConcatBytesOob,
    };
    let snippet = cx.sess.source_map().span_to_snippet(span).ok();
    let dcx = cx.dcx();
    match LitKind::from_token_lit(token_lit) {
        Ok(LitKind::CStr(_, style)) => {
            // Avoid ambiguity in handling of terminal `NUL` by refusing to
            // concatenate C string literals as bytes.
            let sugg = if let Some(mut as_bstr) = snippet
                && style == StrStyle::Cooked
                && as_bstr.starts_with('c')
                && as_bstr.ends_with('"')
            {
                // Suggest`c"foo"` -> `b"foo\0"` if we can
                as_bstr.replace_range(0..1, "b");
                as_bstr.pop();
                as_bstr.push_str(r#"\0""#);
                Some(ConcatBytesInvalidSuggestion::CStrLit { span, as_bstr })
            } else {
                // No suggestion for a missing snippet, raw strings, or if for some reason we have
                // a span that doesn't match `c"foo"` (possible if a proc macro assigns a span
                // that doesn't actually point to a C string).
                None
            };
            // We can only provide a suggestion if we have a snip and it is not a raw string
            dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "C string", sugg, cs_note: Some(()) })
        }
        Ok(LitKind::Char(_)) => {
            let sugg =
                snippet.map(|snippet| ConcatBytesInvalidSuggestion::CharLit { span, snippet });
            dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg, cs_note: None })
        }
        Ok(LitKind::Str(_, _)) => {
            // suggestion would be invalid if we are nested
            let sugg = if !is_nested {
                snippet.map(|snippet| ConcatBytesInvalidSuggestion::StrLit { span, snippet })
            } else {
                None
            };
            dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg, cs_note: None })
        }
        Ok(LitKind::Float(_, _)) => {
            dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None, cs_note: None })
        }
        Ok(LitKind::Bool(_)) => dcx.emit_err(ConcatBytesInvalid {
            span,
            lit_kind: "boolean",
            sugg: None,
            cs_note: None,
        }),
        Ok(LitKind::Int(_, _)) if !is_nested => {
            let sugg =
                snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span, snippet });
            dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg, cs_note: None })
        }
        Ok(LitKind::Int(val, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8))) => {
            assert!(val.get() > u8::MAX.into()); // must be an error
            dcx.emit_err(ConcatBytesOob { span })
        }
        Ok(LitKind::Int(_, _)) => dcx.emit_err(ConcatBytesNonU8 { span }),
        Ok(LitKind::ByteStr(..) | LitKind::Byte(_)) => unreachable!(),
        Ok(LitKind::Err(guar)) => guar,
        Err(err) => report_lit_error(&cx.sess.psess, err, token_lit, span),
    }
}

/// Returns `expr` as a *single* byte literal if applicable.
///
/// Otherwise, returns `None`, and either pushes the `expr`'s span to `missing_literals` or
/// updates `guar` accordingly.
fn handle_array_element(
    cx: &ExtCtxt<'_>,
    guar: &mut Option<ErrorGuaranteed>,
    missing_literals: &mut Vec<rustc_span::Span>,
    expr: &Box<rustc_ast::Expr>,
) -> Option<u8> {
    let dcx = cx.dcx();

    match expr.kind {
        ExprKind::Lit(token_lit) => {
            match LitKind::from_token_lit(token_lit) {
                Ok(LitKind::Int(
                    val,
                    LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8),
                )) if let Ok(val) = u8::try_from(val.get()) => {
                    return Some(val);
                }
                Ok(LitKind::Byte(val)) => return Some(val),
                Ok(LitKind::ByteStr(..)) => {
                    guar.get_or_insert_with(|| {
                        dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: true })
                    });
                }
                _ => {
                    guar.get_or_insert_with(|| invalid_type_err(cx, token_lit, expr.span, true));
                }
            };
        }
        ExprKind::Array(_) | ExprKind::Repeat(_, _) => {
            guar.get_or_insert_with(|| {
                dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false })
            });
        }
        ExprKind::IncludedBytes(..) => {
            guar.get_or_insert_with(|| {
                dcx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false })
            });
        }
        _ => missing_literals.push(expr.span),
    }

    None
}

pub(crate) fn expand_concat_bytes(
    cx: &mut ExtCtxt<'_>,
    sp: Span,
    tts: TokenStream,
) -> MacroExpanderResult<'static> {
    let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else {
        return ExpandResult::Retry(());
    };
    let es = match mac {
        Ok(es) => es,
        Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
    };
    let mut accumulator = Vec::new();
    let mut missing_literals = vec![];
    let mut guar = None;
    for e in es {
        match &e.kind {
            ExprKind::Array(exprs) => {
                for expr in exprs {
                    if let Some(elem) =
                        handle_array_element(cx, &mut guar, &mut missing_literals, expr)
                    {
                        accumulator.push(elem);
                    }
                }
            }
            ExprKind::Repeat(expr, count) => {
                if let ExprKind::Lit(token_lit) = count.value.kind
                    && let Ok(LitKind::Int(count_val, _)) = LitKind::from_token_lit(token_lit)
                {
                    if let Some(elem) =
                        handle_array_element(cx, &mut guar, &mut missing_literals, expr)
                    {
                        for _ in 0..count_val.get() {
                            accumulator.push(elem);
                        }
                    }
                } else {
                    guar = Some(
                        cx.dcx().emit_err(errors::ConcatBytesBadRepeat { span: count.value.span }),
                    );
                }
            }
            &ExprKind::Lit(token_lit) => match LitKind::from_token_lit(token_lit) {
                Ok(LitKind::Byte(val)) => {
                    accumulator.push(val);
                }
                Ok(LitKind::ByteStr(ref byte_sym, _)) => {
                    accumulator.extend_from_slice(byte_sym.as_byte_str());
                }
                _ => {
                    guar.get_or_insert_with(|| invalid_type_err(cx, token_lit, e.span, false));
                }
            },
            ExprKind::IncludedBytes(byte_sym) => {
                accumulator.extend_from_slice(byte_sym.as_byte_str());
            }
            ExprKind::Err(guarantee) => {
                guar = Some(*guarantee);
            }
            ExprKind::Dummy => cx.dcx().span_bug(e.span, "concatenating `ExprKind::Dummy`"),
            _ => {
                missing_literals.push(e.span);
            }
        }
    }
    ExpandResult::Ready(if !missing_literals.is_empty() {
        let guar = cx.dcx().emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals });
        MacEager::expr(DummyResult::raw_expr(sp, Some(guar)))
    } else if let Some(guar) = guar {
        MacEager::expr(DummyResult::raw_expr(sp, Some(guar)))
    } else {
        let sp = cx.with_def_site_ctxt(sp);
        MacEager::expr(cx.expr_byte_str(sp, accumulator))
    })
}
