import {
  mdiChartTimelineVariant,
  mdiClose,
  mdiFileDocumentPlus,
  mdiSwapHorizontal,
  mdiViewDashboard,
} from '@mdi/js';
import axios from 'axios';
import Head from 'next/head';
import { useRouter } from 'next/router';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { toast } from 'react-toastify';
import BaseButton from './BaseButton';
import CardBox from './CardBox';
import CardBoxModal from './CardBoxModal';
import SectionMain from './SectionMain';
import SectionTitleLineWithButton from './SectionTitleLineWithButton';
import { getPageTitle } from '../config';
import { hasPermission } from '../helpers/userPermissions';
import { useAppSelector } from '../stores/hooks';
import { logger } from '../lib/logger';
import { sanitizeSlug, buildUniqueSlug, slugPattern } from '../lib/slugHelpers';
import {
  toRoutePath,
  compareRoutes,
  getProjectId,
  getRows,
} from '../lib/tourFlowHelpers';

type TourPage = {
  id: string;
  name?: string;
  slug?: string;
  sort_order?: number;
  environment?: string;
  projectId?: string;
  project?: { id?: string } | string;
};

type Transition = {
  id: string;
  name?: string;
  slug?: string;
  environment?: string;
  projectId?: string;
  createdAt?: string;
  project?: { id?: string } | string;
};

type ProjectOption = {
  id: string;
  label: string;
};

type ListEntry = {
  type: 'page' | 'transition';
  id: string;
  title: string;
  routeLabel: string;
  description: string;
  parentPageId: string;
};

