"""
Core page layout and structural scaffolding components.
"""
from .base import Component
from typing import List
from django.conf import settings
from .container import Row
from .forms import Button
from .environments import Environment

base_template = """
{% load static tailwind_tags pwa %}
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>--SlotTitle--</title>
    <script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/htmx-ext-ws@2.0.4" integrity="sha384-1RwI/nvUSrMRuNj7hX1+27J8XDdCoSLf0EjEyF69nacuWyiJYoQ/j39RT1mSnd2G" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/htmx-ext-alpine-morph@2.0.0/alpine-morph.js"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/morph@3.x.x/dist/cdn.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
    <link rel="preconnect" href="https://api.fontshare.com" crossorigin>
    <link href="https://api.fontshare.com/v2/css?f[]=satoshi@300,400,500,600,700&display=swap" rel="stylesheet">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
    {% progressive_web_app_meta %}
    {% tailwind_css %}
    <script src="https://api.mapbox.com/mapbox-gl-js/v3.14.0/mapbox-gl.js"></script>
    <link
      href="https://api.mapbox.com/mapbox-gl-js/v3.14.0/mapbox-gl.css"
      rel="stylesheet"
    />

    <script src="//unpkg.com/alpinejs" defer></script>
    <script>
        htmx.config.defaultSwapStyle = 'morph';
    </script>
    <style>
        #global-loading-indicator {
            opacity: 0;
            transition: opacity 200ms ease-in;
        }
        #global-loading-indicator.htmx-request {
            opacity: 1;
        }
    </style>
</head>
<body class="hide-right font-sans" hx-indicator="#global-loading-indicator" hx-push-url="true" hx-ext="alpine-morph">
    --SlotContent--
</body>
</html>
"""


class BaseLayout(Component):
    """The root HTML document layout with necessary boilerplate, styles, and scripts."""
    def __init__(self, **kwargs):
        super().__init__(**{**kwargs, "uid": "base"})

    def render_html(self, **kwargs) -> str:
        return base_template.replace(
            "--SlotContent--",
            "\n".join([child.render(**kwargs) for child in self.children]),
        ).replace("--SlotTitle--", settings.PWA_APP_NAME)


class TopbarLayout(Component):
    """A structural layout providing a persistent top header bar."""
    def __init__(self, **kwargs):
        super().__init__(**{**kwargs, "uid": "topbar"})
        self.topbar_buttons = Row(
            uid="topbar-buttons",
            classes="flex items-center",
            children=[
                Button(
                    uid="topbar-theme-btn",
                    icon="sun",
                    icon_alt="moon",
                    icon_condition="theme === 'light'",
                    onclick="toggleTheme()",
                    classes="btn-sm btn-square btn-outline",
                ),
                Button(
                    uid="topbar-apps-btn",
                    url="{% url 'apps' %}",
                    target="#app-layout",
                    icon="squares-2x2",
                    classes="btn-sm btn-square btn-neutral",
                ),
                Button(
                    uid="topbar-logout-btn",
                    url="{% url 'users:logout' %}",
                    method="post",
                    icon="arrow-right-start-on-rectangle",
                    classes="btn-sm btn-square btn-error",
                ),
            ],
        )

    def render_html(self, **kwargs) -> str:
        buttons_html = self.topbar_buttons.build().render(**kwargs)
        children_html = "\n".join([child.render(**kwargs) for child in self.children])

        return f"""
<div
    x-data="{{
        theme: localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'),
        toggleTheme() {{
            this.theme = this.theme === 'light' ? 'dark' : 'light';
            document.documentElement.setAttribute('data-theme', this.theme);
            localStorage.setItem('theme', this.theme);
        }},
        init() {{
            document.documentElement.setAttribute('data-theme', this.theme);
        }}
    }}"
    class="grid h-[100dvh] grid-rows-[auto_1fr] bg-base-100 font-sans"
>
  <header class="flex items-center justify-end gap-1 bg-base-300 px-4 py-2 border-b border-base-300 z-20">
            {buttons_html}
            <progress class="progress w-full fixed top-0 left-0 h-1 z-50" id="global-loading-indicator"></progress>
  </header>

  <div class="grid relative">
        {children_html}
  </div>
</div>
"""


