import { useEffect, useRef, useState, type ChangeEvent, type CSSProperties } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
  AlertTriangle,
  Check,
  Download,
  ExternalLink,
  Home,
  Image as ImageIcon,
  Loader2,
  RefreshCw,
  Server,
  Sparkles,
  Upload,
  WandSparkles,
} from 'lucide-react';
import { useMarketingStore } from '@/store/useMarketingStore';
import {
  DREAM_WEAVER_URL,
  checkDreamWeaverHealth,
  fetchDreamWeaverResult,
  getDreamWeaverStatus,
  submitDreamWeaverJob,
  type DreamWeaverHealth,
  type DreamWeaverJobResponse,
  type DreamWeaverStatusResponse,
} from '@/lib/dreamWeaverApi';

const GLASS: CSSProperties = {
  background: 'rgba(8, 10, 18, 0.82)',
  border: '1px solid rgba(59,130,246,0.14)',
  backdropFilter: 'blur(24px)',
  WebkitBackdropFilter: 'blur(24px)',
  boxShadow: '0 0 0 1px rgba(255,255,255,0.04), 0 4px 32px rgba(0,0,0,0.55)',
};

const INNER: CSSProperties = {
  background: 'rgba(255,255,255,0.04)',
  border: '1px solid rgba(255,255,255,0.07)',
};

const ROOM_TYPES = [
  { id: 'bedroom', label: 'Bedroom' },
  { id: 'living_room', label: 'Living Room' },
  { id: 'bathroom', label: 'Bathroom' },
  { id: 'kitchen', label: 'Kitchen' },
  { id: 'dining_room', label: 'Dining Room' },
  { id: 'home_office', label: 'Office' },
  { id: 'hallway', label: 'Hallway' },
  { id: 'balcony', label: 'Balcony' },
] as const;

type ProcessingState = 'idle' | 'checking' | 'submitting' | 'rendering' | 'downloading';

interface DreamWeaverOutput {
  id: string;
  roomLabel: string;
  keywords: string;
  imageUrl: string;
  createdAt: Date;
}

function sleep(ms: number) {
  return new Promise((resolve) => window.setTimeout(resolve, ms));
}

function isReadyStatus(status: DreamWeaverStatusResponse) {
  const normalized = status.status?.toLowerCase() ?? '';
  return Boolean(status.ready) || ['ready', 'completed', 'complete', 'succeeded', 'success', 'finished'].includes(normalized);
}

function isFailedStatus(status: DreamWeaverStatusResponse) {
  const normalized = status.status?.toLowerCase() ?? '';
  return ['failed', 'error', 'cancelled', 'canceled'].includes(normalized);
}

function statusLabel(state: ProcessingState, health: DreamWeaverHealth | null) {
  if (state === 'checking') return 'Checking gateway';
  if (state === 'submitting') return 'Submitting render';
  if (state === 'rendering') return 'ComfyUI rendering';
  if (state === 'downloading') return 'Fetching result';
  if (!health) return 'Gateway unknown';
  if (health.online && health.routeMounted && health.comfyuiOnline === false) return 'Gateway online · ComfyUI offline';
  if (health.online && health.routeMounted && health.comfyuiOnline && health.checkpointReady === false) return 'Gateway online · Model missing';
  return health.online && health.routeMounted ? 'Gateway online' : 'Gateway offline';
}

function ResultActions({ output }: { output: DreamWeaverOutput }) {
  function downloadResult() {
    const anchor = document.createElement('a');
    anchor.href = output.imageUrl;
    anchor.download = `dream-weaver-${output.id}.png`;
    anchor.click();
  }

  return (
    <div className="flex items-center gap-2">
      <button
        type="button"
        onClick={downloadResult}
        className="h-9 w-9 rounded-xl flex items-center justify-center transition-colors hover:bg-white/10"
        style={INNER}
        title="Download generated image"
      >
        <Download className="w-4 h-4 text-white/75" />
      </button>
      <button
        type="button"
        onClick={() => window.open(output.imageUrl, '_blank', 'noopener,noreferrer')}
        className="h-9 w-9 rounded-xl flex items-center justify-center transition-colors hover:bg-white/10"
        style={INNER}
        title="Open generated image"
      >
        <ExternalLink className="w-4 h-4 text-white/75" />
      </button>
    </div>
  );
}

