import React from 'react';
import type { AppProps } from 'next/app';
import type { ReactElement, ReactNode } from 'react';
import type { NextPage } from 'next';
import Head from 'next/head';
import { store } from '../stores/store';
import { Provider } from 'react-redux';
import { QueryClientProvider } from '@tanstack/react-query';
import { queryClient } from '../lib/queryClient';

// Import Instrument Sans font (self-hosted via Fontsource)
import '@fontsource-variable/instrument-sans';
import '@fontsource-variable/instrument-sans/wdth.css'; // Condensed width axis
import '../css/main.css';
import axios from 'axios';
import { baseURLApi } from '../config';
import { useRouter } from 'next/router';
import ErrorBoundary from '../components/ErrorBoundary';
import 'intro.js/introjs.css';
import { appWithTranslation } from 'next-i18next';
import '../i18n';
import IntroGuide from '../components/IntroGuide';
import {
  appSteps,
  loginSteps,
  usersSteps,
  rolesSteps,
} from '../stores/introSteps';
import { DownloadProvider } from '../context/DownloadContext';
import { logger } from '../lib/logger';
import { disablePresignedUrls } from '../lib/assetUrl';

/**
 * Check if a URL is a presigned S3 URL
 */
const isPresignedS3Url = (url: string): boolean => {
  return url.includes('X-Amz-Signature=') || url.includes('x-amz-signature=');
};

// Initialize axios
axios.defaults.baseURL = process.env.NEXT_PUBLIC_BACK_API
  ? process.env.NEXT_PUBLIC_BACK_API
  : baseURLApi;

axios.defaults.headers.common['Content-Type'] = 'application/json';

// Set up axios request interceptor synchronously to ensure token is always attached
axios.interceptors.request.use(
  (config) => {
    if (typeof window !== 'undefined') {
      const token =
        sessionStorage.getItem('token') || localStorage.getItem('token');
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      } else {
        delete config.headers.Authorization;
      }
    }
    return config;
  },
  (error) => Promise.reject(error),
);

// Set up axios response interceptor to handle 401 errors and presigned URL failures
axios.interceptors.response.use(
  (response) => response,
  (error) => {
    if (typeof window !== 'undefined') {
      const status = error?.response?.status;
      const requestUrl = `${error?.config?.url || ''}`;
      const isLoginRequest =
        requestUrl.includes('/auth/signin/local') ||
        requestUrl.includes('auth/signin/local');

      // Detect presigned S3 URL failures (CORS not configured)
      // Network errors (status 0) or CORS errors typically indicate S3 CORS issues
      if (
        isPresignedS3Url(requestUrl) &&
        (!status || status === 0 || error.message?.includes('Network Error'))
      ) {
        logger.info('[axios] Presigned URL failed, disabling presigned URLs', {
          url: requestUrl.slice(0, 80),
        });
        disablePresignedUrls();
      }

      if (status === 401 && !isLoginRequest) {
        // Clear stored tokens
        sessionStorage.removeItem('token');
        sessionStorage.removeItem('user');
        localStorage.removeItem('token');
        localStorage.removeItem('user');
        delete axios.defaults.headers.common['Authorization'];

        // Redirect to login if not already there
        if (!window.location.pathname.includes('/login')) {
          window.location.href = '/login';
        }
      }
    }
    return Promise.reject(error);
  },
);

export type NextPageWithLayout<P = Record<string, unknown>, IP = P> = NextPage<
  P,
  IP
> & {
  getLayout?: (page: ReactElement) => ReactNode;
};

type AppPropsWithLayout = AppProps & {
  Component: NextPageWithLayout;
};

