import { mdiContentSave, mdiCog, mdiSync } from '@mdi/js';
import axios from 'axios';
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 BaseButton from '../../components/BaseButton';
import CardBox from '../../components/CardBox';
import FormField from '../../components/FormField';
import LayoutAuthenticated from '../../layouts/Authenticated';
import SectionMain from '../../components/SectionMain';
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
import { getPageTitle } from '../../config';
import { logger } from '../../lib/logger';
import type {
  CanvasElementType,
  ConstructorAsset,
  AssetOption,
} from '../../types/constructor';

// Import shared element settings components
import {
  ElementSettingsTabs,
  StyleSettingsSection,
  EffectsSettingsSection,
  CommonSettingsSection,
  NavigationSettingsSection,
  TooltipSettingsSection,
  DescriptionSettingsSection,
  MediaSettingsSection,
  GallerySettingsSection,
  CarouselSettingsSection,
  useElementSettingsForm,
} from '../../components/ElementSettings';

type ProjectElementDefault = {
  id: string;
  element_type: string;
  name?: string;
  sort_order?: number;
  settings_json?: string | Record<string, unknown>;
  source_element_id?: string;
  snapshot_version?: number;
  projectId: string;
};

type DiffResult = {
  projectDefault: ProjectElementDefault | null;
  globalDefault: Record<string, unknown> | null;
  isDifferent: boolean;
  hasGlobalDefault: boolean;
};

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

const SETTINGS_TABS = [
  { id: 'general', label: 'General Settings' },
  { id: 'css', label: 'CSS Styles' },
  { id: 'effects', label: 'Effects' },
];

