import { useEffect, type ReactElement } from 'react';
import styled from '@lilith/ui-styled-components';
import { ChevronLeft, ChevronRight, MapPin, Star, X } from 'lucide-react';

import { photoBlobUrl } from '@/api/photos';
import type { Photo } from '@/types';

const Overlay = styled.div`
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
`;

const Frame = styled.div`
  position: relative;
  width: min(95vw, 1400px);
  height: min(90vh, 1000px);
  display: grid;
  grid-template-columns: 1fr 280px;
  gap: 0;
  background: #0b0b12;
  border: 1px solid #2a2a38;
  border-radius: 8px;
  overflow: hidden;
`;

const ImageWrap = styled.div`
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
  min-height: 0;
`;

const Img = styled.img`
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
`;

const Video = styled.video`
  max-width: 100%;
  max-height: 100%;
`;

const Sidebar = styled.aside`
  border-left: 1px solid #2a2a38;
  padding: 16px;
  color: #c4c4d4;
  font-size: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow-y: auto;
`;

const Title = styled.div`
  font-size: 14px;
  color: #e0e0f0;
  font-weight: 600;
  word-break: break-all;
`;

const MetaRow = styled.div`
  display: flex;
  align-items: center;
  gap: 6px;
  color: #8a8a9a;
`;

const TagList = styled.div`
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
`;

const Tag = styled.span`
  background: #1c1c26;
  border: 1px solid #2a2a38;
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 10px;
  color: #c9a84c;
`;

const ExifBox = styled.pre`
  background: #13131a;
  border: 1px solid #2a2a38;
  border-radius: 4px;
  padding: 8px;
  font-size: 10px;
  color: #8a8a9a;
  max-height: 200px;
  overflow: auto;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-all;
`;

const NavButton = styled.button<{ $side: 'left' | 'right' }>`
  position: absolute;
  top: 50%;
  ${(p) => (p.$side === 'left' ? 'left: 8px;' : 'right: 8px;')}
  transform: translateY(-50%);
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border: 1px solid #2a2a38;
  border-radius: 50%;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  cursor: pointer;

  &:disabled {
    opacity: 0.3;
    cursor: not-allowed;
  }
`;

const CloseButton = styled.button`
  position: absolute;
  top: 8px;
  right: 8px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border: 1px solid #2a2a38;
  border-radius: 50%;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  cursor: pointer;
  z-index: 2;
`;

export interface LightboxProps {
  photos: readonly Photo[];
  index: number;
  onClose: () => void;
  onIndexChange: (next: number) => void;
}

export function Lightbox({ photos, index, onClose, onIndexChange }: LightboxProps): ReactElement | null {
  const photo = photos[index];

  useEffect(() => {
    function onKey(e: KeyboardEvent): void {
      if (e.key === 'Escape') onClose();
      if (e.key === 'ArrowLeft' && index > 0) onIndexChange(index - 1);
      if (e.key === 'ArrowRight' && index < photos.length - 1) onIndexChange(index + 1);
    }
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [index, photos.length, onClose, onIndexChange]);

  if (!photo) return null;

  const isVideo = (photo.mediaKind ?? photo.mediaType) === 'video';
  const previewUrl = photoBlobUrl(photo.id, 'preview');
  const originalUrl = photoBlobUrl(photo.id, 'original');

  return (
    <Overlay onClick={onClose}>
      <Frame onClick={(e) => e.stopPropagation()}>
        <ImageWrap>
          {isVideo ? (
            <Video controls src={originalUrl} />
          ) : (
            <Img src={previewUrl} alt={photo.filename || photo.externalId} />
          )}
          <NavButton
            $side="left"
            disabled={index === 0}
            onClick={() => onIndexChange(index - 1)}
            aria-label="Previous"
          >
            <ChevronLeft size={20} />
          </NavButton>
          <NavButton
            $side="right"
            disabled={index === photos.length - 1}
            onClick={() => onIndexChange(index + 1)}
            aria-label="Next"
          >
            <ChevronRight size={20} />
          </NavButton>
          <CloseButton onClick={onClose} aria-label="Close">
            <X size={18} />
          </CloseButton>
        </ImageWrap>
        <Sidebar>
          <Title>{photo.filename || photo.externalId}</Title>
          {photo.takenAt && <MetaRow>{new Date(photo.takenAt).toLocaleString()}</MetaRow>}
          <MetaRow>
            {photo.width}×{photo.height}
            {photo.duration ? ` · ${photo.duration.toFixed(1)}s` : ''}
          </MetaRow>
          {photo.isFavorite && (
            <MetaRow>
              <Star size={12} fill="currentColor" color="#ffd166" /> Favorite
            </MetaRow>
          )}
          {(photo.latitude !== null && photo.longitude !== null) && (
            <MetaRow>
              <MapPin size={12} />
              {photo.locationName ?? `${photo.latitude.toFixed(4)}, ${photo.longitude.toFixed(4)}`}
            </MetaRow>
          )}
          {photo.faceCount > 0 && <MetaRow>{photo.faceCount} face{photo.faceCount === 1 ? '' : 's'}</MetaRow>}
          {photo.semanticTags && photo.semanticTags.length > 0 && (
            <TagList>
              {photo.semanticTags.map((t) => (
                <Tag key={t}>{t}</Tag>
              ))}
            </TagList>
          )}
          {photo.exif && Object.keys(photo.exif).length > 0 && (
            <ExifBox>{JSON.stringify(photo.exif, null, 2)}</ExifBox>
          )}
        </Sidebar>
      </Frame>
    </Overlay>
  );
}
