import { createApp, h, defineAsyncComponent, ref, watch } from 'vue';
import { createPinia } from 'pinia';
import axios from 'axios';
import { handleSessionExpired } from './composables/Core/useSessionGuard.js';
import TopHeader from './Pages/Core/Fragments/TopHeader.vue';
import BottomNav from './Pages/Core/Fragments/BottomNav.vue';
import { deepEqual } from './utils/deepEqual';
import { useModal } from './composables/Core/useModal.js';
import { useNavigate, setPageModules } from './composables/Core/useNavigate.js';
import BaseModal from './Components/Core/BaseModal.vue';
import { useNetworkStore } from './stores/network.js';
import { useUserStore } from './stores/user.js';
import { useUIStore } from './stores/ui.js';
import { useAuth } from './composables/Core/useAuth.js';
import { useSessionGuard, startGuard } from './composables/Core/useSessionGuard.js';
import LottiePlayer from './Components/Core/Animations/LottiePlayer.vue';
import AnimatedButton from './Components/Core/Animations/AnimatedButton.vue';
import RouteTransition from './Components/Core/Animations/RouteTransition.vue';



// --- Chunk load error handler (stale hash after rebuild) ---
function handleChunkError(error) {
  const isChunkError =
    error?.message?.includes('Failed to fetch dynamically imported module') ||
    error?.message?.includes('Importing a module script failed') ||
    error?.message?.includes('error loading dynamically imported module') ||
    error?.message?.includes('Loading chunk') ||
    error?.message?.includes('Loading CSS chunk');

  if (isChunkError) {
    // Guard against infinite reload loops — only retry once per URL
    const reloadKey = 'chunk-reload:' + window.location.pathname;
    if (!sessionStorage.getItem(reloadKey)) {
      sessionStorage.setItem(reloadKey, '1');
      console.warn('[ChunkReload] Stale chunk detected, reloading page…');
      window.location.reload();
    } else {
      // Already retried once — clear the flag for next time and log
      sessionStorage.removeItem(reloadKey);
      console.error('[ChunkReload] Reload already attempted, chunk still failing:', error);
    }
  }
}

// Safety-net: catch any unhandled dynamic import rejections globally
window.addEventListener('unhandledrejection', (event) => {
  handleChunkError(event.reason);
});

// Axios request interceptor: ensure POST requests always have at least an empty object as data.
// This prevents 400 Bad Request errors on some production environments (Nginx/WAF) that reject empty POST bodies.
axios.interceptors.request.use(config => {
  if (config.method?.toLowerCase() === 'post' && (config.data === undefined || config.data === null)) {
    config.data = {};
  }
  return config;
});

// Axios interceptor: catch 401/419 from any API call and trigger logout.
// Acts as a last-resort fallback when SSE and polling have both failed.
// Skips guest-probe endpoints that legitimately 401 for unauthenticated visitors,
// and only redirects when we previously had an authenticated session — otherwise
// a guest hitting "/" would be bounced to /login the moment any auth-required
// probe returns 401.
const SESSION_GUARD_SKIP = [
  '/post/loginnow',
  '/get/isloggedin',
  '/sse/stream',
  '/account_settings/details',
  '/get/user/acct-type',
];
axios.interceptors.response.use(
  response => response,
  error => {
    const status = error?.response?.status;
    const url = error?.config?.url ?? '';
    const onLoginPage = window.location.pathname === '/login' || window.location.pathname === '/sp/login';
    const acctType = sessionStorage.getItem('user_acct_type');
    const hadAuthenticatedSession = acctType && acctType !== 'public';

    if (
      (status === 401 || status === 419) &&
      !onLoginPage &&
      hadAuthenticatedSession &&
      !SESSION_GUARD_SKIP.some(s => url.includes(s))
    ) {
      handleSessionExpired();
    }

    return Promise.reject(error);
  }
);

const modal = useModal()

// --- Auto-import all pages (exclude Fragments) ---
const modules = import.meta.glob('./Pages/**/*.vue');


