import { useEffect, useMemo, useState, useRef } from 'react';
import { Link } from 'react-router-dom';
import { heroImageChain, visualAssets } from '../assets/visualAssets';
import { loadPhotoManifest } from '../assets/photoManifest';
import { useRecipes } from '../hooks/useRecipes';
import { useTags } from '../hooks/useTags';
import { RecipeCard } from '../components/RecipeCard';
import { MissionControlPanel } from '../components/MissionControlPanel';
import { UiCard, UiSection, UiButton } from '../components/ui/primitives';
import type { HarnessStatus } from '../types/recipe';
import { radius } from '../theme';

type ViewMode = 'grid' | 'list';

interface PhotoManifestCategoryAsset {
  localPath?: string | null;
  remoteCandidate?: string | null;
}

interface PhotoManifest {
  assets?: {
    photos?: {
      list?: {
        default4x3?: string;
      };
      category?: Record<string, PhotoManifestCategoryAsset>;
    };
  };
}

const emptyStatus: HarnessStatus = {
  running: false,
  version: '-',
  uptime: 0,
};

const featureHighlights = [
  {
    title: 'Organize with tags',
    copy: 'Group your meals by cuisine, prep style, or dietary preference so finding dinner is instant.',
    image: 'https://images.pexels.com/photos/1279330/pexels-photo-1279330.jpeg?auto=compress&cs=tinysrgb&w=1200',
    fallback: '/assets/food/curated/pasta-plate.svg',
    eyebrow: 'Smart organization',
  },
  {
    title: 'Capture from the web',
    copy: 'Import recipe links and keep your best discoveries in one place instead of scattered bookmarks.',
    image: 'https://images.pexels.com/photos/1640774/pexels-photo-1640774.jpeg?auto=compress&cs=tinysrgb&w=1200',
    fallback: '/assets/food/curated/soup-bowl.svg',
    eyebrow: 'Collect recipes fast',
  },
  {
    title: 'Cook with confidence',
    copy: 'Use clear recipe cards and streamlined actions while planning, prepping, and cooking.',
    image: 'https://images.pexels.com/photos/70497/pexels-photo-70497.jpeg?auto=compress&cs=tinysrgb&w=1200',
    fallback: '/assets/food/curated/breakfast-toast.svg',
    eyebrow: 'Ready when you are',
  },
] as const;

function CardSkeleton() {
  return (
    <UiCard className="overflow-hidden">
      <div className="h-48 animate-pulse bg-[var(--surface-muted)]" />
      <div className="space-y-3 p-5">
        <div className="h-5 w-2/3 animate-pulse rounded bg-[var(--surface-muted)]" />
        <div className="h-3 w-full animate-pulse rounded bg-[var(--surface-muted)]" />
        <div className="h-3 w-5/6 animate-pulse rounded bg-[var(--surface-muted)]" />
        <div className="flex gap-2 pt-2">
          <div className="h-6 w-20 animate-pulse rounded-full bg-[var(--surface-muted)]" />
          <div className="h-6 w-20 animate-pulse rounded-full bg-[var(--surface-muted)]" />
        </div>
      </div>
    </UiCard>
  );
}

