//! Card face labels: desktop text labels and Android corner labels.

use super::*;


use bevy::color::Color;
use bevy::sprite::Anchor;
use solitaire_core::{Card, Rank, Suit};

use crate::ui_theme::TEXT_PRIMARY_HC;

pub(super) fn label_for(card: &Card) -> String {
    let rank = match card.rank() {
        Rank::Ace => "A",
        Rank::Two => "2",
        Rank::Three => "3",
        Rank::Four => "4",
        Rank::Five => "5",
        Rank::Six => "6",
        Rank::Seven => "7",
        Rank::Eight => "8",
        Rank::Nine => "9",
        Rank::Ten => "10",
        Rank::Jack => "J",
        Rank::Queen => "Q",
        Rank::King => "K",
    };
    let suit = match card.suit() {
        Suit::Clubs => "C",
        Suit::Diamonds => "D",
        Suit::Hearts => "H",
        Suit::Spades => "S",
    };
    format!("{rank}{suit}")
}

/// Suit colour for the rank/suit overlay rendered atop the constant
/// fallback sprite (only fires under `MinimalPlugins` — production
/// renders the suit glyph baked into the PNG). 2-colour traditional
/// pairing — hearts + diamonds share the saturated red, clubs +
/// spades share the near-white. Two accessibility flags compose:
///
/// - `color_blind`: red-suit cards swap to `RED_SUIT_COLOUR_CBM`
///   (lime) — the "Settings toggle swaps red→lime" half of the
///   design system's colour-blind support. CBM is a hue-replacement
///   for red, so HC has no further effect on red when CBM is on
///   (the lime is itself a high-luminance colour).
/// - `high_contrast`: when CBM is off, red suits boost to
///   `RED_SUIT_COLOUR_HC` (`#ff6868`); black suits boost from
///   `#e8e8e8` (near-white) to `#f5f5f5` (`TEXT_PRIMARY_HC`).
///
/// The other half of CBM support (always-on filled-vs-outlined
/// glyph differentiation for ♥♠ vs ♦♣) is baked into the PNG art
/// and has no constant-fallback equivalent.
pub(super) fn text_colour(card: &Card, color_blind: bool, high_contrast: bool) -> Color {
    if card.suit().is_red() {
        if color_blind {
            // CBM lime wins — the colour-blind swap replaces the
            // red hue entirely, and the lime is already high-
            // luminance, so an HC boost on top has nothing to do.
            RED_SUIT_COLOUR_CBM
        } else if high_contrast {
            RED_SUIT_COLOUR_HC
        } else {
            RED_SUIT_COLOUR
        }
    } else if high_contrast {
        TEXT_PRIMARY_HC
    } else {
        BLACK_SUIT_COLOUR
    }
}

pub(super) fn label_visibility(face_up: bool) -> Visibility {
    if face_up {
        Visibility::Inherited
    } else {
        Visibility::Hidden
    }
}

/// Rank+suit string for the readability overlay on touch HUD layouts.
/// Uses Unicode suit glyphs (♠♥♦♣ — U+2660–U+2666, covered by FiraMono).
pub(super) fn mobile_label_for(card: &Card) -> String {
    let rank = match card.rank() {
        Rank::Ace => "A",
        Rank::Two => "2",
        Rank::Three => "3",
        Rank::Four => "4",
        Rank::Five => "5",
        Rank::Six => "6",
        Rank::Seven => "7",
        Rank::Eight => "8",
        Rank::Nine => "9",
        Rank::Ten => "10",
        Rank::Jack => "J",
        Rank::Queen => "Q",
        Rank::King => "K",
    };
    let suit = match card.suit() {
        Suit::Clubs => "♣",
        Suit::Diamonds => "♦",
        Suit::Hearts => "♥",
        Suit::Spades => "♠",
    };
    format!("{rank}{suit}")
}