export function CatalystDreamWeaverTab() {
  const { pushLiveEvent } = useMarketingStore();
  const fileInputRef = useRef<HTMLInputElement>(null);
  const objectUrlsRef = useRef<Set<string>>(new Set());

  const [sourceFile, setSourceFile] = useState<File | null>(null);
  const [sourcePreview, setSourcePreview] = useState<string | null>(null);
  const [selectedRoomType, setSelectedRoomType] = useState<(typeof ROOM_TYPES)[number]['id']>('bedroom');
  const [keywords, setKeywords] = useState('');
  const [health, setHealth] = useState<DreamWeaverHealth | null>(null);
  const [processingState, setProcessingState] = useState<ProcessingState>('checking');
  const [progress, setProgress] = useState('Checking Dream Weaver gateway...');
  const [error, setError] = useState<string | null>(null);
  const [currentOutput, setCurrentOutput] = useState<DreamWeaverOutput | null>(null);
  const [history, setHistory] = useState<DreamWeaverOutput[]>([]);

  const isProcessing = processingState !== 'idle' && processingState !== 'checking';
  const roomLabel = ROOM_TYPES.find((room) => room.id === selectedRoomType)?.label ?? 'Bedroom';

  useEffect(() => {
    void refreshHealth();
    return () => {
      objectUrlsRef.current.forEach((url) => URL.revokeObjectURL(url));
      objectUrlsRef.current.clear();
    };
  }, []);

  function rememberObjectUrl(blobOrFile: Blob) {
    const url = URL.createObjectURL(blobOrFile);
    objectUrlsRef.current.add(url);
    return url;
  }

  function setSourceFromFile(file: File) {
    if (!file.type.startsWith('image/')) {
      setError('Dream Weaver needs a source room image.');
      return;
    }
    const previewUrl = rememberObjectUrl(file);
    setSourceFile(file);
    setSourcePreview(previewUrl);
    setCurrentOutput(null);
    setError(null);
  }

  function handleFileChange(event: ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    if (file) {
      setSourceFromFile(file);
    }
    event.target.value = '';
  }

  async function refreshHealth() {
    setProcessingState('checking');
    setProgress('Checking Dream Weaver gateway...');
    const nextHealth = await checkDreamWeaverHealth();
    setHealth(nextHealth);
    setProcessingState('idle');
    setProgress(nextHealth.online && nextHealth.routeMounted
      ? nextHealth.comfyuiOnline === false
        ? `Gateway is online and the Dream Weaver route is mounted. ComfyUI is offline${nextHealth.comfyuiUrl ? ` at ${nextHealth.comfyuiUrl}` : ''}.`
        : nextHealth.checkpointReady === false
          ? `ComfyUI is online${nextHealth.comfyuiUrl ? ` at ${nextHealth.comfyuiUrl}` : ''}, but no checkpoint model is installed. Hydrate RealVisXL into ComfyUI/models/checkpoints.`
        : 'Gateway is online and the Dream Weaver route is mounted.'
      : nextHealth.detail ?? 'Dream Weaver gateway is not reachable.');
  }

  async function pollUntilReady(job: DreamWeaverJobResponse) {
    let latestResultUrl = job.result_url;
    for (let attempt = 1; attempt <= 150; attempt += 1) {
      const status = await getDreamWeaverStatus(job);
      latestResultUrl = status.result_url ?? latestResultUrl;
      setProgress(status.status ? `Render ${status.status} · poll ${attempt}/150` : `Render queued · poll ${attempt}/150`);

      if (isReadyStatus(status)) {
        return latestResultUrl;
      }
      if (isFailedStatus(status) || status.error) {
        throw new Error(status.error ?? `Dream Weaver render ${status.status ?? 'failed'}.`);
      }
      await sleep(2000);
    }
    throw new Error('Dream Weaver timed out after 5 minutes.');
  }

  async function generate() {
    if (!sourceFile || isProcessing) return;
    setError(null);
    setCurrentOutput(null);

    try {
      setProcessingState('submitting');
      setProgress(`Submitting ${roomLabel.toLowerCase()} staging request...`);
      const job = await submitDreamWeaverJob({
        image: sourceFile,
        roomType: selectedRoomType,
        keywords,
      });

      setProcessingState('rendering');
      setProgress(`Job ${job.job_id} accepted. Waiting for ComfyUI output...`);
      const resultUrl = await pollUntilReady(job);

      setProcessingState('downloading');
      setProgress('Fetching generated image...');
      const resultBlob = await fetchDreamWeaverResult(job.job_id, resultUrl);
      const imageUrl = rememberObjectUrl(resultBlob);
      const output: DreamWeaverOutput = {
        id: job.job_id,
        roomLabel,
        keywords: keywords.trim(),
        imageUrl,
        createdAt: new Date(),
      };

      setCurrentOutput(output);
      setHistory((items) => [output, ...items].slice(0, 6));
      setProgress('Dream Weaver render complete.');
      pushLiveEvent({
        id: `dw-${job.job_id}-${Date.now()}`,
        type: 'create',
        campaignName: 'Dream Weaver',
        message: `${roomLabel} staging render completed.`,
        timestamp: new Date(),
      });
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Dream Weaver render failed.';
      setError(message);
      setProgress(message);
      pushLiveEvent({
        id: `dw-error-${Date.now()}`,
        type: 'alert',
        campaignName: 'Dream Weaver',
        message,
        timestamp: new Date(),
      });
    } finally {
      setProcessingState('idle');
    }
  }

  return (
    <div className="space-y-5">
      <motion.div
        className="relative rounded-2xl p-5 overflow-hidden"
        style={GLASS}
        initial={{ opacity: 0, y: 16, scale: 0.97 }}
        animate={{ opacity: 1, y: 0, scale: 1 }}
        transition={{ duration: 0.35, ease: [0.4, 0, 0.2, 1] }}
      >
        <div className="absolute inset-x-0 top-0 h-px pointer-events-none"
          style={{ background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.10), transparent)' }} />
        <div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
          <div>
            <h3 className="text-sm font-semibold text-white mb-0.5 flex items-center gap-2">
              <WandSparkles className="w-4 h-4 text-blue-400" /> Dream Weaver
            </h3>
            <p className="text-xs" style={{ color: 'rgba(148,163,184,0.55)' }}>
              Room image transformation pipeline using the same Dream Weaver gateway as the iPad app.
            </p>
          </div>
          <div className="flex items-center gap-2">
            <div className="flex items-center gap-2 rounded-xl px-3 py-2 text-xs" style={INNER}>
              <span className={`h-2 w-2 rounded-full ${health?.online && health.routeMounted ? 'bg-green-400' : 'bg-red-400'}`} />
              <span className="text-white/75">{statusLabel(processingState, health)}</span>
            </div>
            <button
              type="button"
              onClick={() => void refreshHealth()}
              className="h-9 w-9 rounded-xl flex items-center justify-center transition-colors hover:bg-white/10"
              style={INNER}
              title="Check Dream Weaver gateway"
            >
              <RefreshCw className={`w-4 h-4 text-white/75 ${processingState === 'checking' ? 'animate-spin' : ''}`} />
            </button>
          </div>
        </div>
      </motion.div>

      <div className="grid grid-cols-1 xl:grid-cols-[0.95fr_1.05fr] gap-5">
        <motion.div
          className="relative rounded-2xl p-5 overflow-hidden"
          style={GLASS}
          initial={{ opacity: 0, y: 16, scale: 0.97 }}
          animate={{ opacity: 1, y: 0, scale: 1 }}
          transition={{ duration: 0.35, delay: 0.05, ease: [0.4, 0, 0.2, 1] }}
        >
          <div className="space-y-5">
            <div>
              <h3 className="text-sm font-semibold text-white flex items-center gap-2">
                <ImageIcon className="w-4 h-4 text-blue-400" /> Source Room
              </h3>
              <p className="text-xs mt-1" style={{ color: 'rgba(148,163,184,0.55)' }}>
                Upload a ground-truth room photograph, choose the target room type, then add optional styling keywords.
              </p>
            </div>

            <button
              type="button"
              onClick={() => fileInputRef.current?.click()}
              onDragOver={(event) => event.preventDefault()}
              onDrop={(event) => {
                event.preventDefault();
                const file = event.dataTransfer.files?.[0];
                if (file) setSourceFromFile(file);
              }}
              className="relative w-full min-h-[300px] rounded-2xl overflow-hidden flex items-center justify-center text-left transition-colors hover:border-blue-400/40"
              style={{ ...INNER, background: sourcePreview ? 'rgba(255,255,255,0.02)' : 'rgba(255,255,255,0.025)' }}
            >
              {sourcePreview ? (
                <img src={sourcePreview} alt="Selected source room" className="absolute inset-0 h-full w-full object-cover" />
              ) : (
                <div className="flex flex-col items-center gap-3 text-center px-6">
                  <div className="h-12 w-12 rounded-2xl flex items-center justify-center" style={INNER}>
                    <Upload className="h-5 w-5 text-blue-400" />
                  </div>
                  <div>
                    <p className="text-sm font-semibold text-white">Upload room image</p>
                    <p className="text-xs mt-1" style={{ color: 'rgba(148,163,184,0.55)' }}>
                      Click to browse or drop a photo here.
                    </p>
                  </div>
                </div>
              )}
              <input ref={fileInputRef} type="file" accept="image/*" className="hidden" onChange={handleFileChange} />
            </button>

            <div>
              <p className="text-xs font-medium uppercase tracking-widest mb-2" style={{ color: 'rgba(148,163,184,0.65)' }}>
                Room type
              </p>
              <div className="grid grid-cols-2 md:grid-cols-4 gap-2">
                {ROOM_TYPES.map((room) => {
                  const selected = selectedRoomType === room.id;
                  return (
                    <button
                      key={room.id}
                      type="button"
                      onClick={() => setSelectedRoomType(room.id)}
                      className="rounded-xl px-3 py-2 text-sm font-medium flex items-center gap-2 transition-colors"
                      style={{
                        background: selected ? 'rgba(59,130,246,0.18)' : 'rgba(255,255,255,0.04)',
                        border: selected ? '1px solid rgba(59,130,246,0.38)' : '1px solid rgba(255,255,255,0.07)',
                        color: selected ? '#fff' : 'rgba(226,232,240,0.72)',
                      }}
                    >
                      <Home className="w-3.5 h-3.5 text-blue-400" />
                      <span>{room.label}</span>
                    </button>
                  );
                })}
              </div>
            </div>

            <div>
              <label className="text-xs font-medium uppercase tracking-widest mb-2 block" style={{ color: 'rgba(148,163,184,0.65)' }}>
                Keywords
              </label>
              <textarea
                value={keywords}
                onChange={(event) => setKeywords(event.target.value)}
                placeholder="gold, marble, luxury, soft daylight"
                rows={3}
                className="w-full resize-none rounded-xl px-3 py-2 text-sm text-white placeholder-white/20 outline-none focus:border-blue-400/50"
                style={INNER}
              />
            </div>

            <AnimatePresence>
              {error && (
                <motion.div
                  className="rounded-xl p-3 flex items-start gap-2"
                  style={{ background: 'rgba(239,68,68,0.12)', border: '1px solid rgba(239,68,68,0.25)' }}
                  initial={{ opacity: 0, y: -6 }}
                  animate={{ opacity: 1, y: 0 }}
                  exit={{ opacity: 0, y: -6 }}
                >
                  <AlertTriangle className="w-4 h-4 text-red-400 mt-0.5 flex-shrink-0" />
                  <p className="text-sm text-red-200 leading-relaxed">{error}</p>
                </motion.div>
              )}
            </AnimatePresence>

            <div className="flex items-center justify-between gap-3 rounded-2xl p-3" style={INNER}>
              <div className="min-w-0">
                <p className="text-xs font-medium text-white truncate">{progress}</p>
                <p className="text-[11px] mt-1 truncate" style={{ color: 'rgba(148,163,184,0.5)' }}>
                  Gateway: {DREAM_WEAVER_URL}
                </p>
              </div>
              <button
                type="button"
                onClick={() => void generate()}
                disabled={!sourceFile || isProcessing || health?.routeMounted === false || health?.comfyuiOnline === false || health?.checkpointReady === false}
                className="h-11 px-5 rounded-xl text-sm font-semibold flex items-center justify-center gap-2 disabled:opacity-45 disabled:cursor-not-allowed transition-colors"
                style={{ background: 'hsl(var(--accent))', color: 'hsl(var(--accent-fg))' }}
              >
                {isProcessing ? <Loader2 className="w-4 h-4 animate-spin" /> : <Sparkles className="w-4 h-4" />}
                Generate
              </button>
            </div>
          </div>
        </motion.div>

        <motion.div
          className="relative rounded-2xl p-5 overflow-hidden"
          style={GLASS}
          initial={{ opacity: 0, y: 16, scale: 0.97 }}
          animate={{ opacity: 1, y: 0, scale: 1 }}
          transition={{ duration: 0.35, delay: 0.1, ease: [0.4, 0, 0.2, 1] }}
        >
          <div className="flex items-center justify-between gap-3 mb-4">
            <div>
              <h3 className="text-sm font-semibold text-white flex items-center gap-2">
                <WandSparkles className="w-4 h-4 text-blue-400" /> Generated Staging
              </h3>
              <p className="text-xs mt-1" style={{ color: 'rgba(148,163,184,0.55)' }}>
                The result appears here as soon as the gateway marks the job ready.
              </p>
            </div>
            {currentOutput && <ResultActions output={currentOutput} />}
          </div>

          <div className="relative min-h-[460px] rounded-2xl overflow-hidden flex items-center justify-center" style={INNER}>
            {currentOutput ? (
              <img src={currentOutput.imageUrl} alt={`${currentOutput.roomLabel} Dream Weaver result`} className="absolute inset-0 h-full w-full object-contain bg-black" />
            ) : (
              <div className="flex flex-col items-center gap-3 text-center px-8">
                <div className="h-14 w-14 rounded-2xl flex items-center justify-center" style={INNER}>
                  {isProcessing ? <Loader2 className="h-6 w-6 text-blue-400 animate-spin" /> : <WandSparkles className="h-6 w-6 text-blue-400" />}
                </div>
                <div>
                  <p className="text-sm font-semibold text-white">{isProcessing ? 'Dream Weaver is rendering' : 'No generated image yet'}</p>
                  <p className="text-xs mt-1 max-w-md" style={{ color: 'rgba(148,163,184,0.55)' }}>
                    Upload a source image and generate a staging render to populate this canvas.
                  </p>
                </div>
              </div>
            )}
          </div>

          {history.length > 0 && (
            <div className="mt-5">
              <div className="flex items-center justify-between mb-3">
                <p className="text-xs font-medium uppercase tracking-widest" style={{ color: 'rgba(148,163,184,0.65)' }}>
                  Recent renders
                </p>
                <span className="text-[11px]" style={{ color: 'rgba(148,163,184,0.45)' }}>{history.length}/6</span>
              </div>
              <div className="grid grid-cols-2 md:grid-cols-3 gap-3">
                {history.map((item) => (
                  <button
                    key={item.id}
                    type="button"
                    onClick={() => setCurrentOutput(item)}
                    className="group rounded-xl overflow-hidden text-left transition-colors hover:border-blue-400/40"
                    style={INNER}
                  >
                    <div className="aspect-[4/3] bg-black overflow-hidden">
                      <img src={item.imageUrl} alt={item.roomLabel} className="h-full w-full object-cover group-hover:scale-105 transition-transform duration-300" />
                    </div>
                    <div className="p-3">
                      <div className="flex items-center gap-1.5 text-xs font-semibold text-white">
                        <Check className="w-3.5 h-3.5 text-green-400" />
                        {item.roomLabel}
                      </div>
                      <p className="text-[11px] mt-1 truncate" style={{ color: 'rgba(148,163,184,0.55)' }}>
                        {item.keywords || item.createdAt.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
                      </p>
                    </div>
                  </button>
                ))}
              </div>
            </div>
          )}
        </motion.div>
      </div>

      <motion.div
        className="relative rounded-2xl p-5 overflow-hidden"
        style={GLASS}
        initial={{ opacity: 0, y: 16, scale: 0.97 }}
        animate={{ opacity: 1, y: 0, scale: 1 }}
        transition={{ duration: 0.35, delay: 0.15, ease: [0.4, 0, 0.2, 1] }}
      >
        <div className="flex items-center justify-between gap-3">
          <h3 className="text-sm font-semibold text-white flex items-center gap-2">
            <Server className="w-4 h-4 text-blue-400" /> Gateway Contract
          </h3>
          <span className="text-xs font-medium" style={{ color: health?.routeMounted ? '#4ade80' : '#f87171' }}>
            {health?.routeMounted ? 'Route mounted' : 'Route not verified'}
          </span>
        </div>
        <div className="mt-4 grid grid-cols-1 md:grid-cols-3 gap-3">
          {['POST /dream-weaver', 'GET /dream-weaver/status/{job_id}', 'GET /dream-weaver/result/{job_id}'].map((endpoint) => (
            <div key={endpoint} className="rounded-xl p-3" style={INNER}>
              <p className="text-xs font-mono text-blue-200">{endpoint}</p>
            </div>
          ))}
        </div>
      </motion.div>
    </div>
  );
}
