import { mdiChartTimelineVariant } from '@mdi/js';
import Head from 'next/head';
import React, {
  ReactElement,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import { toast, ToastContainer } from 'react-toastify';
import LayoutAuthenticated from '../../layouts/Authenticated';
import SectionMain from '../../components/SectionMain';
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
import { getPageTitle } from '../../config';
import { hasPermission } from '../../helpers/userPermissions';
import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import {
  fetch as fetchAssets,
  deleteItem as deleteAsset,
  clearState as clearAssets,
} from '../../stores/assets/assetsSlice';
import AssetSectionCard, {
  Asset,
  AssetSection,
} from '../../components/Assets/AssetSectionCard';
import { useProjectSelector } from '../../components/Assets/ProjectSelector';
import { useAssetUploader } from '../../components/Assets/useAssetUploader';
import { logger } from '../../lib/logger';

const ASSET_SECTIONS: AssetSection[] = [
  {
    key: 'images',
    label: 'Icons',
    accept: 'image/*',
    assetFormat: 'image',
    assetCategory: 'icon',
    legacyTag: 'IMAGE',
  },
  {
    key: 'backgroundImages',
    label: 'Background Images',
    accept: 'image/*',
    assetFormat: 'image',
    assetCategory: 'background_image',
    legacyTag: 'BACKGROUND',
  },
  {
    key: 'audio',
    label: 'Audio',
    accept: 'audio/*',
    assetFormat: 'audio',
    assetCategory: 'audio',
    legacyTag: 'AUDIO',
  },
  {
    key: 'video',
    label: 'Video',
    accept: 'video/*',
    assetFormat: 'video',
    assetCategory: 'video',
    legacyTag: 'VIDEO',
  },
  {
    key: 'transitions',
    label: 'Transitions',
    accept: 'video/*',
    assetFormat: 'video',
    assetCategory: 'transition',
    legacyTag: 'TRANSITION',
  },
  {
    key: 'logo',
    label: 'Logo',
    accept: 'image/*',
    assetFormat: 'image',
    assetCategory: 'logo',
    legacyTag: 'LOGO',
  },
];

const AssetsTablesPage = () => {
  const dispatch = useAppDispatch();
  const { currentUser } = useAppSelector((state) => state.auth);
  const assets = useAppSelector((state) => state.assets.assets) as Asset[];
  const isLoadingAssets = useAppSelector((state) => state.assets.loading);

  const [deletingAssetId, setDeletingAssetId] = useState<string>('');

  const { selectedProjectId, isLoadingProjects, selectedProjectName } =
    useProjectSelector({ currentUser });

  const prevProjectIdRef = useRef<string>('');

  const loadAssets = useCallback(
    (projectId: string) => {
      if (!projectId) return;
      dispatch(
        fetchAssets({
          query: `?limit=500&page=0&sort=desc&field=createdAt&projectId=${projectId}`,
        }),
      );
    },
    [dispatch],
  );

  const { uploadingSections, uploadQueues, runBatchUpload } = useAssetUploader({
    selectedProjectId,
    onUploadComplete: () => loadAssets(selectedProjectId),
  });

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

    // Clear on project change
    if (prevProjectIdRef.current !== selectedProjectId) {
      dispatch(clearAssets());
    }
    prevProjectIdRef.current = selectedProjectId;

    loadAssets(selectedProjectId);
  }, [selectedProjectId, dispatch, loadAssets]);

  const hasCreatePermission = Boolean(
    currentUser && hasPermission(currentUser, 'CREATE_ASSETS'),
  );
  const hasDeletePermission = Boolean(
    currentUser && hasPermission(currentUser, 'DELETE_ASSETS'),
  );

  const handleDeleteAsset = useCallback(
    async (assetId: string) => {
      setDeletingAssetId(assetId);

      try {
        await dispatch(deleteAsset(assetId)).unwrap();
        toast('Asset deleted', { type: 'success', position: 'bottom-center' });
        loadAssets(selectedProjectId);
      } catch (error: unknown) {
        const errorMessage =
          error instanceof Error ? error.message : String(error);
        logger.error(
          'Failed to delete asset:',
          error instanceof Error ? error : { error: errorMessage },
        );
        toast('Failed to delete asset', {
          type: 'error',
          position: 'bottom-center',
        });
      } finally {
        setDeletingAssetId('');
      }
    },
    [dispatch, selectedProjectId, loadAssets],
  );

  const assetsBySection = useMemo(() => {
    return ASSET_SECTIONS.reduce<Record<string, Asset[]>>((acc, section) => {
      acc[section.key] = assets.filter((asset) => {
        if (asset.type) return asset.type === section.assetCategory;
        return asset.name?.startsWith(`[${section.legacyTag}] `);
      });
      return acc;
    }, {});
  }, [assets]);

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

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

        <div className='grid grid-cols-1 xl:grid-cols-2 gap-4'>
          {ASSET_SECTIONS.map((section) => (
            <AssetSectionCard
              key={section.key}
              section={section}
              assets={assetsBySection[section.key] || []}
              uploadQueue={uploadQueues[section.key] || []}
              isUploading={uploadingSections.includes(section.key)}
              isLoadingAssets={isLoadingAssets}
              hasCreatePermission={hasCreatePermission}
              hasDeletePermission={hasDeletePermission}
              deletingAssetId={deletingAssetId}
              onUpload={(files) => runBatchUpload(section, files)}
              onDeleteAsset={handleDeleteAsset}
              disabled={!selectedProjectId}
            />
          ))}
        </div>
      </SectionMain>
      <ToastContainer />
    </>
  );
};

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

export default AssetsTablesPage;
