/**
 * useConstructorPageActions Hook
 *
 * Handles page create/save/publish operations in the constructor.
 * Manages async state and API calls for page operations.
 */

import { useState, useCallback } from 'react';
import axios from 'axios';
import type { CanvasElement } from '../types/constructor';
import { createLocalId } from '../lib/elementDefaults';
import { parseJsonObject } from '../lib/parseJson';
import { logger } from '../lib/logger';

interface TourPage {
  id: string;
  name?: string;
  slug?: string;
  sort_order?: number;
  environment?: string;
  source_key?: string;
  requires_auth?: boolean;
  ui_schema_json?: string;
  background_image_url?: string;
  background_video_url?: string;
  background_audio_url?: string;
  background_loop?: boolean;
}

interface UseConstructorPageActionsOptions {
  /** Current project ID */
  projectId: string;
  /** Array of all pages */
  pages: TourPage[];
  /** Currently active page */
  activePage: TourPage | null;
  /** Current active page ID */
  activePageId: string;
  /** Current elements array */
  elements: CanvasElement[];
  /** Current background URLs */
  backgroundImageUrl: string;
  backgroundVideoUrl: string;
  backgroundAudioUrl: string;
  /** Callback to reload data after operations */
  onReload: (preservePageId?: string) => Promise<void>;
  /** Callback to set active page ID */
  onSetActivePageId: (pageId: string) => void;
  /** Callback to set menu open state */
  onSetMenuOpen?: (isOpen: boolean) => void;
  /** Callback for error messages */
  onError?: (message: string) => void;
  /** Callback for success messages */
  onSuccess?: (message: string) => void;
}

interface UseConstructorPageActionsResult {
  /** Whether save operation is in progress */
  isSaving: boolean;
  /** Whether save-to-stage operation is in progress */
  isSavingToStage: boolean;
  /** Whether page creation is in progress */
  isCreatingPage: boolean;
  /** Whether transition creation is in progress */
  isCreatingTransition: boolean;
  /** Save current constructor state */
  saveConstructor: () => Promise<void>;
  /** Save dev content to stage environment */
  saveToStage: () => Promise<void>;
  /** Create a new page */
  createPage: () => Promise<void>;
  /** Create a transition (legacy - transitions are now stored on elements) */
  createTransition: (params: {
    name?: string;
    videoUrl: string;
    supportsReverse?: boolean;
    durationSec?: number;
  }) => Promise<void>;
}

/**
 * Hook for managing constructor page operations.
 *
 * @example
 * const {
 *   isSaving,
 *   saveConstructor,
 *   createPage,
 *   isCreatingPage,
 * } = useConstructorPageActions({
 *   projectId,
 *   pages,
 *   activePage,
 *   activePageId,
 *   elements,
 *   backgroundImageUrl,
 *   backgroundVideoUrl,
 *   backgroundAudioUrl,
 *   onReload: loadData,
 *   onSetActivePageId: setActivePageId,
 *   onError: setErrorMessage,
 *   onSuccess: setSuccessMessage,
 * });
 */
