import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import SwipeableView from '../../components/SwipeableView';
import PullToRefresh from '../../components/PullToRefresh';
import MasonryGrid from './MasonryGrid';
import HeroLightbox from './HeroLightbox';
import VideoTab from './VideoTab';
import RegionPinPicker from './RegionPinPicker';
import { getRegionAccent } from './MiniMap';
import { useIsMobile } from '../../hooks/useIsMobile';
import './AlbumDetail.css';

/* ─────────────────────────────────────────────
   AlbumDetail — full-screen album overlay
───────────────────────────────────────────── */
const ANIM_MS = 400;

const prefersReduced = () =>
  typeof window !== 'undefined' &&
  window.matchMedia('(prefers-reduced-motion: reduce)').matches;

export default function AlbumDetail({
  album,
  sourceRect,
  photos,
  photoSummary,
  loading,
  loadingMore,
  hasNext,
  error,
  onClose,
  onLoadMore,
  onReload,
  onCoverChange,
  regions,
}) {
  const isMobile = useIsMobile();

  /* ── Animation phases: enter → open → exit ── */
  const [phase, setPhase] = useState('enter');
  const [selectedPhotoIndex, setSelectedPhotoIndex] = useState(null);
  const [lightboxRect, setLightboxRect] = useState(null);
  const closingRef = useRef(false);

  /* ── Region editing ── */
  const [editingRegion, setEditingRegion] = useState(false);
  const [regionInput, setRegionInput] = useState('');
  const [regionSaving, setRegionSaving] = useState(false);
  const [regionMsg, setRegionMsg] = useState(null); // { type: 'ok'|'err', text }
  const [pinPickerOpen, setPinPickerOpen] = useState(false);
  const [savedRegionId, setSavedRegionId] = useState(null); // region id after save
  const regionInputRef = useRef(null);
  const regionMsgTimer = useRef(null);

  const regionNames = useMemo(() => {
    if (!regions?.features) return [];
    return regions.features
      .map((f) => f.properties?.name || f.properties?.id || '')
      .filter(Boolean);
  }, [regions]);

  const filteredSuggestions = useMemo(() => {
    if (!regionInput.trim()) return regionNames;
    const q = regionInput.toLowerCase();
    return regionNames.filter((n) => n.toLowerCase().includes(q));
  }, [regionInput, regionNames]);

  const handleRegionEditStart = useCallback(() => {
    setEditingRegion(true);
    setRegionInput(album?.regionName || '');
    setRegionMsg(null);
    setTimeout(() => regionInputRef.current?.focus(), 50);
  }, [album]);

  const handleRegionEditCancel = useCallback(() => {
    setEditingRegion(false);
    setRegionInput('');
    setRegionMsg(null);
  }, []);

  const handleRegionSave = useCallback(async (value) => {
    const name = (value ?? regionInput).trim();
    if (!name || !album?.name) return;
    if (name === album.regionName) {
      setEditingRegion(false);
      return;
    }
    setRegionSaving(true);
    try {
      const res = await fetch(
        `/api/travel/albums/${encodeURIComponent(album.name)}/region`,
        {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ region: name }),
        },
      );
      if (!res.ok) throw new Error(`${res.status}`);
      const data = await res.json();
      const newRegionId = data.new_region || name;
      setSavedRegionId(newRegionId);
      setRegionMsg({ type: 'ok', text: `→ ${name}` });
      setEditingRegion(false);
      onCoverChange?.(); // refresh album list
    } catch {
      setRegionMsg({ type: 'err', text: '변경 실패' });
    } finally {
      setRegionSaving(false);
    }
    if (regionMsgTimer.current) clearTimeout(regionMsgTimer.current);
    regionMsgTimer.current = setTimeout(() => setRegionMsg(null), 3000);
  }, [regionInput, album, onCoverChange]);

  const handleRegionKeyDown = useCallback((e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      handleRegionSave();
    } else if (e.key === 'Escape') {
      handleRegionEditCancel();
    }
  }, [handleRegionSave, handleRegionEditCancel]);

  const handleOpenPinPicker = useCallback(() => {
    setPinPickerOpen(true);
  }, []);

  const handlePinSave = useCallback(() => {
    onCoverChange?.(); // refresh regions + albums on map
  }, [onCoverChange]);

  // Enter → open
  useEffect(() => {
    if (prefersReduced()) {
      setPhase('open');
      return;
    }
    const raf = requestAnimationFrame(() => {
      requestAnimationFrame(() => setPhase('open'));
    });
    return () => cancelAnimationFrame(raf);
  }, []);

  /* ── Body scroll lock (only when lightbox NOT open) ── */
  useEffect(() => {
    if (selectedPhotoIndex != null) return; // lightbox handles its own
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = prev; };
  }, [selectedPhotoIndex]);

  /* ── ESC key (close album when lightbox not open) ── */
  useEffect(() => {
    const handler = (e) => {
      if (e.key === 'Escape' && selectedPhotoIndex == null && !editingRegion) {
        handleClose();
      }
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [selectedPhotoIndex, editingRegion]); // eslint-disable-line react-hooks/exhaustive-deps

  /* ── Close with exit animation ── */
  const handleClose = useCallback(() => {
    if (closingRef.current) return;
    closingRef.current = true;
    if (prefersReduced()) {
      onClose();
      return;
    }
    setPhase('exit');
    setTimeout(() => onClose(), ANIM_MS);
  }, [onClose]);

  /* ── Photo selection → open lightbox ── */
  const handleSelectPhoto = useCallback((e, index) => {
    const el = e?.currentTarget || e?.target;
    const rect = el ? el.getBoundingClientRect() : null;
    setLightboxRect(rect);
    setSelectedPhotoIndex(index);
  }, []);

  const handleLightboxClose = useCallback(() => {
    setSelectedPhotoIndex(null);
    setLightboxRect(null);
  }, []);

  const handleLightboxNavigate = useCallback((idx) => {
    setSelectedPhotoIndex(idx);
  }, []);

  /* ── Derived ── */
  const regionAccent = getRegionAccent(album?.region || album?.id || '');

  // Determine if the album's region is a custom region missing coordinates
  const currentRegionId = savedRegionId || album?.region || album?.id || '';
  const needsPin = useMemo(() => {
    if (!currentRegionId || !regions?.features) return false;
    const feature = regions.features.find((f) => {
      const rid = f.properties?.id || f.properties?.name || '';
      return rid.toLowerCase() === currentRegionId.toLowerCase();
    });
    if (!feature) return true; // region not in GeoJSON at all → needs pin
    if (feature.properties?.custom && !feature.geometry) return true; // custom without coords
    return false;
  }, [currentRegionId, regions]);

  // Coords of existing pin (for initialCoords in picker)
  const existingCoords = useMemo(() => {
    if (!currentRegionId || !regions?.features) return null;
    const feature = regions.features.find((f) => {
      const rid = f.properties?.id || f.properties?.name || '';
      return rid.toLowerCase() === currentRegionId.toLowerCase();
    });
    if (feature?.geometry?.type === 'Point') return feature.geometry.coordinates;
    return null;
  }, [currentRegionId, regions]);

  const photoCountLabel = photoSummary?.total
    ? `${photoSummary.total} photos`
    : photos?.length
      ? `${photos.length}${hasNext ? '+' : ''}`
      : '';

  /* ── Phase → class ── */
  const cls = [
    'album-detail',
    phase === 'open' && 'album-detail--open',
    phase === 'exit' && 'album-detail--exit',
  ].filter(Boolean).join(' ');

  /* ── Tab content: Photos ── */
  const photosContent = (
    <div className="album-detail__body">
      {loading ? (
        <div className="album-detail__loading">
          <span className="album-detail__dot" />
          <span className="album-detail__dot" />
          <span className="album-detail__dot" />
        </div>
      ) : error ? (
        <div className="album-detail__error">
          <span className="album-detail__error-text">{error}</span>
        </div>
      ) : !photos || photos.length === 0 ? (
        <div className="album-detail__empty">
          <span className="album-detail__empty-text">No photos</span>
        </div>
      ) : (
        <PullToRefresh onRefresh={onReload}>
          <MasonryGrid
            photos={photos}
            onSelectPhoto={handleSelectPhoto}
            onLoadMore={onLoadMore}
            hasNext={hasNext}
            isLoadingMore={loadingMore}
            regionAccent={regionAccent}
          />
        </PullToRefresh>
      )}
    </div>
  );

  /* ── Tab content: Video ── */
  const videoContent = (
    <div className="album-detail__body">
      <VideoTab />
    </div>
  );

  /* ── Tabs ── */
  const tabLabel = `사진${photoCountLabel ? ` (${photoCountLabel})` : ''}`;
  const tabs = [
    { key: 'photos', label: tabLabel, content: photosContent },
    { key: 'video',  label: '영상',    content: videoContent },
  ];

  return (
    <>
      <div className={cls}>
        {/* Header */}
        <div className="album-detail__header">
          <button
            className="album-detail__back"
            onClick={handleClose}
            aria-label="Back"
          >
            <svg width="18" height="18" viewBox="0 0 18 18" fill="none">
              <path
                d="M11 4L6 9l5 5"
                stroke="currentColor"
                strokeWidth="1.5"
                strokeLinecap="round"
                strokeLinejoin="round"
              />
            </svg>
          </button>

          <div className="album-detail__title-group">
            <span className="album-detail__name">{album?.name || ''}</span>

            {/* Region label / editor */}
            {editingRegion ? (
              <div className="album-detail__region-editor">
                <input
                  ref={regionInputRef}
                  className="album-detail__region-input"
                  type="text"
                  value={regionInput}
                  onChange={(e) => setRegionInput(e.target.value)}
                  onKeyDown={handleRegionKeyDown}
                  placeholder="지역명 입력…"
                  disabled={regionSaving}
                />
                {filteredSuggestions.length > 0 && (
                  <ul className="album-detail__region-suggestions">
                    {filteredSuggestions.map((name) => (
                      <li key={name}>
                        <button
                          className="album-detail__region-suggestion"
                          onMouseDown={(e) => e.preventDefault()}
                          onClick={() => handleRegionSave(name)}
                        >
                          {name}
                        </button>
                      </li>
                    ))}
                  </ul>
                )}
                <button
                  className="album-detail__region-cancel"
                  onClick={handleRegionEditCancel}
                  aria-label="취소"
                >
                  ✕
                </button>
              </div>
            ) : (
              <span className="album-detail__region-row">
                <button
                  className="album-detail__region album-detail__region--editable"
                  onClick={handleRegionEditStart}
                  title="클릭하여 지역 변경"
                >
                  {regionMsg
                    ? <span className={regionMsg.type === 'ok' ? 'album-detail__region-ok' : 'album-detail__region-err'}>{regionMsg.text}</span>
                    : (album?.regionName || '미분류')
                  }
                  <svg className="album-detail__region-edit-icon" width="10" height="10" viewBox="0 0 10 10" fill="none">
                    <path d="M7.5 1.5l1 1-5.5 5.5H2V7z" stroke="currentColor" strokeWidth="0.8" strokeLinejoin="round"/>
                  </svg>
                </button>
                {(needsPin || (regionMsg?.type === 'ok' && savedRegionId)) && (
                  <button
                    className="album-detail__pin-btn"
                    onClick={handleOpenPinPicker}
                    title="지도에 위치 지정"
                  >
                    <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
                      <path d="M6 1C4.07 1 2.5 2.57 2.5 4.5 2.5 7.25 6 11 6 11s3.5-3.75 3.5-6.5C9.5 2.57 7.93 1 6 1zm0 4.75a1.25 1.25 0 110-2.5 1.25 1.25 0 010 2.5z" fill="currentColor"/>
                    </svg>
                    위치 지정
                  </button>
                )}
              </span>
            )}
          </div>

          {photoCountLabel && (
            <span className="album-detail__count">{photoCountLabel}</span>
          )}
        </div>

        {/* Tabs */}
        <SwipeableView tabs={tabs} />
      </div>

      {/* Pin Picker */}
      {pinPickerOpen && currentRegionId && (
        <RegionPinPicker
          regionId={currentRegionId}
          regionName={album?.regionName || currentRegionId}
          initialCoords={existingCoords}
          accent={regionAccent}
          onSave={handlePinSave}
          onClose={() => setPinPickerOpen(false)}
        />
      )}

      {/* Lightbox */}
      {selectedPhotoIndex != null && photos?.length > 0 && (
        <HeroLightbox
          photos={photos}
          selectedIndex={selectedPhotoIndex}
          albumName={album?.name}
          regionId={album?.region || album?.id}
          sourceRect={lightboxRect}
          hasNext={hasNext}
          loadingMore={loadingMore}
          onClose={handleLightboxClose}
          onNavigate={handleLightboxNavigate}
          onLoadMore={onLoadMore}
          onCoverChange={onCoverChange}
        />
      )}
    </>
  );
}