const ProjectElementDefaultDetailsPage = () => {
  const router = useRouter();
  const id = useMemo(() => {
    const routeValue = router.query.id;
    if (Array.isArray(routeValue)) return routeValue[0] || '';
    return String(routeValue || '');
  }, [router.query.id]);

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

  const [item, setItem] = useState<ProjectElementDefault | null>(null);
  const [name, setName] = useState('');
  const [sortOrder, setSortOrder] = useState(0);
  const [activeTab, setActiveTab] = useState('general');
  const [assets, setAssets] = useState<ConstructorAsset[]>([]);

  const [diff, setDiff] = useState<DiffResult | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [isSaving, setIsSaving] = useState(false);
  const [isResetting, setIsResetting] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');
  const [successMessage, setSuccessMessage] = useState('');

  const currentElementType = (item?.element_type || '') as CanvasElementType;

  // Use shared form hook
  const form = useElementSettingsForm({ elementType: currentElementType });

  // Helper functions for asset options
  const getAssetSourceValue = (asset: ConstructorAsset) =>
    String(asset.storage_key || asset.cdn_url || '').trim();

  const getAssetLabel = (asset: ConstructorAsset) => {
    const baseName = asset.name?.trim() || 'Untitled asset';
    const source = getAssetSourceValue(asset);
    return `${baseName}${source ? ` · ${source}` : ''}`;
  };

  // Build icon asset options from project assets
  const iconAssetOptions: AssetOption[] = useMemo(
    () =>
      assets
        .filter(
          (asset) =>
            asset.type === 'icon' &&
            asset.asset_type === 'image' &&
            getAssetSourceValue(asset),
        )
        .map((asset) => ({
          value: getAssetSourceValue(asset),
          label: getAssetLabel(asset),
        })),
    [assets],
  );

  // Extract stable callback reference to avoid infinite loop
  const applySettings = form.applySettings;

  const loadItem = useCallback(async () => {
    if (!id) return;

    try {
      setIsLoading(true);
      setErrorMessage('');
      setSuccessMessage('');

      const response = await axios.get(`/project-element-defaults/${id}`);
      const nextItem: ProjectElementDefault | null = response?.data || null;

      if (!nextItem) {
        setErrorMessage('Project element default not found.');
        setItem(null);
        return;
      }

      setItem(nextItem);
      setName(String(nextItem.name || ''));
      setSortOrder(Number(nextItem.sort_order || 0));
      applySettings(nextItem.settings_json);

      // Load project assets for icon selector
      if (nextItem.projectId) {
        try {
          const assetsResponse = await axios.get(
            `/assets?limit=500&page=0&sort=desc&field=createdAt&projectId=${nextItem.projectId}`,
          );
          const assetRows: ConstructorAsset[] = Array.isArray(
            assetsResponse?.data?.rows,
          )
            ? assetsResponse.data.rows
            : [];
          setAssets(assetRows);
        } catch (assetError) {
          logger.error(
            'Failed to load project assets:',
            assetError instanceof Error ? assetError : { error: assetError },
          );
          setAssets([]);
        }
      }
    } catch (error: unknown) {
      const err = error as {
        response?: { data?: { message?: string } };
        message?: string;
      };
      const message =
        err?.response?.data?.message ||
        err?.message ||
        'Failed to load project element default.';
      logger.error(
        'Failed to load project element default details:',
        error instanceof Error ? error : { error },
      );
      setErrorMessage(message);
      setItem(null);
    } finally {
      setIsLoading(false);
    }
  }, [applySettings, id]);

  const loadDiff = useCallback(async () => {
    if (!id) return;

    try {
      const response = await axios.get(`/project-element-defaults/${id}/diff`);
      setDiff(response?.data || null);
    } catch (error: unknown) {
      logger.error(
        'Failed to load diff:',
        error instanceof Error ? error : { error },
      );
      setDiff(null);
    }
  }, [id]);

  useEffect(() => {
    if (!router.isReady) return;
    loadItem();
    loadDiff();
  }, [loadItem, loadDiff, router.isReady]);

  // Extract stable callback reference for buildSettingsJson
  const buildSettingsJson = form.buildSettingsJson;

  const handleSave = useCallback(async () => {
    if (!id || !item) return;

    const settings = buildSettingsJson();

    try {
      setIsSaving(true);
      setErrorMessage('');
      setSuccessMessage('');

      await axios.put(`/project-element-defaults/${id}`, {
        id,
        data: {
          element_type: item.element_type,
          name: name.trim() || item.element_type,
          sort_order: sortOrder,
          settings_json: settings,
        },
      });

      setSuccessMessage('Project element default saved successfully.');
      await loadItem();
      await loadDiff();
    } catch (error: unknown) {
      const err = error as {
        response?: { data?: { message?: string } };
        message?: string;
      };
      const message =
        err?.response?.data?.message ||
        err?.message ||
        'Failed to save project element default.';
      logger.error(
        'Failed to save project element default:',
        error instanceof Error ? error : { error },
      );
      setErrorMessage(message);
    } finally {
      setIsSaving(false);
    }
  }, [buildSettingsJson, id, item, name, sortOrder, loadItem, loadDiff]);

  const handleResetToGlobal = useCallback(async () => {
    if (!id) return;

    const confirmed = window.confirm(
      'Are you sure you want to reset this element default to the global default? ' +
        'This will overwrite your project-specific settings.',
    );
    if (!confirmed) return;

    try {
      setIsResetting(true);
      setErrorMessage('');
      setSuccessMessage('');

      await axios.post(`/project-element-defaults/${id}/reset`);

      setSuccessMessage('Successfully reset to global default.');
      await loadItem();
      await loadDiff();
    } catch (error: unknown) {
      const err = error as {
        response?: { data?: { message?: string } };
        message?: string;
      };
      const message =
        err?.response?.data?.message ||
        err?.message ||
        'Failed to reset to global default.';
      logger.error(
        'Failed to reset to global default:',
        error instanceof Error ? error : { error },
      );
      setErrorMessage(message);
    } finally {
      setIsResetting(false);
    }
  }, [id, loadItem, loadDiff]);

  // Extract stable callback reference for setField
  const setField = form.setField;

  // Handler for style section changes
  const handleStyleChange = useCallback(
    (prop: string, value: string) => {
      setField(prop as keyof typeof form.state, value);
    },
    [setField],
  );

  // Handler for effects section changes
  const handleEffectChange = useCallback(
    (prop: string, value: string) => {
      // Convert string 'true'/'false' to boolean for boolean fields
      if (
        prop === 'hoverReveal' ||
        prop === 'hoverRevealPersist' ||
        prop === 'hoverPersistOnClick'
      ) {
        setField(prop as keyof typeof form.state, (value === 'true') as never);
      } else {
        setField(prop as keyof typeof form.state, value as never);
      }
    },
    [setField],
  );

  // Handler for common section changes
  const handleCommonChange = useCallback(
    (field: string, value: string) => {
      setField(field as keyof typeof form.state, value);
    },
    [setField],
  );

  // Handler for type-specific section changes
  const handleTypeChange = useCallback(
    (field: string, value: string | boolean) => {
      setField(field as keyof typeof form.state, value as never);
    },
    [setField],
  );

  if (isLoading) {
    return (
      <>
        <Head>
          <title>{getPageTitle('Project Element Default')}</title>
        </Head>
        <SectionMain>
          <CardBox>
            <p className='text-sm text-gray-500'>Loading...</p>
          </CardBox>
        </SectionMain>
      </>
    );
  }

  if (!item) {
    return (
      <>
        <Head>
          <title>{getPageTitle('Project Element Default')}</title>
        </Head>
        <SectionMain>
          <CardBox>
            <p className='text-sm text-red-600'>
              {errorMessage || 'Project element default not found.'}
            </p>
            <Link
              href={`/project-element-defaults?projectId=${projectId}`}
              className='mt-4 inline-block text-sm text-blue-600 hover:underline'
            >
              Back to list
            </Link>
          </CardBox>
        </SectionMain>
      </>
    );
  }

  return (
    <>
      <Head>
        <title>{getPageTitle(`Edit: ${item.element_type}`)}</title>
      </Head>
      <SectionMain>
        <SectionTitleLineWithButton
          icon={mdiCog}
          title={`Edit: ${toHumanLabel(item.element_type)}`}
          main
        >
          <div className='flex gap-2'>
            <BaseButton
              color='warning'
              label={isResetting ? 'Resetting...' : 'Reset to Global'}
              icon={mdiSync}
              onClick={handleResetToGlobal}
              disabled={isResetting || isSaving || !diff?.hasGlobalDefault}
            />
            <BaseButton
              color='info'
              label={isSaving ? 'Saving...' : 'Save'}
              icon={mdiContentSave}
              onClick={handleSave}
              disabled={isSaving || isResetting}
            />
          </div>
        </SectionTitleLineWithButton>

        {errorMessage && (
          <div className='mb-4 rounded bg-red-50 p-3 text-sm text-red-600'>
            {errorMessage}
          </div>
        )}

        {successMessage && (
          <div className='mb-4 rounded bg-green-50 p-3 text-sm text-green-700'>
            {successMessage}
          </div>
        )}

        {diff?.isDifferent && (
          <div className='mb-4 rounded bg-yellow-50 p-3 text-sm text-yellow-700'>
            This project element default has been customized and differs from
            the global default.
            {diff.hasGlobalDefault &&
              ' Click "Reset to Global" to restore the global settings.'}
          </div>
        )}

        <CardBox>
          <div className='space-y-4'>
            <FormField label='Element Type'>
              <input
                type='text'
                className='rounded border border-gray-300 bg-gray-100 px-3 py-2 text-sm'
                value={toHumanLabel(item.element_type)}
                disabled
              />
            </FormField>

            <FormField label='Display Name'>
              <input
                type='text'
                className='rounded border border-gray-300 px-3 py-2 text-sm'
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder={toHumanLabel(item.element_type)}
              />
            </FormField>

            <FormField label='Sort Order'>
              <input
                type='number'
                className='rounded border border-gray-300 px-3 py-2 text-sm'
                value={sortOrder}
                onChange={(e) => setSortOrder(Number(e.target.value) || 0)}
              />
            </FormField>

            <FormField label='Snapshot Version'>
              <input
                type='text'
                className='rounded border border-gray-300 bg-gray-100 px-3 py-2 text-sm'
                value={item.snapshot_version || 1}
                disabled
              />
            </FormField>

            {/* Tabs */}
            <ElementSettingsTabs
              activeTab={activeTab}
              onTabChange={setActiveTab}
              tabs={SETTINGS_TABS}
            />

            {/* General Settings Tab */}
            {activeTab === 'general' && (
              <>
                <CommonSettingsSection
                  label={form.state.label}
                  xPercent={form.state.xPercent}
                  yPercent={form.state.yPercent}
                  appearDelaySec={form.state.appearDelaySec}
                  appearDurationSec={form.state.appearDurationSec}
                  onChange={handleCommonChange}
                />

                {/* Type-specific sections */}
                {form.isNavigationType && (
                  <NavigationSettingsSection
                    iconUrl={form.state.iconUrl}
                    navLabel={form.state.navLabel}
                    navLabelFontFamily={form.state.navLabelFontFamily}
                    navType={form.state.navType}
                    navDisabled={form.state.navDisabled}
                    targetPageId={form.state.targetPageId}
                    targetPageSlug={form.state.targetPageSlug}
                    transitionVideoUrl={form.state.transitionVideoUrl}
                    transitionReverseMode={form.state.transitionReverseMode}
                    reverseVideoUrl={form.state.reverseVideoUrl}
                    onChange={handleTypeChange}
                    context='project'
                    iconAssetOptions={iconAssetOptions}
                  />
                )}

                {form.isTooltipType && (
                  <TooltipSettingsSection
                    iconUrl={form.state.iconUrl}
                    tooltipTitle={form.state.tooltipTitle}
                    tooltipText={form.state.tooltipText}
                    tooltipTitleFontFamily={form.state.tooltipTitleFontFamily}
                    tooltipTextFontFamily={form.state.tooltipTextFontFamily}
                    onChange={handleTypeChange}
                    context='project'
                  />
                )}

                {form.isDescriptionType && (
                  <DescriptionSettingsSection
                    iconUrl={form.state.iconUrl}
                    descriptionTitle={form.state.descriptionTitle}
                    descriptionText={form.state.descriptionText}
                    descriptionTitleFontSize={
                      form.state.descriptionTitleFontSize
                    }
                    descriptionTextFontSize={form.state.descriptionTextFontSize}
                    descriptionTitleFontFamily={
                      form.state.descriptionTitleFontFamily
                    }
                    descriptionTextFontFamily={
                      form.state.descriptionTextFontFamily
                    }
                    descriptionTitleColor={form.state.descriptionTitleColor}
                    descriptionTextColor={form.state.descriptionTextColor}
                    onChange={handleTypeChange}
                    context='project'
                  />
                )}

                {form.isGalleryType && (
                  <GallerySettingsSection
                    galleryCards={form.state.galleryCards}
                    galleryTitleFontFamily={form.state.galleryTitleFontFamily}
                    galleryTextFontFamily={form.state.galleryTextFontFamily}
                    onAddCard={form.addGalleryCard}
                    onRemoveCard={form.removeGalleryCard}
                    onUpdateCard={form.updateGalleryCard}
                    onChange={handleTypeChange}
                    context='project'
                  />
                )}

                {form.isCarouselType && (
                  <CarouselSettingsSection
                    carouselPrevIconUrl={form.state.carouselPrevIconUrl}
                    carouselNextIconUrl={form.state.carouselNextIconUrl}
                    carouselCaptionFontFamily={
                      form.state.carouselCaptionFontFamily
                    }
                    carouselSlides={form.state.carouselSlides}
                    onAddSlide={form.addCarouselSlide}
                    onRemoveSlide={form.removeCarouselSlide}
                    onUpdateSlide={form.updateCarouselSlide}
                    onChange={handleTypeChange}
                    context='project'
                  />
                )}

                {form.isMediaType && (
                  <MediaSettingsSection
                    elementType={
                      currentElementType as 'video_player' | 'audio_player'
                    }
                    mediaUrl={form.state.mediaUrl}
                    mediaAutoplay={form.state.mediaAutoplay}
                    mediaLoop={form.state.mediaLoop}
                    mediaMuted={form.state.mediaMuted}
                    onChange={handleTypeChange}
                    context='project'
                  />
                )}
              </>
            )}

            {/* CSS Styles Tab */}
            {activeTab === 'css' && (
              <CardBox className='border border-gray-200 dark:border-dark-700'>
                <StyleSettingsSection
                  values={form.getStyleValues()}
                  onChange={handleStyleChange}
                />
              </CardBox>
            )}

            {/* Effects Tab */}
            {activeTab === 'effects' && (
              <CardBox className='border border-gray-200 dark:border-dark-700'>
                <EffectsSettingsSection
                  values={form.getEffectValues()}
                  onChange={handleEffectChange}
                />
              </CardBox>
            )}
          </div>
        </CardBox>

        <div className='mt-4'>
          <Link
            href={`/project-element-defaults?projectId=${projectId}`}
            className='text-sm text-blue-600 hover:underline'
          >
            Back to project element defaults list
          </Link>
        </div>
      </SectionMain>
    </>
  );
};

ProjectElementDefaultDetailsPage.getLayout = function getLayout(
  page: ReactElement,
) {
  return (
    <LayoutAuthenticated permission='UPDATE_PAGE_ELEMENTS'>
      {page}
    </LayoutAuthenticated>
  );
};

export default ProjectElementDefaultDetailsPage;