function MyApp({ Component, pageProps }: AppPropsWithLayout) {
  // Use the layout defined at the page level, if available
  const getLayout = Component.getLayout || ((page) => page);
  const router = useRouter();
  const [stepsEnabled, setStepsEnabled] = React.useState(false);
  const [stepName, setStepName] = React.useState('');
  const [steps, setSteps] = React.useState([]);

  // Register service worker for PWA offline support
  React.useEffect(() => {
    if (
      typeof window !== 'undefined' &&
      'serviceWorker' in navigator &&
      process.env.NODE_ENV === 'production'
    ) {
      navigator.serviceWorker
        .register('/sw.js')
        .then((registration) => {
          logger.info('[PWA] Service worker registered:', {
            scope: registration.scope,
          });

          // Check for updates periodically
          setInterval(
            () => {
              registration.update();
            },
            60 * 60 * 1000,
          ); // Check every hour
        })
        .catch((error) => {
          logger.error(
            '[PWA] Service worker registration failed:',
            error instanceof Error ? error : { error },
          );
        });
    }
  }, []);

  React.useEffect(() => {
    // Tour is disabled by default in generated projects.
    return;
    const isCompleted = (stepKey: string) => {
      return localStorage.getItem(`completed_${stepKey}`) === 'true';
    };
    if (router.pathname === '/login' && !isCompleted('loginSteps')) {
      setSteps(loginSteps);
      setStepName('loginSteps');
      setStepsEnabled(true);
    } else if (router.pathname === '/dashboard' && !isCompleted('appSteps')) {
      setTimeout(() => {
        setSteps(appSteps);
        setStepName('appSteps');
        setStepsEnabled(true);
      }, 1000);
    } else if (
      router.pathname === '/users/users-list' &&
      !isCompleted('usersSteps')
    ) {
      setTimeout(() => {
        setSteps(usersSteps);
        setStepName('usersSteps');
        setStepsEnabled(true);
      }, 1000);
    } else if (
      router.pathname === '/roles/roles-list' &&
      !isCompleted('rolesSteps')
    ) {
      setTimeout(() => {
        setSteps(rolesSteps);
        setStepName('rolesSteps');
        setStepsEnabled(true);
      }, 1000);
    } else {
      setSteps([]);
      setStepsEnabled(false);
    }
  }, [router.pathname]);

  const handleExit = () => {
    setStepsEnabled(false);
  };

  const title = 'Shimahara Visual';
  const description =
    'Platform to build, preview (stage), and publish offline-ready interactive tours on project subdomains.';
  const url = 'https://flatlogic.com/';
  const image =
    'https://project-screens.s3.amazonaws.com/screenshots/39215/app-hero-20260316-121031.png';
  const imageWidth = '1920';
  const imageHeight = '960';

  return (
    <QueryClientProvider client={queryClient}>
      <Provider store={store}>
        <DownloadProvider>
          {getLayout(
            <>
              <Head>
                <meta name='description' content={description} />
                <meta property='og:url' content={url} />
                <meta
                  property='og:site_name'
                  content='https://flatlogic.com/'
                />
                <meta key='og:title' property='og:title' content={title} />
                <meta
                  key='og:description'
                  property='og:description'
                  content={description}
                />
                <meta key='og:image' property='og:image' content={image} />
                <meta property='og:image:type' content='image/png' />
                <meta property='og:image:width' content={imageWidth} />
                <meta property='og:image:height' content={imageHeight} />
                <meta property='twitter:card' content='summary_large_image' />
                <meta
                  key='twitter:title'
                  property='twitter:title'
                  content={title}
                />
                <meta
                  key='twitter:description'
                  property='twitter:description'
                  content={description}
                />
                <meta
                  key='twitter:image:src'
                  property='twitter:image:src'
                  content={image}
                />
                <meta property='twitter:image:width' content={imageWidth} />
                <meta property='twitter:image:height' content={imageHeight} />
                <link key='favicon' rel='icon' href='/favicon.svg' />
                <link rel='manifest' href='/manifest.json' />
                <meta name='theme-color' content='#3B82F6' />
                <meta name='mobile-web-app-capable' content='yes' />
                <meta
                  name='apple-mobile-web-app-status-bar-style'
                  content='default'
                />
                <meta
                  name='apple-mobile-web-app-title'
                  content='Tour Builder'
                />
              </Head>

              <ErrorBoundary>
                <Component {...pageProps} />
              </ErrorBoundary>
              <IntroGuide
                steps={steps}
                stepsName={stepName}
                stepsEnabled={stepsEnabled}
                onExit={handleExit}
              />
            </>,
          )}
        </DownloadProvider>
      </Provider>
    </QueryClientProvider>
  );
}

export default appWithTranslation(MyApp);