const pages = {};
for (const path in modules) {
  // Exclude global layout/core fragments that aren't standalone pages
  if (path.includes('Core/Fragments')) continue;

  const key = path
    .replace('./Pages/', '')
    .replace('.vue', '')
    .replace(/\//g, '.');
  pages[key] = modules[path];

  // Also add a simplified lowercase version for easier server-side matching
  const simplifiedKey = key.toLowerCase().replace(/\./g, '/');
  pages[simplifiedKey] = modules[path];
}

// Ensure fallback NotFound
if (!pages['Core.NotFound']) {
  pages['Core.NotFound'] = modules['./Pages/Core/NotFound.vue'];
}

// Wire up page modules for prefetching (hover-based eager loading)
setPageModules(pages);

// --- Get initial page from server ---
const el = document.getElementById('main-body');
const initialPage = JSON.parse(el.dataset.page);

const app = createApp({
  setup() {
    const currentPage = ref(initialPage.component);
    const currentProps = ref(initialPage.props || {});
    const loading = ref(false);
    
    // UI Store for global state
    const uiStore = useUIStore();

    // Start polling /get/isloggedin — auto-logout on session expiry
    useSessionGuard();

    const { navigate, reloadPage } = useNavigate({ currentPage, currentProps, loading })

    // Initialize User Store and fetch user data on app load
    const userStore = useUserStore();
    userStore.fetchCurrentUser().then(() => {
      if (userStore.user?.settings) {
        uiStore.syncSettings(userStore.user.settings);
      }
      // Re-attempt session guard once acctType is known. The initial call in
      // setup() bails for guests (no acctType yet); after fetchCurrentUser
      // resolves with a real authenticated user we kick it off here.
      startGuard();
    });

    // Ensure the initial page is in the history state so that back/forward works correctly from the start
    if (typeof window !== 'undefined' && !window.history.state) {
      window.history.replaceState({ page: initialPage.component, props: initialPage.props }, '', window.location.href);
    }

    // Fetch public system settings (branding, disabled pages, etc.)
    // First sync from initial props to avoid flutters
    if (initialPage.props?.systemSettings) {
      uiStore.syncSettings(initialPage.props.systemSettings);
    }
    uiStore.refreshSettings();

    // Start background interval to refresh system settings every 1 minute
    setInterval(() => {
      uiStore.refreshSettings();
    }, 60000);

    // Provide global access to user details
    app.config.globalProperties.$user = userStore;
    app.config.globalProperties.$auth = useAuth();

    // --- AsyncComponent based on currentPage
    const AsyncComponent = ref(
      defineAsyncComponent({
        loader: () => (pages[currentPage.value] || pages['Core.NotFound'])(),
        onError: (error, retry, fail) => {
          handleChunkError(error);
          fail(); // let Vue handle the error if reload didn't trigger
        },
      })
    );

    // Watch page changes and reload async component
    watch(currentPage, (newPage) => {
      // Close any open modals on page change
      modal.close();

      // Reset titles on page change (components can override this in onMounted)
      uiStore.resetPageTitle();

      const mainContent = document.querySelector('.main-content');
      if (mainContent) mainContent.scrollTop = 0;

      AsyncComponent.value = defineAsyncComponent({
        loader: () => (pages[newPage] || pages['Core.NotFound'])(),
        onError: (error, retry, fail) => {
          handleChunkError(error);
          fail();
        },
      });
    });

    // Watch for logo changes and update favicon/apple-touch-icon DOM elements
    watch(() => uiStore.appLogo, (logoUrl) => {
      if (!logoUrl) return;
      document.querySelectorAll('link[rel="shortcut icon"], link[rel="icon"], link[rel="apple-touch-icon"], link[rel="apple-touch-icon-precomposed"]').forEach(link => {
        link.href = logoUrl;
      });
    }, { immediate: true });

    // Watch for dark mode and update body class
    watch(() => uiStore.darkMode, (isDark) => {
      if (isDark) {
        document.body.classList.add('dark-mode');
      } else {
        document.body.classList.remove('dark-mode');
      }
    }, { immediate: true });

    // Watch for full-width mode and update body class
    watch(() => uiStore.isFullWidth, (isFull) => {
      if (isFull) {
        document.body.classList.add('is-full-width');
      } else {
        document.body.classList.remove('is-full-width');
      }
    }, { immediate: true });

    return { currentPage, currentProps, loading, navigate, AsyncComponent, uiStore };
  },

  render() {
    return h('div', { class: ['app-layout', { 'is-full-width': this.uiStore.isFullWidth }] }, [
      this.uiStore.showHeader ? h(TopHeader) : null,
      h('main', { class: ['main-content', { 'no-header': !this.uiStore.showHeader, 'no-nav': !this.uiStore.showBottomNav }] }, [
        h(RouteTransition, { routeKey: this.currentPage }, {
          default: () => h(this.AsyncComponent, this.currentProps)
        })
      ]),
      this.uiStore.showBottomNav ? h(BottomNav) : null,

      h(
        BaseModal,
        {
          modelValue: modal.show.value,
          'onUpdate:modelValue': v => (modal.show.value = v),
          modalTitle: modal.title.value,
          body: modal.body.value,
          footerClose: !modal.footer.value,
        },
        modal.footer.value
          ? { footer: () => h(modal.footer.value) }
          : {}
      ),
    ]);
  },
});

// Add global styles for the layout to ensure no overlap
const style = document.createElement('style');
style.textContent = `
  :root {
    --bg-primary: #ffffff;
    --bg-secondary: #f8f9fa;
    --bg-tertiary: #f0f2f5;
    --bg-card: #ffffff;
    --text-primary: #1e1e1e;
    --text-secondary: #717171;
    --text-muted: #a0a0a0;
    --border-color: rgba(0, 0, 0, 0.08);
    --accent-color: #533dea;
    --accent-soft: rgba(83, 61, 234, 0.1);
    --header-bg: rgba(255, 255, 255, 0.85);
    --nav-bg: rgba(255, 255, 255, 0.85);
    --bg-html: #fcebeb;
    --icon-filter: none;
    --layout-max-width: 1440px;
  }

  body.dark-mode {
    --bg-primary: #121418;
    --bg-secondary: #1a1c22;
    --bg-tertiary: #24272d;
    --bg-card: #1f2228;
    --text-primary: #e0e0e0;
    --text-secondary: #b0b0b0;
    --text-muted: #888888;
    --border-color: rgba(255, 255, 255, 0.08);
    --accent-color: #816ef0;
    --accent-soft: rgba(129, 110, 240, 0.15);
    --header-bg: rgba(18, 20, 24, 0.9);
    --nav-bg: rgba(18, 20, 24, 0.95);
    --bg-html: #1A0D0D;
    --icon-filter: brightness(0) invert(1);
  }

  html {
    background-color: var(--bg-html);
    transition: background-color 0.3s ease;
  }

  .app-layout {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background-color: var(--bg-primary);
    color: var(--text-primary);
    transition: background-color 0.3s ease, color 0.3s ease;
  }
  
  body {
    margin: 0 auto !important;
    padding: 0;
    overflow: hidden; /* Prevent double scrollbars if main-content scrolls */
    max-width: var(--layout-max-width, 100%);
    width: 100%;
    transition: max-width 0.3s ease, background-color 0.3s ease;
    background-color: var(--bg-primary);
    color: var(--text-primary);
  }
  
  body.is-full-width {
    max-width: none !important;
  }

  body.is-full-width .header,
  body.is-full-width .bottom-navigation-bar {
    max-width: none !important;
  }
  
  .app-layout.is-full-width .tf-container {
    max-width: none !important;
    width: 100% !important;
    padding: 0 !important;
  }
  
  .main-content {
    flex: 1;
    padding-top: 66px; /* Height of TopHeader (56px) + safe margin */
    padding-bottom: 80px; /* Height of BottomNav + some breathing room */
    overflow-y: auto;
    background-color: var(--bg-primary);
    transition: background-color 0.3s ease, padding 0.3s ease;
  }
  
  .main-content.no-header {
    padding-top: 0 !important;
  }
  
  .main-content.no-nav {
    padding-bottom: 0 !important;
  }

  /* Global theme consistency overrides */
  .dark-mode .tf-container,
  .dark-mode .manage-stores-page,
  .dark-mode .home-page,
  .dark-mode .account-settings-page,
  .dark-mode .card-section,
  .dark-mode .store-details-page,
  .dark-mode .pos-container,
  .dark-mode .box-user {
    background-color: transparent !important;
    background: transparent !important;
    color: var(--text-primary) !important;
  }

  .dark-mode h1, .dark-mode h2, .dark-mode h3, .dark-mode h4, .dark-mode h5, .dark-mode h6,
  .dark-mode span, .dark-mode p, .dark-mode label, .dark-mode i, .dark-mode div:not(.icon-box):not(.btn) {
    color: var(--text-primary) !important;
  }

  .dark-mode .text-muted, .dark-mode .text-secondary, .dark-mode .smallest {
    color: var(--text-secondary) !important;
  }

  .dark-mode input, .dark-mode select, .dark-mode textarea, .dark-mode .search-field {
    background-color: var(--bg-secondary) !important;
    color: var(--text-primary) !important;
    border-color: var(--border-color) !important;
  }

  .dark-mode .card, .dark-mode .list-user-info, 
  .dark-mode .store-table-container,
  .dark-mode .manage-stores-page .store-table-container,
  .dark-mode .pos-container .products-side, .dark-mode .pos-container .cart-side,
  .dark-mode .pos-container .product-card, .dark-mode .profile-card,
  .dark-mode .suggestions-dropdown, .dark-mode .scanner-container {
    background-color: var(--bg-card) !important;
    color: var(--text-primary) !important;
    border-color: var(--border-color) !important;
  }

  .dark-mode .table tbody tr, .dark-mode .table td {
    background-color: transparent !important;
    color: var(--text-primary) !important;
    border-color: var(--border-color) !important;
  }

  .dark-mode .table tr.active, .dark-mode .table tr:hover {
    background-color: var(--bg-tertiary) !important;
  }

  .dark-mode .icon-wrapper, .dark-mode .icon-box {
    background-color: var(--accent-soft) !important;
    border: 1px solid var(--border-color);
  }

  /* Force standard border color for all themed elements */
  .dark-mode div, .dark-mode section, .dark-mode ul, .dark-mode li, .dark-mode header, .dark-mode footer, .dark-mode nav {
    border-color: var(--border-color) !important;
  }

  .dark-mode .table thead th {
    background-color: var(--bg-tertiary) !important;
    color: var(--accent-color) !important;
    border-bottom: 1px solid var(--border-color);
  }

  .dark-mode .table tbody td {
    border-bottom: 1px solid var(--border-color);
    color: var(--text-primary) !important;
  }

  .dark-mode .header, .dark-mode .top-header {
    background-color: var(--header-bg) !important;
    backdrop-filter: blur(12px) !important;
    -webkit-backdrop-filter: blur(12px) !important;
    border-bottom-color: var(--border-color) !important;
  }

  .dark-mode .bottom-navigation-bar {
    background-color: var(--nav-bg) !important;
    backdrop-filter: blur(12px) !important;
    -webkit-backdrop-filter: blur(12px) !important;
    border-top-color: var(--border-color) !important;
    box-shadow: 0 -4px 30px rgba(0, 0, 0, 0.5) !important;
  }

  /* Bootstrap class overrides for dark mode — neutralizes hardcoded bg-white / bg-light / text-dark
     so components don't need per-file :global(.dark-mode) patches for these specific classes */
  .dark-mode .bg-white  { background-color: var(--bg-card) !important; }
  .dark-mode .bg-light  { background-color: var(--bg-secondary) !important; }
  .dark-mode .text-dark { color: var(--text-primary) !important; }
  .dark-mode .border    { border-color: var(--border-color) !important; }
  .dark-mode .modal-content  { background-color: var(--bg-card) !important; color: var(--text-primary) !important; border-color: var(--border-color) !important; }
  .dark-mode .dropdown-menu  { background-color: var(--bg-card) !important; border-color: var(--border-color) !important; }
  .dark-mode .dropdown-item  { color: var(--text-primary) !important; }
  .dark-mode .dropdown-item:hover { background-color: var(--bg-tertiary) !important; }
  .dark-mode .list-group-item { background-color: var(--bg-card) !important; color: var(--text-primary) !important; border-color: var(--border-color) !important; }
  .dark-mode .modal-header, .dark-mode .modal-footer { border-color: var(--border-color) !important; }

  /* Glassmorphism utility */
  .glass-card {
    background: rgba(255, 255, 255, 0.4) !important;
    backdrop-filter: blur(10px) !important;
    -webkit-backdrop-filter: blur(10px) !important;
    border: 1px solid rgba(0, 0, 0, 0.05) !important;
    box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07) !important;
  }

  .dark-mode .glass-card {
    background: rgba(31, 34, 40, 0.7) !important;
    backdrop-filter: blur(10px) !important;
    -webkit-backdrop-filter: blur(10px) !important;
    border: 1px solid rgba(255, 255, 255, 0.08) !important;
    box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3) !important;
  }

  /* Theme-aware icons */
  .icon-box img, .icon-wrapper img, .nav-icon, .icon-user {
    filter: var(--icon-filter);
    transition: filter 0.3s ease;
  }
`;
document.head.appendChild(style);

app.config.globalProperties.$modal = modal;

// Initialize Pinia
const pinia = createPinia();
app.use(pinia);

// --- Global navigate helper
let rootInstance = null;
app.config.globalProperties.$navigate = payload => {
  if (rootInstance) {
    rootInstance.navigate(payload);
  } else {
    console.warn('App not yet mounted, $navigate called too early.');
  }
};
const network = useNetworkStore()
// app.use(network) // Removed: Pinia stores are not Vue plugins. Pinia (the instance) is already registered above.

// Provide global access to user details - moved inside setup function

window.addEventListener('online', () => {
  network.setOnline(true)
})


window.addEventListener('offline', () => {
  network.setOnline(false)
})

// Register components
app.component('TopHeader', TopHeader);
app.component('BottomNav', BottomNav);
app.component('LottiePlayer', LottiePlayer);
app.component('AnimatedButton', AnimatedButton);

rootInstance = app.mount('#app');
window.$navigateHelper = app.config.globalProperties.$navigate;

// Expose prefetch helper globally for hover-based chunk preloading
window.$prefetchPage = (pageName) => {
  if (!pageName) return;
  const loader = pages[pageName];
  if (loader) loader().catch(() => {});
};

// Register Service Worker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js')
      .then(registration => {
        console.log('ServiceWorker registration successful with scope: ', registration.scope);
      })
      .catch(error => {
        console.log('ServiceWorker registration failed: ', error);
      });
  });
}