# Messages needs to move to a place where it can be triggered anytime
sidebar_template = """
<div id="--UID--" class="size-full" x-data="{
        showLeft: window.innerWidth >= 768,
        isMobile: window.innerWidth < 768,
}">
    <div class="grid h-full transition-[grid-template-columns] duration-[400ms] ease-in"
         :class="isMobile ? 'grid-cols-1' : (showLeft ? 'grid-cols-[250px_1fr]' : 'grid-cols-[0px_1fr]')">
      <div x-show="isMobile && showLeft"
           x-transition.opacity
           @click="showLeft = false"
           class="absolute inset-0 bg-black/50 z-20"></div>
       <aside class="bg-base-100 border-r border-base-300 overflow-hidden"
              :class="isMobile ? 'absolute inset-y-0 left-0 z-50 shadow-xl transition-transform duration-300' : ''"
             :style="isMobile ? (showLeft ? 'transform: translateX(0)' : 'transform: translateX(-100%)') : ''">
        <div class="h-full overflow-y-auto w-[250px] bg-base-100 p-2">
            <div class="m-2 border-b border-base-300 pb-4">
                --SlotEnvironment--
            </div>
            --SlotSidebar--
        </div>
      </aside>
      <main class="overflow-y-auto p-4 relative h-full">
        <button @click="showLeft = !showLeft" class="btn btn-sm btn-square mb-2">
            {% heroicon_mini "bars-3" %}
        </button>

        {% if messages %}
        <div class="messages mb-4">
            {% for message in messages %}
            <div class="alert {% if message.tags == 'error' %}alert-error{% elif message.tags == 'success' %}alert-success{% else %}alert-info{% endif %} shadow-lg mb-2">
                <div class="flex-1">
                    <span class="font-semibold">{% if message.tags == 'error' %}Error:{% elif message.tags == 'success' %}Success:{% else %}Info:{% endif %}</span>
                    {{ message }}
                </div>
            </div>
            {% endfor %}
        </div>
        {% endif %}

        --SlotContent--
      </main>
    </div>
</div>
"""


class SidebarLayout(Component):
    """A responsive layout with a collapsible sidebar and main content area."""
    def __init__(self, sidebar: List[Component], **kwargs):
        super().__init__(**{**kwargs, "uid": "app-layout"})
        self.main_content = self.children or []
        self.sidebar = sidebar or []

    def render_html(self, **kwargs) -> str:
        rendered_html =  (
            sidebar_template.replace(
                "--UID--",
                self.uid,
            )
            .replace(
                "--SlotSidebar--",
                "\n".join([child.render(**kwargs) for child in self.sidebar]),
            )
            .replace(
                "--SlotContent--",
                "\n".join([child.render(**kwargs) for child in self.main_content]),
            )
            
        )

        try:
            from lariv.registry import EnvironmentRegistry
            rendered_html = rendered_html.replace(
                            "--SlotEnvironment--",
                            Environment(uid=f"{self.uid}_environment", registry=EnvironmentRegistry).render(**kwargs),
            )
        except ImportError:
            pass

        return rendered_html


card_template = """
<div class="min-h-screen flex items-center justify-center bg-base-200">
    <progress class="progress w-full fixed top-0 left-0 h-1 z-50" id="global-loading-indicator"></progress>
    <div class="card shadow-xl">
        <div class="card-body">
            --SlotContent--
        </div>
    </div>
</div>
"""


class CardLayout(Component):
    """A centered card layout generally used for authentication pages."""
    def __init__(self, **kwargs):
        super().__init__(
            **{**kwargs, "uid": "card"},
        )

    def render_html(self, **kwargs) -> str:
        return card_template.replace(
            "--SlotContent--",
            "\n".join([child.render(**kwargs) for child in self.children]),
        )


class ScaffoldLayout(Component):
    """The standard application scaffolding combining Base, Topbar, and Sidebar layouts."""
    def __init__(
        self,
        sidebar_children: List[Component] | None = None,
        **kwargs,
    ):
        layout = BaseLayout(
            children=[
                TopbarLayout(
                    children=[
                        SidebarLayout(
                            children=kwargs["children"],
                            sidebar=sidebar_children,
                        ),
                    ],
                )
            ],
        )
        super().__init__(**{**kwargs, "children": [layout]})
        self.main_content = kwargs["children"] or []
        self.sidebar_children = sidebar_children or []

    def render_html(self, **kwargs) -> str:
        return "\n".join(child.render(**kwargs) for child in self.children)


# Simple layout template without sidebar (for apps page, etc.)
simple_layout_template = """
<div id="app-layout" class="size-full overflow-y-auto p-4">
    --SlotContent--
</div>
"""


class SimpleLayout(Component):
    """Layout without sidebar, just content area."""

    def __init__(self, **kwargs):
        super().__init__(**{**kwargs, "uid": "app-layout"})

    def render_html(self, **kwargs) -> str:
        content = "\n".join([child.render(**kwargs) for child in self.children])
        return simple_layout_template.replace("--SlotContent--", content)


class SimpleScaffoldLayout(Component):
    """Scaffold without sidebar - uses base + topbar + simple layout."""

    def __init__(self, children: List[Component], **kwargs):
        layout = BaseLayout(
            children=[
                TopbarLayout(
                    children=[
                        SimpleLayout(
                            children=children,
                        ),
                    ],
                )
            ],
        )
        super().__init__(**kwargs, children=[layout])
        self.main_content = children or []

    def render_html(self, **kwargs) -> str:
        return "\n".join(child.render(**kwargs) for child in self.children)


class AuthScaffoldLayout(Component):
    """Scaffold for auth pages (login, signup) - uses base + card without topbar."""

    def __init__(self, children: List[Component], **kwargs):
        layout = BaseLayout(
            children=[
                CardLayout(
                    children=children,
                ),
            ],
        )
        super().__init__(**kwargs, children=[layout])
        self.main_content = children or []

    def render_html(self, **kwargs) -> str:
        return "\n".join(child.render(**kwargs) for child in self.children)
