---
import '../styles/global.css';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import SubscriptionPopup from '../components/SubscriptionPopup.astro';
import BackToTop from '../components/interactive/BackToTop.svelte';
import { api, DEFAULT_SITE_SETTINGS } from '../lib/api/client';
import { getI18n, LOCALE_COOKIE_NAME, SUPPORTED_LOCALES } from '../lib/i18n';
import type { SiteSettings } from '../lib/types';

interface Props {
  title?: string;
  description?: string;
  siteSettings?: SiteSettings;
  canonical?: string;
  noindex?: boolean;
  ogImage?: string;
  ogType?: string;
  twitterCard?: 'summary' | 'summary_large_image';
  jsonLd?: Record<string, unknown> | Array<Record<string, unknown>>;
}

const props = Astro.props;
const { locale, messages } = getI18n(Astro);

let siteSettings = props.siteSettings ?? DEFAULT_SITE_SETTINGS;

if (!props.siteSettings) {
  try {
    siteSettings = await api.getSiteSettings();
  } catch (error) {
    console.error('Failed to load site settings:', error);
  }
}

const title = props.title || siteSettings.siteTitle;
const description = props.description || siteSettings.siteDescription;
const siteUrl = siteSettings.siteUrl.replace(/\/$/, '');
const defaultCanonical = `${siteUrl}${Astro.url.pathname}`;
const canonical = props.canonical
  ? /^https?:\/\//i.test(props.canonical)
    ? props.canonical
    : `${siteUrl}${props.canonical.startsWith('/') ? props.canonical : `/${props.canonical}`}`
  : defaultCanonical;
const resolvedOgImage = props.ogImage || siteSettings.seo.defaultOgImage;
const ogImage = resolvedOgImage
  ? /^https?:\/\//i.test(resolvedOgImage)
    ? resolvedOgImage
    : `${siteUrl}${resolvedOgImage.startsWith('/') ? resolvedOgImage : `/${resolvedOgImage}`}`
  : undefined;
const ogType = props.ogType || 'website';
const twitterCard = props.twitterCard || (ogImage ? 'summary_large_image' : 'summary');
const defaultJsonLdObjects = [
  {
    '@context': 'https://schema.org',
    '@type': 'WebSite',
    name: siteSettings.siteName,
    alternateName: siteSettings.siteShortName,
    url: siteUrl,
    description,
    inLanguage: locale,
    potentialAction: {
      '@type': 'SearchAction',
      target: `${siteUrl}/search?q={search_term_string}`,
      'query-input': 'required name=search_term_string',
    },
  },
  {
    '@context': 'https://schema.org',
    '@type': 'Organization',
    name: siteSettings.siteName,
    alternateName: siteSettings.siteShortName,
    url: siteUrl,
    description,
    logo: siteSettings.ownerAvatarUrl || ogImage,
    sameAs: [
      siteSettings.social.github,
      siteSettings.social.twitter,
    ].filter(Boolean),
  },
  {
    '@context': 'https://schema.org',
    '@type': 'Person',
    name: siteSettings.ownerName,
    url: siteUrl,
    image: siteSettings.ownerAvatarUrl || undefined,
    jobTitle: siteSettings.ownerTitle,
    description: siteSettings.ownerBio || description,
    sameAs: [
      siteSettings.social.github,
      siteSettings.social.twitter,
    ].filter(Boolean),
  },
].filter((item) => item.name || item.url);
const mergedJsonLdObjects = [
  ...defaultJsonLdObjects,
  ...(props.jsonLd === undefined
    ? []
    : Array.isArray(props.jsonLd)
      ? props.jsonLd
      : [props.jsonLd]),
];
const jsonLd = mergedJsonLdObjects.length ? JSON.stringify(mergedJsonLdObjects) : undefined;
const i18nPayload = JSON.stringify({ locale, messages });
---

