from engine.effects.types import EffectConfig, EffectContext, EffectPlugin


class BorderEffect(EffectPlugin):
    """Simple border effect for terminal display.

    Draws a border around the buffer and optionally displays
    performance metrics in the border corners.

    Internally crops to display dimensions to ensure border fits.
    """

    name = "border"
    config = EffectConfig(enabled=True, intensity=1.0)

    def process(self, buf: list[str], ctx: EffectContext) -> list[str]:
        if not buf:
            return buf

        # Get actual display dimensions from context
        display_w = ctx.terminal_width
        display_h = ctx.terminal_height

        # If dimensions are reasonable, crop first - use slightly smaller to ensure fit
        if display_w >= 10 and display_h >= 3:
            # Subtract 2 for border characters (left and right)
            crop_w = display_w - 2
            crop_h = display_h - 2
            buf = self._crop_to_size(buf, crop_w, crop_h)
            w = display_w
            h = display_h
        else:
            # Use buffer dimensions
            h = len(buf)
            w = max(len(line) for line in buf) if buf else 0

        if w < 3 or h < 3:
            return buf

        inner_w = w - 2

        # Get metrics from context
        fps = 0.0
        frame_time = 0.0
        metrics = ctx.get_state("metrics")
        if metrics:
            avg_ms = metrics.get("avg_ms")
            frame_count = metrics.get("frame_count", 0)
            if avg_ms and frame_count > 0:
                fps = 1000.0 / avg_ms
                frame_time = avg_ms

        # Build borders
        # Top border: ┌────────────────────┐ or with FPS
        if fps > 0:
            fps_str = f" FPS:{fps:.0f}"
            if len(fps_str) < inner_w:
                right_len = inner_w - len(fps_str)
                top_border = "┌" + "─" * right_len + fps_str + "┐"
            else:
                top_border = "┌" + "─" * inner_w + "┐"
        else:
            top_border = "┌" + "─" * inner_w + "┐"

        # Bottom border: └────────────────────┘ or with frame time
        if frame_time > 0:
            ft_str = f" {frame_time:.1f}ms"
            if len(ft_str) < inner_w:
                right_len = inner_w - len(ft_str)
                bottom_border = "└" + "─" * right_len + ft_str + "┘"
            else:
                bottom_border = "└" + "─" * inner_w + "┘"
        else:
            bottom_border = "└" + "─" * inner_w + "┘"

        # Build result with left/right borders
        result = [top_border]
        for line in buf[: h - 2]:
            if len(line) >= inner_w:
                result.append("│" + line[:inner_w] + "│")
            else:
                result.append("│" + line + " " * (inner_w - len(line)) + "│")

        result.append(bottom_border)

        return result

    def _crop_to_size(self, buf: list[str], w: int, h: int) -> list[str]:
        """Crop buffer to fit within w x h."""
        result = []
        for i in range(min(h, len(buf))):
            line = buf[i]
            if len(line) > w:
                result.append(line[:w])
            else:
                result.append(line + " " * (w - len(line)))

        # Pad with empty lines if needed (for border)
        while len(result) < h:
            result.append(" " * w)

        return result

    def configure(self, config: EffectConfig) -> None:
        self.config = config
