import { useState, useCallback, useEffect } from 'preact/hooks';
import './Recom.css';
import { route } from 'preact-router';
import { PipelineProgress } from '../components/PipelineProgress.js';
import { RecommendationCard } from '../components/RecommendationCard.js';
import { Sidebar } from '../components/Sidebar.js';
import { NewRecommendationModal } from '../components/NewRecommendationModal.js';
import { useRecommendationsContext } from '../context/RecommendationsContext.js';
import { useSSE } from '../hooks/useSSE.js';
import { getRecommendation } from '../api/client.js';
import type { Recommendation, SSEEvent, StageMap, PipelineStage } from '../types/index.js';

interface RecomProps {
  id: string;
  path?: string;
}

const DEFAULT_STAGES: StageMap = {
  interpreter: 'pending',
  retrieval: 'pending',
  ranking: 'pending',
  curator: 'pending',
};

const STAGE_ORDER: (keyof StageMap)[] = ['interpreter', 'retrieval', 'ranking', 'curator'];

export function Recom({ id }: RecomProps) {
  const { list, feedback, submitFeedback, rerank, updateStatus, refreshList, createNew } = useRecommendationsContext();

  const [rec, setRec] = useState<Recommendation | null>(null);
  const [stages, setStages] = useState<StageMap>(DEFAULT_STAGES);
  const [sseUrl, setSseUrl] = useState<string | null>(null);
  const [showModal, setShowModal] = useState(false);

  useEffect(() => {
    setRec(null);
    setStages(DEFAULT_STAGES);
    setSseUrl(null);
    getRecommendation(id)
      .then((data) => {
        setRec(data);
        if (data.status === 'running' || data.status === 'pending') {
          setStages(DEFAULT_STAGES);
          setSseUrl(`/api/recommendations/${id}/stream`);
        }
      })
      .catch(() => route('/'));
  }, [id]);

  const handleSSEEvent = useCallback(
    (event: SSEEvent) => {
      if (event.stage !== 'complete') {
        const stageKey = event.stage as keyof StageMap;
        if (STAGE_ORDER.includes(stageKey)) {
          setStages((prev) => ({
            ...prev,
            [stageKey]: event.status === 'start' ? 'running' : event.status === 'done' ? 'done' : 'error',
          }));
        }
      }

      if (event.stage === 'complete' && event.status === 'done') {
        setSseUrl(null);
        updateStatus(id, 'done');
        void getRecommendation(id).then(setRec);
        void refreshList();
      }

      if (event.status === 'error') {
        setSseUrl(null);
        updateStatus(id, 'error');
        const stageKey = event.stage as PipelineStage;
        if (stageKey !== 'complete') {
          setStages((prev) => ({ ...prev, [stageKey as keyof StageMap]: 'error' }));
        }
      }
    },
    [id, updateStatus, refreshList],
  );

  useSSE(sseUrl, handleSSEEvent);

  const handleRerank = async () => {
    await rerank(id);
    setStages(DEFAULT_STAGES);
    setSseUrl(`/api/recommendations/${id}/stream`);
    setRec((prev) => (prev ? { ...prev, status: 'pending' } : null));
  };

  const handleCreateNew = async (body: {
    main_prompt: string;
    liked_shows: string;
    disliked_shows: string;
    themes: string;
    brainstorm_count?: number;
    media_type: import('../types/index.js').MediaType;
    use_web_search?: boolean;
  }) => {
    const newId = await createNew(body);
    route(`/recom/${newId}`);
  };

  const isRunning = rec?.status === 'running' || rec?.status === 'pending' || !!sseUrl;
  const feedbackMap = new Map(feedback.map((f) => [f.item_name, f]));

  return (
    <div class="layout">
      <Sidebar
        list={list}
        selectedId={id}
        onSelect={(sid) => route(`/recom/${sid}`)}
        onNewClick={() => setShowModal(true)}
      />

      <main class="main-content">
        <div class="recom-content">
          {isRunning && (
            <div class="content-area">
              <PipelineProgress stages={stages} />
            </div>
          )}

          {!isRunning && rec?.status === 'done' && rec.recommendations && (
            <div class="content-area">
              <h2 class="rec-title">{rec.title}</h2>
              <div class="cards-grid">
                {rec.recommendations.map((show) => (
                  <RecommendationCard
                    key={show.title}
                    show={show}
                    existingFeedback={feedbackMap.get(show.title)}
                    onFeedback={async (name, stars, comment) => {
                      await submitFeedback({ item_name: name, stars, feedback: comment });
                    }}
                  />
                ))}
              </div>
              <div class="rerank-section">
                <button
                  class="btn-rerank"
                  onClick={handleRerank}
                  disabled={feedback.length === 0}
                  title={feedback.length === 0 ? 'Rate at least one show to enable re-ranking' : 'Re-rank based on your feedback'}
                >
                  Re-rank with Feedback {feedback.length > 0 ? `(${feedback.length} rated)` : ''}
                </button>
              </div>
            </div>
          )}

          {!isRunning && rec?.status === 'error' && (
            <div class="content-area error-state">
              <h2>Something went wrong</h2>
              <p>The pipeline encountered an error. You can try again by clicking Re-rank.</p>
              <button class="btn-primary" onClick={handleRerank}>
                Try Again
              </button>
            </div>
          )}
        </div>
      </main>

      {showModal && (
        <NewRecommendationModal
          onClose={() => setShowModal(false)}
          onSubmit={handleCreateNew}
        />
      )}
    </div>
  );
}