const TourFlowManager = () => {
  const router = useRouter();
  const { currentUser } = useAppSelector((state) => state.auth);

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

  const [pages, setPages] = useState<TourPage[]>([]);
  const [transitions, setTransitions] = useState<Transition[]>([]);
  const [projects, setProjects] = useState<ProjectOption[]>([]);
  const [selectedProjectId, setSelectedProjectId] = useState('');
  const [isLoading, setIsLoading] = useState(true);
  const [isCreatingPage, setIsCreatingPage] = useState(false);
  const [isCreatingTransition, setIsCreatingTransition] = useState(false);
  const [isCreatePageModalActive, setIsCreatePageModalActive] = useState(false);
  const [newPageSlug, setNewPageSlug] = useState('');
  const [newPageSlugError, setNewPageSlugError] = useState('');
  const [deletingId, setDeletingId] = useState('');
  const [errorMessage, setErrorMessage] = useState('');

  const canCreatePage = hasPermission(currentUser, 'CREATE_TOUR_PAGES');
  const canCreateTransition = hasPermission(currentUser, 'CREATE_TRANSITIONS');
  const canDeletePage = hasPermission(currentUser, 'DELETE_TOUR_PAGES');
  const canDeleteTransition = hasPermission(currentUser, 'DELETE_TRANSITIONS');

  const loadProjects = useCallback(async () => {
    const response = await axios.get('/projects/autocomplete?limit=100');
    const projectOptions = Array.isArray(response?.data) ? response.data : [];
    setProjects(projectOptions);

    if (projectOptions.length === 0) {
      toast('Please create a project first', {
        type: 'info',
        position: 'bottom-center',
      });
      router.replace('/projects/projects-new');
      return '';
    }

    if (
      routeProjectId &&
      projectOptions.some((item: ProjectOption) => item.id === routeProjectId)
    ) {
      setSelectedProjectId(routeProjectId);
      return routeProjectId;
    }

    if (projectOptions.length > 0) {
      setSelectedProjectId((prev) => prev || projectOptions[0].id);
      return projectOptions[0].id;
    }

    setSelectedProjectId('');
    return '';
  }, [routeProjectId, router]);

  const loadData = useCallback(async () => {
    try {
      setIsLoading(true);
      setErrorMessage('');

      const projectId = selectedProjectId || (await loadProjects());
      if (!projectId) {
        setPages([]);
        setTransitions([]);
        setIsLoading(false);
        return;
      }

      const pagesResponse = await axios.get(
        `/tour_pages?limit=500&sort=asc&field=sort_order&project=${projectId}&environment=dev`,
      );

      setPages(getRows(pagesResponse));
      setTransitions([]);
    } catch (error: any) {
      setErrorMessage(
        error?.response?.data?.message ||
          error?.message ||
          'Failed to load pages and transitions.',
      );
      logger.error(
        'Failed to load merged pages/transitions list:',
        error instanceof Error ? error : { error },
      );
    } finally {
      setIsLoading(false);
    }
  }, [loadProjects, selectedProjectId]);

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

  useEffect(() => {
    if (!selectedProjectId) return;
    if (routeProjectId && selectedProjectId === routeProjectId) return;

    if (routeProjectId) return;

    router.replace(
      {
        pathname: '/tour_pages/tour_pages-list',
        query: { projectId: selectedProjectId },
      },
      undefined,
      { shallow: true },
    );
  }, [routeProjectId, router, selectedProjectId]);

  const sortedPages = useMemo(
    () =>
      [...pages].sort((first, second) => {
        const routeCompare = compareRoutes(first.slug, second.slug);
        if (routeCompare !== 0) return routeCompare;

        const orderCompare = (first.sort_order || 0) - (second.sort_order || 0);
        if (orderCompare !== 0) return orderCompare;

        return (first.name || '').localeCompare(second.name || '');
      }),
    [pages],
  );

  const sortedTransitions = useMemo(
    () =>
      [...transitions].sort((first, second) => {
        const dateFirst = first.createdAt
          ? new Date(first.createdAt).getTime()
          : 0;
        const dateSecond = second.createdAt
          ? new Date(second.createdAt).getTime()
          : 0;
        if (dateFirst !== dateSecond) return dateFirst - dateSecond;

        return (first.name || first.slug || '').localeCompare(
          second.name || second.slug || '',
        );
      }),
    [transitions],
  );

  const activeProjectId = useMemo(() => {
    if (selectedProjectId) return selectedProjectId;

    const fromPages = sortedPages.find((item) => getProjectId(item));
    if (fromPages) return getProjectId(fromPages);

    const fromTransitions = sortedTransitions.find((item) =>
      getProjectId(item),
    );
    if (fromTransitions) return getProjectId(fromTransitions);

    return projects[0]?.id || '';
  }, [projects, selectedProjectId, sortedPages, sortedTransitions]);

  const targetEnvironment = useMemo(
    () =>
      sortedPages[0]?.environment || sortedTransitions[0]?.environment || 'dev',
    [sortedPages, sortedTransitions],
  );

  const pageSlugsInEnvironment = useMemo(
    () =>
      new Set(
        pages
          .filter((item) => (item.environment || 'dev') === targetEnvironment)
          .map((item) => String(item.slug || '').trim())
          .filter(Boolean),
      ),
    [pages, targetEnvironment],
  );

  const slugValidationError = useMemo(() => {
    const slug = newPageSlug.trim();
    if (!slug) return 'Slug is required.';
    if (!slugPattern.test(slug))
      return 'Use lowercase letters, numbers, and hyphens only.';
    if (pageSlugsInEnvironment.has(slug))
      return 'This slug already exists in the selected environment.';
    return '';
  }, [newPageSlug, pageSlugsInEnvironment]);

  const nextPageNumber = useMemo(() => pages.length + 1, [pages.length]);

  const listEntries = useMemo<ListEntry[]>(() => {
    const entries: ListEntry[] = [];

    sortedPages.forEach((page, index) => {
      const route = toRoutePath(page.slug);

      entries.push({
        type: 'page',
        id: page.id,
        title: page.name || `Page ${index + 1}`,
        routeLabel: route,
        description: 'Page',
        parentPageId: page.id,
      });

      const transition = sortedTransitions[index];
      if (!transition) return;

      entries.push({
        type: 'transition',
        id: transition.id,
        title: transition.name || transition.slug || `Transition ${index + 1}`,
        routeLabel: route,
        description: `Transition after ${route}`,
        parentPageId: page.id,
      });
    });

    return entries;
  }, [sortedPages, sortedTransitions]);

  const openConstructor = (
    pageId: string,
    sourceId: string,
    sourceType: 'page' | 'transition',
  ) => {
    if (!activeProjectId) {
      router.push('/projects/projects-list');
      return;
    }

    router.push({
      pathname: '/constructor',
      query: {
        projectId: activeProjectId,
        pageId,
        sourceId,
        sourceType,
      },
    });
  };

  const openCreatePageModal = () => {
    if (!activeProjectId) {
      setErrorMessage('Project not found. Please create a project first.');
      return;
    }

    const suggestedSlug = buildUniqueSlug(
      `page-${nextPageNumber}`,
      pageSlugsInEnvironment,
    );
    setNewPageSlug(suggestedSlug);
    setNewPageSlugError('');
    setIsCreatePageModalActive(true);
  };

  const handleSlugChange = (value: string) => {
    setNewPageSlug(value);
    setNewPageSlugError('');
  };

  const closeCreatePageModal = () => {
    setIsCreatePageModalActive(false);
    setNewPageSlug('');
    setNewPageSlugError('');
  };

  const handleCreatePage = async () => {
    if (!activeProjectId) {
      setErrorMessage('Project not found. Please create a project first.');
      return;
    }

    const slug = newPageSlug.trim();
    const validationError = slugValidationError || newPageSlugError;
    if (validationError) {
      setNewPageSlugError(validationError);
      return;
    }

    try {
      setIsCreatingPage(true);
      setErrorMessage('');
      setNewPageSlugError('');
      const payload = {
        project: activeProjectId,
        environment: targetEnvironment,
        source_key: '',
        name: `Page ${nextPageNumber}`,
        slug,
        sort_order:
          Math.max(...pages.map((item) => Number(item.sort_order || 0)), 0) + 1,
        background_image_url: '',
        background_video_url: '',
        background_audio_url: '',
        background_loop: false,
        requires_auth: false,
        ui_schema_json: '',
      };

      await axios.post('/tour_pages', { data: payload });
      setIsCreatePageModalActive(false);
      setNewPageSlug('');
      await loadData();
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Failed to create page.';
      setErrorMessage(message);
      setNewPageSlugError(message);
      logger.error(
        'Failed to create page:',
        error instanceof Error ? error : { error },
      );
    } finally {
      setIsCreatingPage(false);
    }
  };

  const handleCreateTransition = async () => {
    // Transitions are now set directly on navigation elements as transitionVideoUrl
    toast.info('Transitions are configured directly on navigation elements.');
  };

  const handleDelete = async (
    event: React.MouseEvent,
    id: string,
    type: 'page' | 'transition',
  ) => {
    event.stopPropagation();

    try {
      setDeletingId(id);
      setErrorMessage('');

      if (type === 'page') {
        await axios.delete(`/tour_pages/${id}`);
        setPages((prev) => prev.filter((item) => item.id !== id));
      }
    } catch (error: any) {
      setErrorMessage(
        error?.response?.data?.message ||
          error?.message ||
          'Failed to delete item.',
      );
      logger.error(
        'Failed to delete item:',
        error instanceof Error ? error : { error },
      );
    } finally {
      setDeletingId('');
    }
  };

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

        <p className='mb-6 text-sm font-semibold'>
          {isLoading
            ? 'Loading project...'
            : projects.find((project) => project.id === activeProjectId)
                ?.label || 'No project selected'}
        </p>

        <CardBox className='mb-6' cardBoxClassName='flex flex-wrap gap-3'>
          <BaseButton
            color='info'
            icon={mdiFileDocumentPlus}
            label='Create Page'
            onClick={openCreatePageModal}
            disabled={
              !canCreatePage ||
              isCreatingPage ||
              isCreatingTransition ||
              !activeProjectId
            }
          />
          <BaseButton
            color='info'
            icon={mdiSwapHorizontal}
            label={
              isCreatingTransition
                ? 'Creating Transition...'
                : 'Create Transition'
            }
            onClick={handleCreateTransition}
            disabled={
              !canCreateTransition ||
              isCreatingPage ||
              isCreatingTransition ||
              !activeProjectId
            }
          />
          <BaseButton
            color='lightDark'
            icon={mdiViewDashboard}
            label='To Constructor'
            href={
              activeProjectId
                ? `/constructor?projectId=${activeProjectId}`
                : '/projects/projects-list'
            }
          />
        </CardBox>

        <CardBoxModal
          title='Create page'
          buttonColor='info'
          buttonLabel={isCreatingPage ? 'Creating...' : 'Create'}
          isConfirmDisabled={Boolean(slugValidationError) || isCreatingPage}
          isActive={isCreatePageModalActive}
          onConfirm={handleCreatePage}
          onCancel={isCreatingPage ? undefined : closeCreatePageModal}
        >
          <div>
            <label
              htmlFor='new-page-slug'
              className='block text-sm font-semibold mb-1'
            >
              Page slug
            </label>
            <input
              id='new-page-slug'
              type='text'
              value={newPageSlug}
              onChange={(event) => handleSlugChange(event.target.value)}
              placeholder='my-page-slug'
              className='w-full border border-gray-300 rounded px-3 py-2 bg-white dark:bg-dark-800'
              autoFocus
            />
            <p className='text-xs text-gray-500 mt-2'>
              Use lowercase letters, numbers, and hyphens.
            </p>
            {(newPageSlugError || slugValidationError) && (
              <p className='text-xs text-red-600 mt-2'>
                {newPageSlugError || slugValidationError}
              </p>
            )}
          </div>
        </CardBoxModal>

        {errorMessage && (
          <CardBox className='mb-6'>
            <p className='text-sm text-red-600'>{errorMessage}</p>
          </CardBox>
        )}

        <CardBox>
          {isLoading ? (
            <p className='text-sm text-gray-500'>
              Loading pages and transitions...
            </p>
          ) : listEntries.length === 0 ? (
            <p className='text-sm text-gray-500'>
              No pages or transitions yet.
            </p>
          ) : (
            <ul className='grid grid-cols-1 lg:grid-cols-2 gap-4'>
              {listEntries.map((entry) => {
                const canDelete =
                  entry.type === 'page' ? canDeletePage : canDeleteTransition;
                const isDeleting = deletingId === entry.id;

                return (
                  <li key={`${entry.type}-${entry.id}`}>
                    <button
                      type='button'
                      className='w-full text-left border border-gray-200 rounded-lg p-4 hover:bg-gray-50 transition-colors relative'
                      onClick={() =>
                        openConstructor(
                          entry.parentPageId,
                          entry.id,
                          entry.type,
                        )
                      }
                    >
                      <div className='pr-8'>
                        <p className='text-xs uppercase text-gray-500 mb-1'>
                          {entry.description}
                        </p>
                        <p className='font-semibold'>{entry.title}</p>
                        <p className='text-sm text-gray-500 mt-1'>
                          Route: {entry.routeLabel}
                        </p>
                      </div>

                      <BaseButton
                        className='!absolute top-3 right-3'
                        icon={mdiClose}
                        color='danger'
                        outline
                        small
                        onClick={(event) =>
                          handleDelete(event, entry.id, entry.type)
                        }
                        disabled={!canDelete || isDeleting}
                      />
                    </button>
                  </li>
                );
              })}
            </ul>
          )}
        </CardBox>
      </SectionMain>
    </>
  );
};

export default TourFlowManager;