/// Spawns the [`AndroidCornerLabel`] + [`AndroidCornerBg`] children on
/// face-up cards. The background sprite covers the card art's own small
/// corner text so only the large overlay is visible.
/// Spawns the [`AndroidCornerLabel`] + [`AndroidCornerBg`] children on
/// face-up cards using FiraMono (passed via `font_handle`) so that the
/// suit Unicode glyphs U+2660–U+2666 render correctly. Without an explicit
/// font handle Bevy falls back to its built-in face which does not include
/// those glyphs, causing a coloured missing-glyph rectangle to appear in
/// the text colour — the root cause of the "red square on face-down cards"
/// visual bug (the box bleeds through near the card edge at z=0.02).
pub(super) fn add_android_corner_label(
    parent: &mut ChildSpawnerCommands,
    card: &Card,
    face_up: bool,
    card_size: Vec2,
    color_blind: bool,
    high_contrast: bool,
    font_handle: Option<&Handle<Font>>,
) {
    if !face_up {
        return;
    }
    let font_size = card_size.x * FONT_SIZE_FRAC_MOBILE;
    let inset = 3.0_f32;
    // Background covers ~3 monospace chars wide × 1 line tall.
    // FiraMono char width ≈ 0.6 × font_size; 2.0× gives room for "10♠"
    // (3 chars = 1.8× font_size) plus a small margin.
    let bg_w = font_size * 2.0;
    let bg_h = font_size * 1.25;

    // Background covers the PNG's baked-in small corner text (top-left).
    // Classic PNG cards have a white face, so the background must be white too.
    // (CARD_FACE_COLOUR is the Terminal theme's dark face colour — wrong here.)
    parent.spawn((
        AndroidCornerBg,
        Sprite {
            color: Color::WHITE,
            custom_size: Some(Vec2::new(bg_w, bg_h)),
            ..default()
        },
        Transform::from_xyz(
            -card_size.x / 2.0 + inset + bg_w / 2.0,
            card_size.y / 2.0 - inset - bg_h / 2.0,
            0.015,
        ),
    ));
    // Cover the matching rotated baked-in text at the bottom-right corner.
    parent.spawn((
        AndroidCornerBg,
        Sprite {
            color: Color::WHITE,
            custom_size: Some(Vec2::new(bg_w, bg_h)),
            ..default()
        },
        Transform::from_xyz(
            card_size.x / 2.0 - inset - bg_w / 2.0,
            -card_size.y / 2.0 + inset + bg_h / 2.0,
            0.015,
        ),
    ));

    // Large rank+suit text drawn on top of the background. FiraMono must be
    // wired here explicitly — the suit glyphs (U+2660–U+2666) are not in
    // Bevy's built-in font and render as a coloured rectangle without it.
    //
    // Classic PNG cards have a white face: red suits stay the same saturated
    // red, but black suits must use a dark colour (CARD_FACE_COLOUR ≈ #1a1a1a)
    // rather than the near-white BLACK_SUIT_COLOUR designed for the dark
    // Terminal theme background.
    let text_col = if card.suit().is_red() {
        if color_blind {
            RED_SUIT_COLOUR_CBM
        } else if high_contrast {
            RED_SUIT_COLOUR_HC
        } else {
            RED_SUIT_COLOUR
        }
    } else {
        CARD_FACE_COLOUR
    };
    let label_text = mobile_label_for(card);
    parent.spawn((
        AndroidCornerLabel(label_text.clone()),
        CardLabel,
        Text2d::new(label_text),
        TextFont {
            font: font_handle.cloned().unwrap_or_default(),
            font_size,
            ..default()
        },
        TextColor(text_col),
        Anchor::TOP_LEFT,
        Transform::from_xyz(-card_size.x / 2.0 + inset, card_size.y / 2.0 - inset, 0.02),
    ));
}

// ---------------------------------------------------------------------------
// Task #34 — Card-flip animation systems
// ---------------------------------------------------------------------------