<!DOCTYPE html>
<html lang={locale} data-locale={locale}>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content={description} />
    <meta name="author" content={siteSettings.ownerName} />
    <meta name="robots" content={props.noindex ? 'noindex, nofollow' : 'index, follow'} />
    <link rel="canonical" href={canonical} />
    <meta property="og:locale" content={locale} />
    <meta property="og:site_name" content={siteSettings.siteName} />
    <meta property="og:title" content={title} />
    <meta property="og:description" content={description} />
    <meta property="og:type" content={ogType} />
    <meta property="og:url" content={canonical} />
    <meta name="twitter:card" content={twitterCard} />
    <meta name="twitter:title" content={title} />
    <meta name="twitter:description" content={description} />
    {siteSettings.seo.defaultTwitterHandle && (
      <meta name="twitter:site" content={siteSettings.seo.defaultTwitterHandle} />
    )}
    {siteSettings.seo.defaultTwitterHandle && (
      <meta name="twitter:creator" content={siteSettings.seo.defaultTwitterHandle} />
    )}
    {ogImage && <meta property="og:image" content={ogImage} />}
    {ogImage && <meta name="twitter:image" content={ogImage} />}
    <link
      rel="alternate"
      type="application/rss+xml"
      title={`${siteSettings.siteName} RSS`}
      href={`${siteUrl}/rss.xml`}
    />
    <link
      rel="alternate"
      type="text/plain"
      title={`${siteSettings.siteName} llms.txt`}
      href={`${siteUrl}/llms.txt`}
    />
    <link
      rel="alternate"
      type="text/plain"
      title={`${siteSettings.siteName} llms-full.txt`}
      href={`${siteUrl}/llms-full.txt`}
    />
    <link rel="icon" href="/favicon.ico" />
    <title>{title}</title>
    {jsonLd && <script is:inline type="application/ld+json" set:html={jsonLd}></script>}
    <slot name="head" />

    <style is:inline>
      :root {
        --primary: #2563eb;
        --primary-rgb: 37 99 235;
        --primary-light: rgba(37 99 235 / 0.14);
        --primary-dark: #1d4ed8;
        --secondary: #f97316;
        --secondary-rgb: 249 115 22;
        --secondary-light: rgba(249 115 22 / 0.14);
        --bg: #eef3f8;
        --bg-rgb: 238 243 248;
        --bg-secondary: #e2e8f0;
        --bg-tertiary: #cbd5e1;
        --terminal-bg: #f8fbff;
        --text: #0f172a;
        --text-rgb: 15 23 42;
        --text-secondary: #475569;
        --text-tertiary: #5f6f86;
        --terminal-text: #0f172a;
        --title-color: #0f172a;
        --button-text: #0f172a;
        --border-color: #d6e0ea;
        --border-color-rgb: 214 224 234;
        --terminal-border: #d6e0ea;
        --tag-bg: #edf3f8;
        --tag-text: #0f172a;
        --header-bg: rgba(244 248 252 / 0.92);
        --code-bg: #eef3f8;
        --success: #10b981;
        --success-rgb: 16 185 129;
        --success-light: #d1fae5;
        --success-dark: #065f46;
        --warning: #f59e0b;
        --warning-rgb: 245 158 11;
        --warning-light: #fef3c7;
        --warning-dark: #92400e;
        --danger: #ef4444;
        --danger-rgb: 239 68 68;
        --danger-light: #fee2e2;
        --danger-dark: #991b1b;
        --gray-light: #f3f4f6;
        --gray-dark: #374151;
        --btn-close: #ff5f56;
        --btn-minimize: #ffbd2e;
        --btn-expand: #27c93f;
      }

      html.dark {
        --primary: #00ff9d;
        --primary-rgb: 0 255 157;
        --primary-light: #00ff9d33;
        --primary-dark: #00b8ff;
        --secondary: #00b8ff;
        --secondary-rgb: 0 184 255;
        --secondary-light: #00b8ff33;
        --bg: #0a0e17;
        --bg-rgb: 10 14 23;
        --bg-secondary: #161b22;
        --bg-tertiary: #21262d;
        --terminal-bg: #0d1117;
        --text: #e6e6e6;
        --text-rgb: 230 230 230;
        --text-secondary: #d1d5db;
        --text-tertiary: #9ca3af;
        --terminal-text: #e6e6e6;
        --title-color: #ffffff;
        --button-text: #e6e6e6;
        --border-color: rgba(255 255 255 / 0.1);
        --border-color-rgb: 255 255 255;
        --terminal-border: rgba(255 255 255 / 0.1);
        --tag-bg: #161b22;
        --tag-text: #e6e6e6;
        --header-bg: rgba(22 27 34 / 0.9);
        --code-bg: #161b22;
        --success-light: #064e3b;
        --success-dark: #d1fae5;
        --warning-light: #78350f;
        --warning-dark: #fef3c7;
        --danger-light: #7f1d1d;
        --danger-dark: #fee2e2;
        --gray-light: #1f2937;
        --gray-dark: #e5e7eb;
      }

      @media (prefers-color-scheme: dark) {
        :root:not(.light):not(.dark) {
          --primary: #00ff9d;
          --primary-rgb: 0 255 157;
          --primary-light: #00ff9d33;
          --primary-dark: #00b8ff;
          --secondary: #00b8ff;
          --secondary-rgb: 0 184 255;
          --secondary-light: #00b8ff33;
          --bg: #0a0e17;
          --bg-rgb: 10 14 23;
          --bg-secondary: #161b22;
          --bg-tertiary: #21262d;
          --terminal-bg: #0d1117;
          --text: #e6e6e6;
          --text-rgb: 230 230 230;
          --text-secondary: #d1d5db;
          --text-tertiary: #9ca3af;
          --terminal-text: #e6e6e6;
          --title-color: #ffffff;
          --button-text: #e6e6e6;
          --border-color: rgba(255 255 255 / 0.1);
          --border-color-rgb: 255 255 255;
          --terminal-border: rgba(255 255 255 / 0.1);
          --tag-bg: #161b22;
          --tag-text: #e6e6e6;
          --header-bg: rgba(22 27 34 / 0.9);
          --code-bg: #161b22;
          --success-light: #064e3b;
          --success-dark: #d1fae5;
          --warning-light: #78350f;
          --warning-dark: #fef3c7;
          --danger-light: #7f1d1d;
          --danger-dark: #fee2e2;
          --gray-light: #1f2937;
          --gray-dark: #e5e7eb;
        }
      }

      body {
        background-color: var(--bg);
        color: var(--text);
      }
    </style>

    <script is:inline define:vars={{ i18nPayload, locale, localeCookieName: LOCALE_COOKIE_NAME, supportedLocales: SUPPORTED_LOCALES }}>
      window.__TERMI_I18N__ = JSON.parse(i18nPayload);
      window.__termiTranslate = function(key, params = {}) {
        const payload = window.__TERMI_I18N__ || { messages: {} };
        const template = key.split('.').reduce((current, segment) => {
          if (!current || typeof current !== 'object') {
            return undefined;
          }
          return current[segment];
        }, payload.messages);

        if (typeof template !== 'string') {
          return key;
        }

        return template.replace(/\{(\w+)\}/g, (_, name) => String(params[name] ?? ''));
      };

      (function() {
        document.documentElement.lang = locale;
        document.documentElement.dataset.locale = locale;
        localStorage.setItem('locale', locale);
        document.cookie = `${localeCookieName}=${encodeURIComponent(locale)};path=/;max-age=31536000;samesite=lax`;
      })();
    </script>

    <script is:inline>
      (function() {
        function renderPrompt(el, nextCommand, typingMode) {
          const id = el.getAttribute('data-id');
          const cmdEl = document.getElementById('cmd-' + id);
          const cursorEl = document.getElementById('cursor-' + id);

          if (!cmdEl || !cursorEl) return;

          const command = String(nextCommand || '');
          const typing = typingMode === true || typingMode === 'true';
          const renderSeq = String((Number(el.getAttribute('data-render-seq') || '0') || 0) + 1);

          el.setAttribute('data-command', command);
          el.setAttribute('data-render-seq', renderSeq);
          cmdEl.textContent = '';
          cursorEl.style.animation = 'none';
          cursorEl.style.opacity = '1';

          if (!typing) {
            cmdEl.textContent = command;
            cursorEl.style.animation = 'blink 1s infinite';
            return;
          }

          let index = 0;

          function typeChar() {
            if (el.getAttribute('data-render-seq') !== renderSeq) {
              return;
            }

            if (index < command.length) {
              cmdEl.textContent += command.charAt(index);
              index += 1;
              setTimeout(typeChar, 42 + Math.random() * 22);
            } else {
              cursorEl.style.animation = 'blink 1s infinite';
            }
          }

          setTimeout(typeChar, 120);
        }

        if (!window.__termiCommandPrompt) {
          window.__termiCommandPrompt = {
            set(promptId, command, options = {}) {
              if (!promptId) return;
              const el = document.querySelector(`[data-prompt-id="${promptId}"]`);
              if (!el) return;
              renderPrompt(el, command, options.typing ?? true);
            }
          };
        }

        function mountPrompts() {
          const prompts = document.querySelectorAll('[data-command]:not([data-command-mounted])');

          prompts.forEach(function(el) {
            el.setAttribute('data-command-mounted', 'true');
            renderPrompt(el, el.getAttribute('data-command') || '', el.getAttribute('data-typing') === 'true');
          });
        }

        if (document.readyState === 'loading') {
          document.addEventListener('DOMContentLoaded', mountPrompts, { once: true });
        } else {
          mountPrompts();
        }
      })();
    </script>

    <script is:inline>
      (function() {
        const STORAGE_KEY = 'theme';
        const VALID_THEMES = new Set(['light', 'dark', 'system']);
        const root = document.documentElement;
        const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

        function readThemeMode() {
          try {
            const savedMode = localStorage.getItem(STORAGE_KEY);
            return VALID_THEMES.has(savedMode) ? savedMode : 'system';
          } catch {
            return 'system';
          }
        }

        function resolveTheme(mode) {
          return mode === 'dark' || (mode === 'system' && mediaQuery.matches) ? 'dark' : 'light';
        }

        function applyTheme(mode, options = {}) {
          const { persist = false, notify = true } = options;
          const safeMode = VALID_THEMES.has(mode) ? mode : 'system';
          const resolvedTheme = resolveTheme(safeMode);

          root.dataset.themeMode = safeMode;
          root.dataset.themeResolved = resolvedTheme;
          root.classList.toggle('dark', resolvedTheme === 'dark');
          root.classList.toggle('light', resolvedTheme === 'light');

          if (persist) {
            try {
              localStorage.setItem(STORAGE_KEY, safeMode);
            } catch {
              // Ignore storage write failures and keep the UI responsive.
            }
          }

          if (notify) {
            window.dispatchEvent(
              new CustomEvent('termi:theme-change', {
                detail: { mode: safeMode, resolved: resolvedTheme },
              })
            );
          }

          return { mode: safeMode, resolved: resolvedTheme };
        }

        function syncThemeFromStorage(notify = false) {
          return applyTheme(readThemeMode(), { notify });
        }

        window.__termiTheme = {
          getMode: readThemeMode,
          resolveTheme,
          applyTheme(mode) {
            return applyTheme(mode, { persist: true, notify: true });
          },
          syncTheme() {
            return syncThemeFromStorage(true);
          },
        };

        syncThemeFromStorage(false);

        if (!window.__termiThemeMediaBound) {
          const handleSystemThemeChange = () => {
            if (readThemeMode() === 'system') {
              syncThemeFromStorage(true);
            }
          };

          if (typeof mediaQuery.addEventListener === 'function') {
            mediaQuery.addEventListener('change', handleSystemThemeChange);
          } else {
            mediaQuery.onchange = handleSystemThemeChange;
          }

          window.__termiThemeMediaBound = true;
        }
      })();
    </script>

    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
    />
    <noscript>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />
    </noscript>
    <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=JetBrains+Mono:wght@400;700&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap"
      rel="stylesheet"
    >
    <noscript>
      <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
    </noscript>
  </head>
  <body class="min-h-screen bg-[var(--bg)] text-[var(--text)] font-sans antialiased">
    <div class="relative min-h-screen flex flex-col">
      <div class="fixed inset-0 -z-10 bg-[var(--bg)]"></div>
      <div
        class="fixed inset-0 -z-10 opacity-70"
        style="background:
          radial-gradient(circle at top left, rgba(var(--primary-rgb), 0.06), transparent 30%),
          radial-gradient(circle at top right, rgba(var(--secondary-rgb), 0.05), transparent 26%),
          linear-gradient(180deg, color-mix(in oklab, var(--terminal-bg) 34%, transparent), transparent 48%);"
      ></div>
      <div
        class="fixed inset-0 -z-10 opacity-30"
        style="background-image:
          linear-gradient(rgba(var(--primary-rgb), 0.035) 1px, transparent 1px),
          linear-gradient(90deg, rgba(var(--primary-rgb), 0.03) 1px, transparent 1px);
          background-size: 100% 18px, 18px 100%;"
      ></div>

      <Header siteSettings={siteSettings} />

      <main class="flex-1 w-full pb-[calc(5.5rem+env(safe-area-inset-bottom))] lg:pb-0">
        <slot />
      </main>

      <Footer siteSettings={siteSettings} />
      <SubscriptionPopup siteSettings={siteSettings} requestUrl={Astro.url} />
      <BackToTop client:load />
    </div>
  </body>
</html>

<style>
  :global(body) {
    font-family: 'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  }

  :global(code, pre) {
    font-family: 'JetBrains Mono', 'Fira Code', monospace;
  }
</style>
