# order_screen.py
from __future__ import annotations

import pygame
from order_data import OrderDataProvider

class OrderScreen:
    """
    Compact 3-column order board (no TV image).
    Draw-only class: it asks OrderDataProvider for data and renders it.
    """

    def __init__(self, screen: pygame.Surface, speed = 2):
        self.screen = screen
        self.data = OrderDataProvider(speed=speed, ttl_ms=400, max_orders=3, max_products=12)

        sw, sh = screen.get_width(), screen.get_height()

        # --- Compact area (shorter so it doesn't cover bottom map) ---
        self.width = min(980, int(sw * 0.96))
        self.height = min(330, int(sh * 0.46))
        self.x = (sw - self.width) // 2
        self.y = 13 * 16

        # --- Typography ---
        self.font_title = pygame.font.SysFont("Arial", 20, bold=True)
        self.font_header = pygame.font.SysFont("Arial", 15, bold=True)
        self.font_body = pygame.font.SysFont("Arial", 12)
        self.font_small = pygame.font.SysFont("Arial", 11)

        # Layout
        self.pad = 14
        self.card_pad = 12
        self.card_gap = 12

        # Colors
        self.c_text = (20, 20, 20)
        self.c_muted = (90, 90, 90)
        self.c_border = (210, 210, 210)
        self.c_card_bg = (248, 248, 248)

        # Status pill colors (bg, text)
        self.status_colors = {
            "pending": ((255, 243, 205), (133, 100, 4)),
            "ready": ((212, 237, 218), (21, 87, 36)),
            "paid": ((209, 236, 241), (12, 84, 96)),
            "cancel": ((248, 215, 218), (114, 28, 36)),
        }

    # ---------------- Helpers ----------------

    def _draw_rounded_rect(
        self,
        surface: pygame.Surface,
        rect: pygame.Rect,
        color: tuple[int, int, int],
        radius: int = 12,
        border_color: tuple[int, int, int] | None = None,
        border_width: int = 1,
    ) -> None:
        pygame.draw.rect(surface, color, rect, border_radius=radius)
        if border_color and border_width > 0:
            pygame.draw.rect(surface, border_color, rect, width=border_width, border_radius=radius)

    def _blit_text(
        self,
        surface: pygame.Surface,
        text: str,
        font: pygame.font.Font,
        color: tuple[int, int, int],
        x: int,
        y: int,
    ) -> tuple[int, int]:
        surf = font.render(text, True, color)
        surface.blit(surf, (x, y))
        return surf.get_width(), surf.get_height()

    def _ellipsis(self, text: str, font: pygame.font.Font, max_width: int) -> str:
        if font.size(text)[0] <= max_width:
            return text
        if max_width <= font.size("...")[0]:
            return "..."

        lo, hi = 0, len(text)
        while lo < hi:
            mid = (lo + hi) // 2
            candidate = text[:mid].rstrip() + "..."
            if font.size(candidate)[0] <= max_width:
                lo = mid + 1
            else:
                hi = mid

        return text[: max(0, lo - 1)].rstrip() + "..."

    def _status_style(self, status: str | None):
        s = (status or "").lower()
        if s in self.status_colors:
            return self.status_colors[s]
        return ((235, 235, 235), (60, 60, 60))

    def _format_money(self, value) -> str:
        try:
            return f"{float(value):.2f}€"
        except Exception:
            return "0.00€"

    # ---------------- Main draw ----------------

    def draw(self) -> None:
        """
        Call this from your main loop:
            order_screen.draw()
        """
        orders = self.data.get_orders()
        last_error = self.data.last_error

        bx, by, bw, bh = self.x, self.y, self.width, self.height

        # Title
        self._blit_text(self.screen, "Pending orders", self.font_title, self.c_text, bx + self.pad, by)

        # Error line (small)
        if last_error:
            self._blit_text(
                self.screen,
                f"DB Error: {last_error}",
                self.font_small,
                (180, 0, 0),
                bx + self.pad,
                by + 22,
            )

        # Cards area
        cards_top = by + 34
        cards_h = bh - 34
        cards_w = bw - self.pad * 2

        card_w = (cards_w - self.card_gap * 2) // 3
        card_h = cards_h - self.pad

        for slot in range(3):
            card_x = bx + self.pad + slot * (card_w + self.card_gap)
            card_y = cards_top
            card_rect = pygame.Rect(card_x, card_y, card_w, card_h)

            # Shadow
            shadow = pygame.Surface((card_w + 8, card_h + 8), pygame.SRCALPHA)
            pygame.draw.rect(
                shadow,
                (0, 0, 0, 35),
                pygame.Rect(4, 6, card_w, card_h),
                border_radius=14,
            )
            self.screen.blit(shadow, (card_x - 4, card_y - 6))

            # Card background
            self._draw_rounded_rect(
                self.screen, card_rect, self.c_card_bg, radius=14, border_color=self.c_border, border_width=1
            )

            # Empty slot
            if slot >= len(orders):
                self._blit_text(self.screen, "—", self.font_header, self.c_muted, card_x + self.card_pad, card_y + self.card_pad)
                continue

            order = orders[slot]

            inner_x = card_x + self.card_pad
            inner_y = card_y + self.card_pad
            inner_w = card_w - self.card_pad * 2

            # Header row
            order_id = order.get("id", "N/A")
            status = order.get("status", "unknown")
            table_name = order.get("table", "-")
            total_price = order.get("total", 0)

            self._blit_text(self.screen, f"Order #{order_id}", self.font_header, self.c_text, inner_x, inner_y)

            total_text = self._format_money(total_price)
            total_w = self.font_header.size(total_text)[0]
            self._blit_text(self.screen, total_text, self.font_header, self.c_text, inner_x + inner_w - total_w, inner_y)

            # Status pill
            pill_bg, pill_text = self._status_style(status)
            pill_label = (status or "unknown").upper()
            pill_pad_x, pill_pad_y = 8, 4
            pill_w = self.font_small.size(pill_label)[0] + pill_pad_x * 2
            pill_h = self.font_small.size(pill_label)[1] + pill_pad_y * 2

            pill_x = inner_x + inner_w - total_w - 10 - pill_w
            pill_y = inner_y - 2
            pill_rect = pygame.Rect(pill_x, pill_y, pill_w, pill_h)
            self._draw_rounded_rect(self.screen, pill_rect, pill_bg, radius=999, border_color=None, border_width=0)
            self._blit_text(
                self.screen,
                pill_label,
                self.font_small,
                pill_text,
                pill_x + pill_pad_x,
                pill_y + pill_pad_y - 1,
            )

            # Table line
            self._blit_text(self.screen, f"Table: {table_name}", self.font_body, self.c_muted, inner_x, inner_y + 22)

            # Divider
            divider_y = inner_y + 42
            pygame.draw.line(self.screen, (220, 220, 220), (inner_x, divider_y), (inner_x + inner_w, divider_y), 1)

            # Products
            products = order.get("products", []) or []
            list_y = divider_y + 8
            line_h = 14

            if not products:
                self._blit_text(self.screen, "(No products)", self.font_body, self.c_muted, inner_x, list_y)
                continue

            for p in products[:8]:
                left = f"• {p.get('name', 'Unknown')} x{p.get('qty', 1)}"
                right = f"{p.get('waiter', '-')}"
                right_w = self.font_body.size(right)[0]
                max_left_w = max(40, inner_w - right_w - 10)
                left = self._ellipsis(left, self.font_body, max_left_w)

                self._blit_text(self.screen, left, self.font_body, self.c_text, inner_x, list_y)
                self._blit_text(self.screen, right, self.font_body, self.c_muted, inner_x + inner_w - right_w, list_y)

                list_y += line_h
