import { mdiChartTimelineVariant } from '@mdi/js';
import Head from 'next/head';
import Link from 'next/link';
import { useRouter } from 'next/router';
import React, {
  ReactElement,
  useCallback,
  useEffect,
  useMemo,
  useState,
} from 'react';
import axios from 'axios';
import CardBox from '../../components/CardBox';
import LayoutAuthenticated from '../../layouts/Authenticated';
import SectionMain from '../../components/SectionMain';
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
import { getPageTitle } from '../../config';
import { logger } from '../../lib/logger';

type TourPage = {
  id: string;
  name?: string;
  sort_order?: number;
  ui_schema_json?: string;
};

type ConstructorElement = {
  id?: string;
  type?: string;
  label?: string;
  navLabel?: string;
  tooltipTitle?: string;
  descriptionTitle?: string;
};

type ConstructorSchema = {
  elements?: ConstructorElement[];
};

type ProjectElementItem = {
  id: string;
  pageId: string;
  pageName: string;
  elementType: string;
  name: string;
};

const parseJsonObject = (value?: unknown): Record<string, any> => {
  if (!value) return {};

  try {
    if (typeof value === 'string') {
      const parsed = JSON.parse(value);
      return typeof parsed === 'object' && parsed !== null ? parsed : {};
    }

    if (typeof value === 'object') {
      return value as Record<string, any>;
    }

    return {};
  } catch (error) {
    logger.error(
      'Failed to parse page schema JSON on pages elements list:',
      error instanceof Error ? error : { error },
    );
    return {};
  }
};

const toElementLabel = (value: string) =>
  value
    .split('_')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ');

const getElementName = (element: ConstructorElement) => {
  if (
    element.type === 'navigation_next' ||
    element.type === 'navigation_prev'
  ) {
    return String(element.navLabel || '').trim();
  }

  if (element.type === 'tooltip') {
    return String(element.tooltipTitle || '').trim();
  }

  if (element.type === 'description') {
    return String(element.descriptionTitle || '').trim();
  }

  return String(element.label || '').trim();
};

const PagesElementsListPage = () => {
  const router = useRouter();
  const routeProjectId = useMemo(() => {
    const value = router.query.projectId;
    if (Array.isArray(value)) return value[0] || '';
    return String(value || '');
  }, [router.query.projectId]);

  const [projectName, setProjectName] = useState('');
  const [isLoadingProject, setIsLoadingProject] = useState(false);
  const [isLoadingElements, setIsLoadingElements] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');
  const [projectElements, setProjectElements] = useState<ProjectElementItem[]>(
    [],
  );

  const loadData = useCallback(async () => {
    if (!routeProjectId) {
      setProjectName('');
      setProjectElements([]);
      return;
    }

    setIsLoadingProject(true);
    setIsLoadingElements(true);
    setErrorMessage('');

    try {
      const [projectResponse, pagesResponse] = await Promise.all([
        axios.get(`/projects/${routeProjectId}`),
        axios.get(
          `/tour_pages?limit=500&page=0&sort=asc&field=sort_order&project=${routeProjectId}`,
        ),
      ]);

      const project = projectResponse?.data || {};
      setProjectName(project?.name || '');

      const pageRows: TourPage[] = Array.isArray(pagesResponse?.data?.rows)
        ? pagesResponse.data.rows
        : [];

      const items: ProjectElementItem[] = [];

      pageRows.forEach((page, pageIndex) => {
        const schema = parseJsonObject(
          page.ui_schema_json,
        ) as ConstructorSchema;
        const elements = Array.isArray(schema.elements) ? schema.elements : [];

        elements.forEach((element) => {
          const elementType = String(element?.type || '').trim();
          const elementId = String(element?.id || '').trim();
          if (!elementType || !elementId) return;

          items.push({
            id: elementId,
            pageId: String(page.id),
            pageName: String(page.name || `Page ${pageIndex + 1}`),
            elementType,
            name: getElementName(element),
          });
        });
      });

      setProjectElements(items);
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Failed to load pages elements.';
      setErrorMessage(message);
      logger.error(
        'Failed to load project elements from constructor pages:',
        error instanceof Error ? error : { error },
      );
      setProjectName('');
      setProjectElements([]);
    } finally {
      setIsLoadingProject(false);
      setIsLoadingElements(false);
    }
  }, [routeProjectId]);

  useEffect(() => {
    loadData();
  }, [loadData]);

  const getElementEditorHref = (item: ProjectElementItem) =>
    `/page_elements/page_elements-project-edit/?projectId=${encodeURIComponent(routeProjectId)}&pageId=${encodeURIComponent(item.pageId)}&elementId=${encodeURIComponent(item.id)}`;

  return (
    <>
      <Head>
        <title>{getPageTitle('Pages Elements')}</title>
      </Head>
      <SectionMain>
        <SectionTitleLineWithButton
          icon={mdiChartTimelineVariant}
          title='Pages Elements'
          main
        >
          {''}
        </SectionTitleLineWithButton>

        <p className='mb-6 text-sm font-semibold'>
          {isLoadingProject
            ? 'Loading project...'
            : projectName || 'No project selected'}
        </p>

        {errorMessage ? (
          <CardBox className='mb-6 text-sm text-red-600'>
            {errorMessage}
          </CardBox>
        ) : null}

        <CardBox>
          <h3 className='mb-3 text-lg font-semibold'>
            Project elements from constructor pages
          </h3>

          {isLoadingElements ? (
            <p className='text-sm text-gray-500'>Loading elements...</p>
          ) : projectElements.length === 0 ? (
            <p className='text-sm text-gray-500'>
              No constructor elements found yet.
            </p>
          ) : (
            <div className='space-y-2'>
              {projectElements.map((item) => (
                <Link
                  key={`${item.pageId}_${item.id}`}
                  href={getElementEditorHref(item)}
                  className='block w-full rounded border border-gray-200 px-3 py-2 text-left hover:bg-gray-50 dark:border-dark-700 dark:hover:bg-dark-800'
                >
                  <p className='text-sm font-semibold'>{item.name}</p>
                  <p className='text-xs text-gray-500'>
                    {item.pageName} • {toElementLabel(item.elementType)}
                  </p>
                </Link>
              ))}
            </div>
          )}
        </CardBox>
      </SectionMain>
    </>
  );
};

PagesElementsListPage.getLayout = function getLayout(page: ReactElement) {
  return (
    <LayoutAuthenticated permission={'READ_PAGE_ELEMENTS'}>
      {page}
    </LayoutAuthenticated>
  );
};

export default PagesElementsListPage;
