import '../css/app.css';
import './bootstrap';

import { ConfirmProvider } from '@/Components/ConfirmDialog';
import { GorevModalProvider } from '@/Components/GorevModalProvider';
import { ModulModalProvider } from '@/Components/ModulModalProvider';
import { ProjeModalProvider } from '@/Components/ProjeModalProvider';
import YuklemeGostergesi from '@/Components/YuklemeGostergesi';
import { YuklemeProvider } from '@/Components/YuklemeProvider';
import { slashEkle } from '@/lib/url';
import { createInertiaApp, router } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ReactNode } from 'react';
import { createRoot } from 'react-dom/client';

// Sistem ayarındaki app_name'i runtime'da app.blade.php'deki <meta name="app-name"> üzerinden oku.
const metaAppName = typeof document !== 'undefined'
    ? document.querySelector('meta[name="app-name"]')?.getAttribute('content')
    : null;
const appName = metaAppName || import.meta.env.VITE_APP_NAME || 'Cari Takip';

/*
 * KANONİK ADRES — sayfa adresleri sonda "/" ile biter.
 *
 * Sunucuda SonaSlashEkle middleware'i bunu uygular, ancak Inertia istekleri
 * X-Inertia başlığı taşıdığı için middleware onları yönlendirmez. Yönlendirilseydi
 * de her gezinme fazladan bir tur atardı. Bu yüzden kural istemcide, istek daha
 * gönderilmeden uygulanır: hem adres çubuğu tutarlı kalır hem ekstra istek olmaz.
 *
 * router.visit tüm gezinme yollarının (Link, router.get/post/..., manual visit)
 * ortak geçididir; tek noktadan yamalamak yeterlidir.
 */
const orijinalVisit = router.visit.bind(router);
router.visit = ((url: any, options?: any) => {
    // YALNIZCA GET: POST/PUT/PATCH/DELETE adresleri olduğu gibi bırakılır. Bu adresler
    // eylem uçlarıdır (ör. /musteri-sozlesmeleri/toplu-sil), kanonik sayfa adresi değildir;
    // dokunmamak hem gereksiz farklılığı hem de olası eşleşme sürprizlerini önler.
    const yontem = String(options?.method ?? 'get').toLowerCase();
    if (yontem !== 'get') return orijinalVisit(url, options);

    if (typeof url === 'string') return orijinalVisit(slashEkle(url), options);
    // URL nesnesi — pathname üzerinde çalışılır
    if (url && typeof url === 'object' && 'pathname' in url) {
        try {
            const kopya = new URL(url.toString());
            kopya.pathname = slashEkle(kopya.pathname);
            return orijinalVisit(kopya as any, options);
        } catch {
            /* çözümlenemezse olduğu gibi bırak */
        }
    }
    return orijinalVisit(url, options);
}) as typeof router.visit;

/**
 * Inertia Layout — her sayfa Inertia App ağacı INSIDE'ında bu wrapper ile sarılır.
 * Providers App içinde olmak zorunda, çünkü içerideki global modal'lar usePage() kullanır.
 */
const RootLayout = ({ children }: { children: ReactNode }) => (
    <ConfirmProvider>
        {/*
         * YuklemeProvider TÜM MODAL SAĞLAYICILARINDAN DIŞTA olmalı.
         *
         * Modal sağlayıcıları kendi modallarını `{children}`'ın KARDEŞİ olarak
         * mount eder (ör. ModulModalProvider → CariFormModal). YuklemeProvider
         * içeride kalırsa o modallar sağlayıcının DIŞINDA kalır; içlerindeki
         * FileManager `useYukleme()` çağırdığında "provider içinde kullanılmalı"
         * hatası verir ve modal hiç açılmaz. Dışta olması bu sınıfı tümden kapatır.
         *
         * Ters bağımlılık yok: YuklemeProvider hiçbir modal context'ini kullanmaz.
         */}
        <YuklemeProvider>
            {/*
             * SIRALAMA ÖNEMLİ — ModulModalProvider modal sağlayıcıları arasında EN DIŞTA.
             *
             * GorevFormModal ve ProjeFormModal, kendi provider'ları tarafından mount edilir.
             * Bu modallar içindeki AsyncSelect/Select'lerin hızlı-ekleme "+" butonu
             * useModulModalOptional() ile ModulModalContext'e erişir. ModulModalProvider
             * içeride kalırsa bu modallar context'in DIŞINDA kalır ve "+" butonu hiç görünmez.
             *
             * ModulModalProvider'ın mount ettiği modallar (Cari/Musteri/Urun/...) ise
             * useGorevModal/useProjeModal kullanmaz — bu yüzden dışta olması sorun çıkarmaz.
             */}
            <ModulModalProvider>
                <GorevModalProvider>
                    <ProjeModalProvider>
                        {children}
                    </ProjeModalProvider>
                </GorevModalProvider>
            </ModulModalProvider>

            {/* Her sayfada sağ altta sabit; iş yokken hiçbir şey çizmez. */}
            <YuklemeGostergesi />
        </YuklemeProvider>
    </ConfirmProvider>
);

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) => {
        const page: any = resolvePageComponent(
            `./Pages/${name}.tsx`,
            import.meta.glob('./Pages/**/*.tsx'),
        );
        return page.then((mod: any) => {
            const pageComp = mod.default ?? mod;
            // Sayfanın kendi layout'u yoksa kök layout uygula
            if (pageComp && typeof pageComp === 'function' && !(pageComp as any).layout) {
                (pageComp as any).layout = (innerPage: ReactNode) => <RootLayout>{innerPage}</RootLayout>;
            }
            return mod;
        });
    },
    setup({ el, App, props }) {
        const root = createRoot(el);
        root.render(<App {...props} />);
    },
    progress: {
        color: '#3b82f6',
    },
});
