'use client';

import React, { useState, useCallback, useEffect, useMemo, useRef } from 'react';
import { createPortal } from 'react-dom';
import { ToastContext } from '../context/ToastContext';
import { ToastContainer } from './ToastContainer';
import { ToastProps, ToastProviderProps, ToastPosition, ToastLayout, RichColorsMode, ToastSize } from '../types';
import { MAX_TOASTS } from '../utils/constants';
import { registerToastStore, unregisterToastStore } from '../utils/toastStore';
import '../styles/toast.css';

export const ToastProvider: React.FC<ToastProviderProps> = ({
  children = null,
  defaultPosition,
  position: positionProp,
  defaultLayout,
  layout: layoutProp,
  maxToasts = MAX_TOASTS,
  containerClassName = '',
  showCloseButton = true,
  swipeDirection = 'right',
  showProgressBar = true,
  color = true,
  richColors = false,
  size = 'md',
  defaultDuration,
  duration,
}) => {
  // Support both naming conventions: defaultPosition/position, defaultLayout/layout
  const initialPosition = positionProp ?? defaultPosition ?? 'top-right';
  const initialLayout = layoutProp ?? defaultLayout ?? 'normal';
  const finalDuration = duration ?? defaultDuration;

  const [toasts, setToasts] = useState<ToastProps[]>([]);
  const [position, setPosition] = useState<ToastPosition>(initialPosition);
  const [layout, setLayout] = useState<ToastLayout>(initialLayout);
  const resolvedRichColorsMode: RichColorsMode | undefined =
    richColors === true ? 'minimal' : typeof richColors === 'string' ? richColors : undefined;
  const toastSize: ToastSize = size;

  const audioRefsRef = useRef<Map<string, HTMLAudioElement>>(new Map());

  const addToast = useCallback(
    (toast: Omit<ToastProps, 'id'>) => {
      const id = Math.random().toString(36).substring(2, 11);
      // Apply default duration if not provided in toast options
      // If toast explicitly sets duration (including 0 for infinite), use it
      // Otherwise, use defaultDuration if provided, or leave undefined for Toast component default
      const toastWithDuration = {
        ...toast,
        duration: toast.duration !== undefined ? toast.duration : finalDuration,
      };
      setToasts((prevToasts) => {
        const newToasts = [...prevToasts, { ...toastWithDuration, id }];
        return newToasts.slice(-maxToasts);
      });
      if (toast.soundEffect) {
        // Clean up old audio instances and create new one
        const audio = new Audio(toast.soundEffect);
        audioRefsRef.current.set(id, audio);
        audio.play()
          .catch((e) => console.error('Error playing sound:', e))
          .finally(() => {
            // Clean up after playback or error
            setTimeout(() => {
              audioRefsRef.current.delete(id);
              audio.remove();
            }, 1000);
          });
      }
      return id;
    },
    [maxToasts, finalDuration],
  );

  // Cleanup audio on unmount
  useEffect(() => {
    return () => {
      audioRefsRef.current.forEach((audio) => {
        audio.pause();
        audio.remove();
      });
      audioRefsRef.current.clear();
    };
  }, []);

  const removeToast = useCallback((id: string) => {
    setToasts((prevToasts) => prevToasts.filter((toast) => toast.id !== id));
  }, []);

  const updateToast = useCallback((id: string, updates: Partial<Omit<ToastProps, 'id'>>) => {
    setToasts((prevToasts) =>
      prevToasts.map((toast) => (toast.id === id ? { ...toast, ...updates } : toast)),
    );
  }, []);

  const clearAllToasts = useCallback(() => {
    setToasts([]);
  }, []);

  const contextValue = useMemo(
    () => ({
      addToast,
      removeToast,
      updateToast,
      clearAllToasts,
      position,
      setPosition,
      layout,
      setLayout,
      showCloseButton,
      swipeDirection,
      showProgressBar,
      color,
      richColors: resolvedRichColorsMode,
      size: toastSize,
    }),
    [
      addToast,
      removeToast,
      updateToast,
      clearAllToasts,
      position,
      layout,
      showCloseButton,
      swipeDirection,
      showProgressBar,
      color,
      resolvedRichColorsMode,
      toastSize,
    ],
  );

  const [isMounted, setIsMounted] = useState(false);

  useEffect(() => {
    setIsMounted(true);
  }, []);

  // Register toast store for global access
  useEffect(() => {
    registerToastStore({
      addToast,
      removeToast,
      updateToast,
      clearAllToasts,
    });

    return () => {
      unregisterToastStore();
    };
  }, [addToast, removeToast, updateToast, clearAllToasts]);

  // Sync position prop changes
  useEffect(() => {
    if (positionProp !== undefined) {
      setPosition(positionProp);
    }
  }, [positionProp]);

  // Sync layout prop changes
  useEffect(() => {
    if (layoutProp !== undefined) {
      setLayout(layoutProp);
    }
  }, [layoutProp]);

  return (
    <ToastContext.Provider value={contextValue}>
      {children}
      {isMounted &&
        createPortal(
          <ToastContainer
            toasts={toasts}
            position={position}
            layout={layout}
            className={containerClassName}
            showCloseButton={showCloseButton}
            swipeDirection={swipeDirection}
            showProgressBar={showProgressBar}
            color={color}
            richColors={resolvedRichColorsMode}
            size={toastSize}
            onRemoveToast={removeToast}
          />,
          document.body,
        )}
    </ToastContext.Provider>
  );
};
