"""Vite plugin for FastHTML - automatic bundling, minifcation and script injection of static assets"""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.

# %% auto #0
__all__ = ['setup_files', 'add_vite']

# %% ../nbs/00_core.ipynb #943022ba
import subprocess, shutil
from fasthtml.common import *
from fastcore.utils import *

# %% ../nbs/00_core.ipynb #7f372c6c
# TODO: move this to github and pull from there
_monster_temp = {'vite.config.js': '''import franken from "franken-ui/plugin-vite";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    franken({
      layer: true,
      preflight: false,
      layerExceptions: ["chart"],
    }),
    tailwindcss(),
  ],
  css: {
    transformer: "lightningcss",
  },
  build: {
    cssMinify: "lightningcss",
    manifest: true,
    rollupOptions: {
      input: "src/index.js",
    },
    outDir: './dist',
    emptyOutDir: true
  },
});''',
        
        'package.json': '''{
  "name": "fastvite",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "lightningcss": "^1.30.2",
    "vite": "^7.1.10"
  },
  "dependencies": {
    "@tailwindcss/vite": "^4.1.14",
    "franken-ui": "^2.1.0"
  }
}''',
        
        'src/style.css': '''@import "tailwindcss";
@import "franken-ui/css/franken-ui.css";
@source "../../";

@theme {
  --color-background: oklch(from hsl(var(--background)) l c h);
  --color-foreground: oklch(from hsl(var(--foreground)) l c h);
  --color-muted: oklch(from hsl(var(--muted)) l c h);
  --color-muted-foreground: oklch(from hsl(var(--muted-foreground)) l c h);
  --color-card: oklch(from hsl(var(--card)) l c h);
  --color-card-foreground: oklch(from hsl(var(--card-foreground)) l c h);
  --color-popover: oklch(from hsl(var(--popover)) l c h);
  --color-popover-foreground: oklch(from hsl(var(--popover-foreground)) l c h);
  --color-border: oklch(from hsl(var(--border)) l c h / var(--border-alpha, 1));
  --color-input: oklch(from hsl(var(--input)) l c h / var(--input-alpha, 1));
  --color-primary: oklch(from hsl(var(--primary)) l c h);
  --color-primary-foreground: oklch(from hsl(var(--primary-foreground)) l c h);
  --color-secondary: oklch(from hsl(var(--secondary)) l c h);
  --color-secondary-foreground: oklch(from hsl(var(--secondary-foreground)) l c h);
  --color-accent: oklch(from hsl(var(--accent)) l c h);
  --color-accent-foreground: oklch(from hsl(var(--accent-foreground)) l c h);
  --color-destructive: oklch(from hsl(var(--destructive)) l c h / var(--destructive-alpha, 1));
  --color-destructive-foreground: oklch(from hsl(var(--destructive-foreground)) l c h);
  --color-ring: oklch(from hsl(var(--ring)) l c h);
}

@layer base {
  button,
  [role="button"] {
    cursor: pointer;
  }
  body {
    @apply antialiased min-h-screen bg-background text-foreground box-border;
  }
}''',
         'src/index.js': '''import "vite/modulepreload-polyfill";
import "./style.css";
import "franken-ui/js/core.iife";
import "franken-ui/js/icon.iife";'''
}

# %% ../nbs/00_core.ipynb #ea10cdd7
_basecoat_temp = {'vite.config.js': '''import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [tailwindcss()],
  css: {
    transformer: "lightningcss",
  },
  build: {
    cssMinify: "lightningcss",
    manifest: true,
    rollupOptions: {
      input: "src/index.js",
    },
    outDir: './dist',
    emptyOutDir: true
  },
});''',
        
        'package.json': '''{
  "name": "fastvite",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "lightningcss": "^1.30.2",
    "vite": "^7.1.10"
  },
  "dependencies": {
    "@tailwindcss/vite": "^4.1.14",
    "basecoat-css": "^0.3.2"
  }
}''',
        
        'src/style.css': '''@import "tailwindcss";
@import "basecoat-css";
@source "../../";

@layer base {
  body {
    @apply antialiased min-h-screen box-border;
  }
}''',
         'src/index.js': '''import "vite/modulepreload-polyfill";
import "./style.css";
import "basecoat-css/all";'''
}