export function useConstructorPageActions({
  projectId,
  pages,
  activePage,
  activePageId,
  elements,
  backgroundImageUrl,
  backgroundVideoUrl,
  backgroundAudioUrl,
  onReload,
  onSetActivePageId,
  onSetMenuOpen,
  onError,
  onSuccess,
}: UseConstructorPageActionsOptions): UseConstructorPageActionsResult {
  const [isSaving, setIsSaving] = useState(false);
  const [isSavingToStage, setIsSavingToStage] = useState(false);
  const [isCreatingPage, setIsCreatingPage] = useState(false);
  const [isCreatingTransition, setIsCreatingTransition] = useState(false);

  const saveConstructor = useCallback(async () => {
    if (!activePageId) {
      onError?.('Select a page before saving.');
      return;
    }

    try {
      setIsSaving(true);

      const existingSchema = parseJsonObject<Record<string, any>>(
        activePage?.ui_schema_json,
        {},
      );
      const schemaToSave = {
        ...existingSchema,
        elements,
      };

      await axios.put(`/tour_pages/${activePageId}`, {
        id: activePageId,
        data: {
          environment: activePage?.environment,
          source_key: activePage?.source_key,
          name: activePage?.name,
          slug: activePage?.slug,
          sort_order: activePage?.sort_order,
          requires_auth: activePage?.requires_auth,
          ui_schema_json: schemaToSave,
          background_image_url: backgroundImageUrl,
          background_video_url: backgroundVideoUrl,
          background_audio_url: backgroundAudioUrl,
          background_loop: Boolean(backgroundAudioUrl),
        },
      });

      onSuccess?.(
        'Constructor settings saved. Element positions are stored in percentages.',
      );
      await onReload(activePageId);
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Failed to save constructor changes.';
      logger.error(
        'Failed to save constructor changes:',
        error instanceof Error ? error : { error },
      );
      onError?.(message);
    } finally {
      setIsSaving(false);
    }
  }, [
    activePage?.environment,
    activePage?.name,
    activePage?.requires_auth,
    activePage?.slug,
    activePage?.sort_order,
    activePage?.source_key,
    activePage?.ui_schema_json,
    activePageId,
    backgroundAudioUrl,
    backgroundImageUrl,
    backgroundVideoUrl,
    elements,
    onError,
    onReload,
    onSuccess,
  ]);

  const saveToStage = useCallback(async () => {
    if (!projectId) {
      onError?.('Project ID is required to save to stage.');
      return;
    }

    // First save current changes
    await saveConstructor();

    try {
      setIsSavingToStage(true);

      await axios.post('/publish/save-to-stage', { projectId });

      onSuccess?.(
        'Successfully saved dev content to stage environment. All pages, elements, and transitions have been copied.',
      );
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Failed to save to stage.';
      logger.error(
        'Failed to save to stage:',
        error instanceof Error ? error : { error },
      );
      onError?.(message);
    } finally {
      setIsSavingToStage(false);
    }
  }, [projectId, saveConstructor, onError, onSuccess]);

  const createPage = useCallback(async () => {
    if (!projectId) {
      onError?.('Project is required.');
      return;
    }

    const maxSortOrder = Math.max(
      0,
      ...pages.map((item) => Number(item.sort_order || 0)),
    );
    const nextPageNumber = pages.length + 1;

    const payload = {
      project: projectId,
      environment: activePage?.environment || 'dev',
      source_key: '',
      name: `Page ${nextPageNumber}`,
      slug: `page-${nextPageNumber}-${Date.now().toString().slice(-4)}`,
      sort_order: maxSortOrder + 1,
      background_image_url: '',
      background_video_url: '',
      background_audio_url: '',
      background_loop: false,
      requires_auth: false,
      ui_schema_json: JSON.stringify({ elements: [] }),
    };

    try {
      setIsCreatingPage(true);
      const response = await axios.post('/tour_pages', { data: payload });
      const createdPage = response?.data;

      await onReload();

      if (createdPage?.id) {
        onSetActivePageId(createdPage.id);
      }

      onSetMenuOpen?.(true);
      onSuccess?.('New page created. You can now configure it in constructor.');
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Failed to create page.';
      logger.error(
        'Failed to create page from constructor:',
        error instanceof Error ? error : { error },
      );
      onError?.(message);
    } finally {
      setIsCreatingPage(false);
    }
  }, [
    activePage?.environment,
    onError,
    onReload,
    onSetActivePageId,
    onSetMenuOpen,
    onSuccess,
    pages,
    projectId,
  ]);

  const createTransition = useCallback(
    async (params: {
      name?: string;
      videoUrl: string;
      supportsReverse?: boolean;
      durationSec?: number;
    }) => {
      if (!projectId) {
        onError?.('Project is required.');
        return;
      }

      const sanitizedVideoUrl = String(params.videoUrl || '').trim();
      if (!sanitizedVideoUrl) {
        onError?.('Select a transition video asset first.');
        return;
      }

      if (!params.durationSec) {
        onError?.(
          'Could not resolve transition video duration yet. Please wait a moment and try again.',
        );
        return;
      }

      try {
        setIsCreatingTransition(true);

        // Transitions are now stored directly in navigation elements as transitionVideoUrl
        // This method is kept for backwards compatibility but just shows a message
        onSuccess?.(
          'Transition video can be set directly on navigation elements.',
        );
      } catch (error: any) {
        const message =
          error?.response?.data?.message ||
          error?.message ||
          'Failed to create transition.';
        logger.error(
          'Failed to create transition from constructor:',
          error instanceof Error ? error : { error },
        );
        onError?.(message);
      } finally {
        setIsCreatingTransition(false);
      }
    },
    [projectId, onError, onSuccess],
  );

  return {
    isSaving,
    isSavingToStage,
    isCreatingPage,
    isCreatingTransition,
    saveConstructor,
    saveToStage,
    createPage,
    createTransition,
  };
}

export default useConstructorPageActions;