export function RecipeListPage() {
  const [searchTerm, setSearchTerm] = useState('');
  const [searchQuery, setSearchQuery] = useState('');
  const [selectedTagIds, setSelectedTagIds] = useState<number[]>([]);
  const [heroCandidateIndex, setHeroCandidateIndex] = useState(0);
  const [viewMode, setViewMode] = useState<ViewMode>('grid');
  const [photoManifest, setPhotoManifest] = useState<PhotoManifest | null>(null);
  
  // Infinite scroll sentinel ref
  const sentinelRef = useRef<HTMLDivElement>(null);

  const heroCandidates = heroImageChain();
  const heroSrc = heroCandidates[Math.min(heroCandidateIndex, heroCandidates.length - 1)];

  useEffect(() => {
    let active = true;

    loadPhotoManifest<PhotoManifest>()
      .then((manifest) => {
        if (active) setPhotoManifest(manifest);
      })
      .catch(() => {
        if (active) setPhotoManifest(null);
      });

    return () => {
      active = false;
    };
  }, []);

  const { recipes, loading, error, hasMore, loadMore } = useRecipes({
    search: searchQuery,
    limit: 20,
    tagIds: selectedTagIds,
  });

  const { tags, loading: tagsLoading } = useTags();

  // Infinite scroll observer
  useEffect(() => {
    if (!sentinelRef.current || !hasMore || loading) return;

    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting && hasMore && !loading) {
          loadMore();
        }
      },
      { threshold: 0.1, rootMargin: '100px' }
    );

    observer.observe(sentinelRef.current);

    return () => observer.disconnect();
  }, [hasMore, loading, loadMore]);

  const handleSearch = (e: React.FormEvent) => {
    e.preventDefault();
    setSearchQuery(searchTerm);
  };

  const handleClearSearch = () => {
    setSearchTerm('');
    setSearchQuery('');
  };

  const handleClearFilters = () => {
    setSearchTerm('');
    setSearchQuery('');
    setSelectedTagIds([]);
  };

  const handleClearSearchFilter = () => {
    setSearchTerm('');
    setSearchQuery('');
  };

  const handleToggleTagFilter = (tagId: number) => {
    setSelectedTagIds((prev) => (prev.includes(tagId) ? prev.filter((id) => id !== tagId) : [...prev, tagId]));
  };

  const handleClearTagFilter = (tagId: number) => {
    setSelectedTagIds((prev) => prev.filter((id) => id !== tagId));
  };

  const selectedTags = useMemo(
    () => tags.filter((tag) => selectedTagIds.includes(tag.id)),
    [tags, selectedTagIds],
  );

  const filteredRecipes = useMemo(() => {
    if (selectedTagIds.length === 0) return recipes;

    return recipes.filter((recipe) => {
      const recipeTagIds = recipe.tags.map((tag) => tag.id);
      return selectedTagIds.every((tagId) => recipeTagIds.includes(tagId));
    });
  }, [recipes, selectedTagIds]);
  const hasActiveFilters = Boolean(searchQuery) || selectedTagIds.length > 0;
  const allRecipesSelected = selectedTagIds.length === 0;
  const recipeCountLabel = `${filteredRecipes.length} recipe${filteredRecipes.length !== 1 ? 's' : ''}`;
  const activeViewLabel = viewMode === 'grid' ? 'Grid view active' : 'List view active';

  return (
    <div className="ui-page">
      <MissionControlPanel status={emptyStatus} />

      <UiSection className="relative mt-6 overflow-hidden p-0" padding="none">
        <div className="grid grid-cols-1 lg:grid-cols-2">
          <div className="flex flex-col justify-center gap-4 px-6 py-8 md:px-10 md:py-12">
            <p className="text-xs font-semibold uppercase tracking-[0.2em] text-[var(--color-primary)] md:text-sm">Your kitchen companion</p>
            <h1 className="text-3xl font-extrabold leading-tight text-[var(--text-h)] md:text-5xl">Plan meals faster and keep every favorite recipe organized</h1>
            <p className="max-w-lg text-sm text-[var(--text-dim)] md:text-base">
              Build your personal cookbook with better structure, quick tag filters, and easy capture from web links.
            </p>
            <div className="flex flex-wrap gap-3 pt-1">
              <Link
                to="/recipe/new"
                className="ui-btn ui-btn-primary inline-flex items-center gap-2 px-5 py-2.5"
                style={{ borderRadius: radius.md }}
              >
                Start a Recipe
              </Link>
              <a
                href="#recipes-grid"
                className="ui-btn ui-btn-secondary inline-flex items-center gap-2 px-5 py-2.5"
                style={{ borderRadius: radius.md }}
              >
                Browse Library
              </a>
            </div>
          </div>
          <div className="relative min-h-[260px] bg-[var(--surface-muted)] md:min-h-[320px] lg:min-h-full">
            <img
              src={heroSrc}
              alt={visualAssets.hero.alt}
              className="h-full w-full object-cover"
              onError={() => {
                if (heroCandidateIndex < heroCandidates.length - 1) {
                  setHeroCandidateIndex((current) => current + 1);
                }
              }}
            />
            <div
              className="pointer-events-none absolute inset-0"
              style={{ background: 'linear-gradient(to top, rgba(28, 25, 23, 0.45), rgba(28, 25, 23, 0.15), transparent)' }}
            />
            <div className="absolute bottom-4 left-4 rounded-full bg-white/90 px-4 py-1.5 text-sm font-semibold text-[var(--text)] shadow">
              {filteredRecipes.length} saved recipes
            </div>
          </div>
        </div>
      </UiSection>

      <section className="mt-6 grid grid-cols-1 gap-4 md:grid-cols-3">
        {featureHighlights.map((feature) => (
          <UiCard
            key={feature.title}
            className="overflow-hidden p-0"
          >
            <div className="relative h-36 bg-[var(--surface-muted)]">
              <img
                src={feature.image}
                alt=""
                aria-hidden="true"
                className="h-full w-full object-cover"
                loading="lazy"
                onError={(e) => {
                  e.currentTarget.src = feature.fallback;
                }}
              />
              <div
                className="pointer-events-none absolute inset-0"
                style={{ background: 'linear-gradient(to top, rgba(28, 25, 23, 0.5), rgba(28, 25, 23, 0.08), transparent)' }}
              />
              <p className="absolute bottom-2 left-3 text-xs font-semibold uppercase tracking-[0.08em] text-white/95">{feature.eyebrow}</p>
            </div>
            <div className="p-4">
              <h2 className="text-lg font-bold text-[var(--text-h)]">{feature.title}</h2>
              <p className="mt-1 text-sm text-[var(--text-dim)]">{feature.copy}</p>
            </div>
          </UiCard>
        ))}
      </section>

      <UiSection
        className="mb-8 mt-7 flex flex-col gap-4 px-5 py-6 md:px-6"
        padding="none"
      >
        <div className="flex flex-col gap-3 md:flex-row md:items-end md:justify-between">
          <div>
            <h2 className="mb-0 text-2xl font-extrabold text-[var(--text-h)]">Recipe Library</h2>
            <p className="mt-1 text-sm text-[var(--text-dim)]">Search, filter, and jump back into your most-used meals</p>
          </div>
          <div className="self-start md:text-right">
            <p className="mb-1 text-xs font-semibold uppercase tracking-[0.12em] text-[var(--text-dim)]">Layout</p>
            <div className="flex items-center gap-2 rounded-full border border-[var(--border)] bg-[var(--surface)] p-1">
              <button
                type="button"
                onClick={() => setViewMode('grid')}
                aria-pressed={viewMode === 'grid'}
                className={`rounded-full px-3 py-1.5 text-xs font-semibold transition ${
                  viewMode === 'grid'
                    ? 'bg-[var(--color-primary)] text-white'
                    : 'text-[var(--text-dim)] hover:bg-[var(--surface-muted)]'
                }`}
              >
                Grid
              </button>
              <button
                type="button"
                onClick={() => setViewMode('list')}
                aria-pressed={viewMode === 'list'}
                className={`rounded-full px-3 py-1.5 text-xs font-semibold transition ${
                  viewMode === 'list'
                    ? 'bg-[var(--color-primary)] text-white'
                    : 'text-[var(--text-dim)] hover:bg-[var(--surface-muted)]'
                }`}
              >
                List
              </button>
            </div>
            <p className="mt-1 text-xs text-[var(--text-dim)]">Changes the entire recipe library layout</p>
          </div>
        </div>

        <form onSubmit={handleSearch} className="mt-2 grid grid-cols-1 gap-3 md:grid-cols-[1fr_auto]">
          <label className="relative block" aria-label="Search recipes">
            <span className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-[var(--text-dim)]" aria-hidden="true">
              <svg viewBox="0 0 24 24" className="h-4 w-4" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <circle cx="11" cy="11" r="8" />
                <path d="m21 21-4.3-4.3" />
              </svg>
            </span>
            <input
              type="text"
              placeholder="Search title, ingredient, or tag"
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="ui-input pl-10 pr-10 text-base"
              style={{ borderRadius: radius.md, minHeight: 46 }}
            />
            {(searchTerm || searchQuery) && (
              <button
                type="button"
                onClick={handleClearSearch}
                className="absolute right-3 top-1/2 -translate-y-1/2 rounded-md p-1 text-[var(--text-dim)]/70 transition-colors hover:text-[var(--text-dim)] focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]"
                aria-label="Clear search"
              >
                ×
              </button>
            )}
          </label>
          <UiButton
            type="submit"
            className="px-6"
          >
            Search
          </UiButton>
        </form>

        {!tagsLoading && tags.length > 0 && (
          <div className="mt-1 flex flex-wrap items-center gap-2">
            <span className="mr-1 text-sm font-medium text-[var(--text)]">Filter by tag:</span>
            <div className="flex flex-1 flex-wrap gap-2">
              <button
                type="button"
                onClick={() => setSelectedTagIds([])}
                className={
                  allRecipesSelected
                    ? 'ui-chip border-transparent bg-[var(--color-primary)] px-3 py-1.5 text-sm font-semibold text-white'
                    : 'ui-chip px-3 py-1.5 text-sm font-medium text-[var(--text)] hover:bg-[var(--surface-muted)]'
                }
                style={{ borderRadius: radius.full }}
              >
                All Recipes
              </button>
              {tags.map((tag) => {
                const isSelected = selectedTagIds.includes(tag.id);
                return (
                  <button
                    type="button"
                    key={tag.id}
                    onClick={() => handleToggleTagFilter(tag.id)}
                    aria-pressed={isSelected}
                    className={
                      isSelected
                        ? 'ui-chip border-transparent px-3 py-1.5 text-sm font-semibold text-white shadow-sm ring-2 ring-[var(--color-primary)]/35 ring-offset-1 ring-offset-[var(--surface)]'
                        : 'ui-chip px-3 py-1.5 text-sm font-medium text-[var(--text)] hover:bg-[var(--surface-muted)]'
                    }
                    style={{
                      backgroundColor: isSelected ? tag.color || 'var(--color-primary)' : '',
                      borderRadius: radius.full,
                    }}
                  >
                    {isSelected ? `✓ ${tag.name}` : tag.name}
                  </button>
                );
              })}
            </div>
          </div>
        )}

        {hasActiveFilters && (
          <div className="mt-1 flex flex-wrap items-center gap-2 text-sm">
            <span className="text-[var(--text-dim)]">Active filters:</span>
            {searchQuery && (
              <span className="ui-badge inline-flex items-center gap-1.5 px-2 py-1">
                <span>Search: "{searchQuery}"</span>
                <button
                  type="button"
                  onClick={handleClearSearchFilter}
                  className="rounded-sm px-1 leading-none text-[var(--text-dim)] transition-colors hover:text-[var(--text)] focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]"
                  aria-label="Remove search filter"
                  title="Remove search filter"
                >
                  ×
                </button>
              </span>
            )}
            {selectedTags.map((tag) => (
              <span key={tag.id} className="ui-badge inline-flex items-center gap-1.5 px-2 py-1">
                <span>Tag: {tag.name}</span>
                <button
                  type="button"
                  onClick={() => handleClearTagFilter(tag.id)}
                  className="rounded-sm px-1 leading-none text-[var(--text-dim)] transition-colors hover:text-[var(--text)] focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]"
                  aria-label={`Remove ${tag.name} tag filter`}
                  title={`Remove ${tag.name} tag filter`}
                >
                  ×
                </button>
              </span>
            ))}
            <UiButton
              type="button"
              onClick={handleClearFilters}
              className="min-h-0 rounded-sm px-2 py-1 font-medium text-[var(--color-primary-dark)]"
            >
              Clear all filters
            </UiButton>
          </div>
        )}
      </UiSection>

      <UiSection
        className="mt-3 flex flex-col gap-3 border border-[var(--border)]/70 bg-[var(--surface)] px-4 py-3 md:flex-row md:items-center md:justify-between"
        padding="none"
      >
        <div>
          <p className="text-lg font-extrabold text-[var(--text-h)]">{recipeCountLabel}</p>
          <p className="text-sm text-[var(--text-dim)]">
            {hasActiveFilters ? 'Matching your current search and filters' : 'Available in your recipe library'}
          </p>
        </div>
        <div className="inline-flex items-center gap-2 self-start rounded-full border border-[var(--color-primary)]/30 bg-[var(--color-primary-light)] px-3 py-1.5 text-sm font-semibold text-[var(--color-primary-dark)] md:self-auto">
          <span aria-hidden="true">{viewMode === 'grid' ? '▦' : '☰'}</span>
          <span>{activeViewLabel}</span>
        </div>
      </UiSection>

      {error && (
        <div className="my-6 rounded-lg border border-[var(--color-error)]/25 bg-[var(--color-error-light)] p-4 text-center">
          <p className="text-[var(--color-error)]">
            <strong>Error:</strong> {error}
          </p>
        </div>
      )}

      {loading && recipes.length === 0 && (
        <div className="mt-6 grid grid-cols-1 gap-6 sm:grid-cols-2 xl:grid-cols-3">
          {Array.from({ length: 6 }).map((_, idx) => (
            <CardSkeleton key={idx} />
          ))}
        </div>
      )}

      {!loading && !error && filteredRecipes.length === 0 && (
        <div
          className="mx-auto flex max-w-xl flex-col items-center gap-2 rounded-xl border border-dashed border-[var(--color-primary)]/25 bg-gradient-to-br from-[var(--surface)] to-[var(--color-primary-light)] p-14 text-center shadow-card"
          style={{ borderRadius: radius.lg }}
        >
          <img
            src={hasActiveFilters ? '/assets/empty-state/no-results-search.svg' : '/assets/empty-state/no-recipes.svg'}
            alt=""
            aria-hidden="true"
            className="mb-2 h-28 w-28"
          />
          <h3 className="mb-2 text-xl font-bold text-[var(--text-h)]">{hasActiveFilters ? 'No recipes found' : 'No recipes yet'}</h3>
          <p className="mb-4 text-[var(--text-dim)]">{hasActiveFilters ? 'Try another keyword or clear filters.' : 'Start your cookbook with a first delicious recipe.'}</p>
          {!hasActiveFilters && (
            <Link
              to="/recipe/new"
              className="ui-btn ui-btn-primary px-6 py-3"
              style={{ borderRadius: radius.md }}
            >
              Add Your First Recipe
            </Link>
          )}
        </div>
      )}

      {filteredRecipes.length > 0 && (
        <>
          <div
            id="recipes-grid"
            className={`mt-5 transition-all ${
              viewMode === 'grid'
                ? 'grid grid-cols-1 gap-6 sm:grid-cols-2 xl:grid-cols-3'
                : 'flex flex-col gap-3 rounded-xl border-2 border-[var(--color-primary)]/30 bg-[var(--surface-muted)]/45 p-3 shadow-sm'
            }`}
          >
            {filteredRecipes.map((recipe) => (
              <RecipeCard key={recipe.id} recipe={recipe} tags={recipe.tags} viewMode={viewMode} photoManifest={photoManifest} />
            ))}
          </div>
          
          {/* Infinite scroll sentinel */}
          {hasMore && (
            <div ref={sentinelRef} className="mt-8 text-center">
              {loading && (
                <div className="text-sm text-[var(--text-dim)]">Loading more recipes...</div>
              )}
            </div>
          )}
          
          <div className="mt-7 text-center text-sm text-[var(--text-dim)]">
            Showing {filteredRecipes.length} recipe{filteredRecipes.length !== 1 ? 's' : ''}
          </div>
        </>
      )}
    </div>
  );
}