# %% ../nbs/00_core.ipynb #f74565d6
def setup_files(root_dir, entry_file, use_monster=True):
    "Setup Vite files in project, with FastHTML configuration"
    n_files = 0
    templ = _monster_temp if use_monster else _basecoat_temp
    for path,ctx in templ.items():
        path = Path(root_dir)/path
        path.parent.mkdir(parents=True, exist_ok=True)
        if not path.exists():
            path.write_text(ctx)
            print(f"Created: {path}")
            n_files += 1
    subprocess.run("pybun install", cwd=root_dir, shell=True, check=True)

# %% ../nbs/00_core.ipynb #50f9ce80
def _mk_scripts(dirname, entry_file):
    "Create necessary vite headers and inject into app"
    manifest = loads(Path(dirname).joinpath('dist/.vite/manifest.json').read_text())
    entry = f'src/{entry_file}'
    def _imported_chunks(name, seen=None):
        if seen is None: seen = set()
        chunk = manifest[name]
        for imp in chunk.get('imports', []):
            if imp in seen: continue
            seen.add(imp)
            yield from _imported_chunks(imp, seen)
            yield manifest[imp]
    
    def _url(path): return f"/{dirname}/{path}"
    entry_chunk = manifest[entry]
    imported = list(_imported_chunks(entry))
    
    hdrs = [Link(rel='stylesheet', href=_url(css)) 
            for css in entry_chunk.get('css', [])]
    hdrs += [Link(rel='stylesheet', href=_url(css))
             for chunk in imported for css in chunk.get('css', [])]
    hdrs.append(Script(type='module', src=_url(entry_chunk['file'])))
    hdrs += [Link(rel='modulepreload', href=_url(chunk['file']))
             for chunk in imported]
    
    return hdrs

# %% ../nbs/00_core.ipynb #a204e74b
_monster_head = [
    Script("""
    const htmlElement = document.documentElement;

    const __FRANKEN__ = JSON.parse(
    localStorage.getItem("__FRANKEN__") || "{}",
    );

    if (
    __FRANKEN__.mode === "dark" ||
    (!__FRANKEN__.mode &&
        window.matchMedia("(prefers-color-scheme: dark)").matches)
    ) {
    htmlElement.classList.add("dark");
    } else {
    htmlElement.classList.remove("dark");
    }

    htmlElement.classList.add(__FRANKEN__.theme || "uk-theme-zinc");
    htmlElement.classList.add(__FRANKEN__.radii || "uk-radii-md");
    htmlElement.classList.add(__FRANKEN__.shadows || "uk-shadows-md");
    htmlElement.classList.add(__FRANKEN__.font || "uk-font-sm");""")
]

# %% ../nbs/00_core.ipynb #829ae52e
def add_vite(app:FastHTML, entry_file='index.js', dirname='frontend', use_monster=True, directory='.'):
    "Configure app to use vite"
    pwd = Path(directory)/dirname
    outdir = pwd/'dist'
    if not outdir.exists(): outdir.mkdir(parents=True, exist_ok=True)
    app.mount(f'/{dirname}', app=StaticNoCache(directory=pwd/'dist'), name=dirname)
    async def _run(o):
        # 1. Setup files & install with npm
        setup_files(root_dir=dirname, entry_file=entry_file, use_monster=use_monster)

        # 2. Build compiled assets
        subprocess.run('pybun run build', cwd=dirname, shell=True, check=True)

        # 3. Splice script/link injections into headers
        def_hdrs = [*_mk_scripts(dirname=dirname, entry_file=entry_file)]
        #if use_monster: def_hdrs.append(_monster_head)
        app.hdrs[0:0] = def_hdrs

        # Run old lifespan (if set)
        if app.lifespan:
            async for _ in app.lifespan(o): yield
        else: yield
    app.set_lifespan(_run)
