import { useState, useEffect, useRef, useCallback } from 'react';
import { useNavigate, useLocation, useParams } from 'react-router';
import { motion } from 'motion/react';
import { Check, AlertCircle, RefreshCw, ShieldX } from 'lucide-react';
import {
  discoverChannels,
  collectChannelData,
  generateReportV2,
  generateContentPlan,
  fetchPipelineStatus,
} from '../lib/supabase';

type Phase = 'resuming' | 'discovering' | 'collecting' | 'generating' | 'planning' | 'complete';

const PHASE_STEPS = [
  { key: 'discovering' as Phase, label: 'Scanning website & discovering channels...', labelDone: 'Channels discovered' },
  { key: 'collecting' as Phase, label: 'Collecting channel data & market analysis...', labelDone: 'Data collected' },
  { key: 'generating' as Phase, label: 'Generating AI marketing report...', labelDone: 'Report generated' },
  { key: 'planning' as Phase, label: 'Generating AI content strategy...', labelDone: 'Content plan generated' },
  { key: 'complete' as Phase, label: 'Finalizing report...', labelDone: 'Complete' },
];

// Session keys for pipeline resume
const SESSION_KEYS = {
  reportId: 'infinith_reportId',
  clinicId: 'infinith_clinicId',
  runId: 'infinith_runId',
  url: 'infinith_url',
};

function saveSession(data: { reportId: string; clinicId?: string; runId?: string; url?: string }) {
  sessionStorage.setItem(SESSION_KEYS.reportId, data.reportId);
  if (data.clinicId) sessionStorage.setItem(SESSION_KEYS.clinicId, data.clinicId);
  if (data.runId) sessionStorage.setItem(SESSION_KEYS.runId, data.runId);
  if (data.url) sessionStorage.setItem(SESSION_KEYS.url, data.url);
}

function loadSession() {
  return {
    reportId: sessionStorage.getItem(SESSION_KEYS.reportId),
    clinicId: sessionStorage.getItem(SESSION_KEYS.clinicId),
    runId: sessionStorage.getItem(SESSION_KEYS.runId),
    url: sessionStorage.getItem(SESSION_KEYS.url),
  };
}

function clearSession() {
  Object.values(SESSION_KEYS).forEach(k => sessionStorage.removeItem(k));
}

export default function AnalysisLoadingPage() {
  const [phase, setPhase] = useState<Phase>('discovering');
  const [error, setError] = useState<string | null>(null);
  const [errorCode, setErrorCode] = useState<string | null>(null);
  const [errorDomain, setErrorDomain] = useState<string | null>(null);
  const [errorDetails, setErrorDetails] = useState<Record<string, string> | null>(null);
  const navigate = useNavigate();
  const location = useLocation();
  const { reportId: urlReportId } = useParams<{ reportId?: string }>();
  const url = (location.state as { url?: string })?.url;
  const hasStarted = useRef(false);

  const phaseIndex = PHASE_STEPS.findIndex(s => s.key === phase);

  const runPipeline = useCallback(async (
    startUrl?: string,
    resumeFrom?: { reportId: string; clinicId?: string; runId?: string; phase: Phase },
  ) => {
    try {
      let reportId = resumeFrom?.reportId || '';
      let clinicId = resumeFrom?.clinicId;
      let runId = resumeFrom?.runId;
      let startPhase = resumeFrom?.phase || 'discovering';

      // Phase 1: Discover Channels (skip if resuming from later phase)
      if (startPhase === 'discovering') {
        if (!startUrl) throw new Error('No URL provided');
        setPhase('discovering');
        const discovery = await discoverChannels(startUrl);
        if (!discovery.success) throw new Error(discovery.error || 'Channel discovery failed');
        reportId = discovery.reportId;
        clinicId = discovery.clinicId;
        runId = discovery.runId;

        // Save to session + update URL for resume
        saveSession({ reportId, clinicId, runId, url: startUrl });
        window.history.replaceState(null, '', `/report/loading/${reportId}`);
        startPhase = 'collecting';
      }

      // Phase 2: Collect Channel Data
      if (startPhase === 'collecting') {
        setPhase('collecting');
        const collection = await collectChannelData(reportId, clinicId, runId);
        // Allow partial success — only fail on total failure
        if (collection.success === false && !collection.partialFailure) {
          throw new Error(collection.error || 'Data collection failed');
        }
        if (collection.channelErrors && Object.keys(collection.channelErrors).length > 0) {
          console.warn('[pipeline] Partial failures:', collection.channelErrors);
        }
        startPhase = 'generating';
      }

      // Phase 3: Generate Report
      let reportResult: Record<string, unknown> | null = null;
      if (startPhase === 'generating') {
        setPhase('generating');
        const result = await generateReportV2(reportId, clinicId, runId);
        if (!result.success) throw new Error(result.error || 'Report generation failed');
        reportResult = result;
        startPhase = 'planning';
      }

      // Phase 4: Generate Content Plan (non-blocking — failure doesn't stop pipeline)
      if (startPhase === 'planning') {
        setPhase('planning');
        try {
          await generateContentPlan(reportId, clinicId, runId);
        } catch (planErr) {
          console.warn('[pipeline] Content plan generation failed (non-blocking):', planErr);
        }

        // Complete — navigate to report
        setPhase('complete');
        clearSession();

        // Use stored report result or refetch
        const result = reportResult || await generateReportV2(reportId, clinicId, runId).catch(() => null);
        setTimeout(() => {
          navigate(`/report/${reportId}`, {
            replace: true,
            state: result?.report && result?.metadata
              ? { report: result.report, metadata: result.metadata, reportId, clinicId }
              : undefined,
          });
        }, 800);
      }
    } catch (err) {
      const msg = err instanceof Error ? err.message : 'An error occurred';
      setError(msg);
      if (err && typeof err === 'object' && 'code' in err) {
        setErrorCode((err as { code?: string }).code || null);
      }
      if (err && typeof err === 'object' && 'domain' in err) {
        setErrorDomain((err as { domain?: string }).domain || null);
      }
    }
  }, [navigate]);

  // Retry from the current failed phase
  const handleRetry = useCallback(() => {
    setError(null);
    setErrorDetails(null);
    const session = loadSession();
    if (session.reportId) {
      // Resume from the phase that failed
      runPipeline(undefined, {
        reportId: session.reportId,
        clinicId: session.clinicId || undefined,
        runId: session.runId || undefined,
        phase,
      });
    } else if (url || session.url) {
      // Restart from scratch
      hasStarted.current = false;
      runPipeline(url || session.url || undefined);
    }
  }, [phase, url, runPipeline]);

  useEffect(() => {
    if (hasStarted.current) return;
    hasStarted.current = true;

    // 1. Try URL param resume (e.g., /report/loading/abc-123)
    if (urlReportId) {
      setPhase('resuming');
      fetchPipelineStatus(urlReportId)
        .then((status) => {
          // Also check sessionStorage for clinicId/runId
          const session = loadSession();
          const clinicId = session.clinicId || status.clinicId;
          const runId = session.runId || status.runId;

          if (status.hasReport || status.status === 'complete') {
            // Already done — go to report
            navigate(`/report/${urlReportId}`, { replace: true });
            return;
          }

          let resumePhase: Phase = 'discovering';
          if (status.status === 'discovered' || status.status === 'discovering') {
            resumePhase = 'collecting';
          } else if (['collecting', 'collected', 'partial'].includes(status.status)) {
            resumePhase = 'generating';
          } else if (status.status === 'collection_failed') {
            setError('Data collection failed. Please retry.');
            setPhase('collecting');
            return;
          }

          saveSession({ reportId: urlReportId, clinicId, runId, url: session.url || undefined });
          runPipeline(undefined, { reportId: urlReportId, clinicId, runId, phase: resumePhase });
        })
        .catch(() => {
          setError('Could not resume analysis. Please try again.');
        });
      return;
    }

    // 2. Try sessionStorage resume
    const session = loadSession();
    if (session.reportId && !url) {
      setPhase('resuming');
      fetchPipelineStatus(session.reportId)
        .then((status) => {
          if (status.hasReport || status.status === 'complete') {
            clearSession();
            navigate(`/report/${session.reportId}`, { replace: true });
            return;
          }

          let resumePhase: Phase = 'discovering';
          if (['discovered', 'discovering'].includes(status.status)) {
            resumePhase = 'collecting';
          } else if (['collecting', 'collected', 'partial'].includes(status.status)) {
            resumePhase = 'generating';
          }

          runPipeline(undefined, {
            reportId: session.reportId!,
            clinicId: session.clinicId || undefined,
            runId: session.runId || undefined,
            phase: resumePhase,
          });
        })
        .catch(() => {
          clearSession();
          navigate('/', { replace: true });
        });
      return;
    }

    // 3. Fresh start with URL
    if (!url) {
      navigate('/', { replace: true });
      return;
    }

    runPipeline(url);
  }, [url, urlReportId, navigate, runPipeline]);

  // Adjust phaseIndex for 'resuming' state
  const displayPhaseIndex = phase === 'resuming' ? -1 : phaseIndex;

  return (
    <div className="relative min-h-screen bg-primary-900 flex flex-col items-center justify-center px-6 overflow-hidden">
      <div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,_rgba(79,29,161,0.25)_0%,_transparent_70%)]" />
      <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[500px] h-[500px] bg-purple-600/20 rounded-full blur-[120px] pointer-events-none" />

      <div className="relative z-10 flex flex-col items-center w-full max-w-lg">
        <motion.h1
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.6 }}
          className="text-4xl md:text-5xl font-serif font-bold mb-4"
          style={{
            background: 'linear-gradient(to right, #fff3eb, #e4cfff, #f5f9ff)',
            WebkitBackgroundClip: 'text',
            WebkitTextFillColor: 'transparent',
          }}
        >
          INFINITH
        </motion.h1>

        {(url || loadSession().url) && (
          <motion.p
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.6, delay: 0.1 }}
            className="text-purple-300/80 text-sm font-mono mb-12 truncate max-w-full"
          >
            {url || loadSession().url}
          </motion.p>
        )}

        {error ? (
          errorCode === 'CLINIC_NOT_REGISTERED' ? (
            <motion.div
              initial={{ opacity: 0, scale: 0.95 }}
              animate={{ opacity: 1, scale: 1 }}
              className="w-full p-6 rounded-2xl bg-purple-500/10 border border-purple-500/20 text-center"
            >
              <ShieldX className="w-10 h-10 text-purple-400 mx-auto mb-3" />
              <p className="text-white text-lg font-medium mb-2">미등록 병원</p>
              <p className="text-purple-300/80 text-sm mb-1">
                <span className="font-mono text-purple-200">{errorDomain}</span>
              </p>
              <p className="text-purple-300/60 text-sm mb-6">
                현재 분석 대상 병원 목록에 포함되지 않은 도메인입니다.
              </p>
              <button
                onClick={() => { clearSession(); navigate('/', { replace: true }); }}
                className="px-6 py-2 text-sm font-medium text-white bg-purple-600/30 rounded-lg hover:bg-purple-600/50 transition-colors"
              >
                돌아가기
              </button>
            </motion.div>
          ) : (
            <motion.div
              initial={{ opacity: 0, scale: 0.95 }}
              animate={{ opacity: 1, scale: 1 }}
              className="w-full p-6 rounded-2xl bg-red-500/10 border border-red-500/20 text-center"
            >
              <AlertCircle className="w-10 h-10 text-red-400 mx-auto mb-3" />
              <p className="text-red-300 text-sm mb-4">{error}</p>

              {errorDetails && (
                <div className="mb-4 text-left bg-red-500/5 rounded-lg p-3">
                  <p className="text-red-400/60 text-xs font-mono mb-1">Failed channels:</p>
                  {Object.entries(errorDetails).map(([ch, err]) => (
                    <p key={ch} className="text-red-400/80 text-xs font-mono">
                      • {ch}: {err}
                    </p>
                  ))}
                </div>
              )}

              <div className="flex gap-3 justify-center">
                <button
                  onClick={handleRetry}
                  className="px-6 py-2 text-sm font-medium text-white bg-purple-600/30 rounded-lg hover:bg-purple-600/50 transition-colors flex items-center gap-2"
                >
                  <RefreshCw className="w-4 h-4" />
                  Retry
                </button>
                <button
                  onClick={() => { clearSession(); navigate('/', { replace: true }); }}
                  className="px-6 py-2 text-sm font-medium text-white bg-white/10 rounded-lg hover:bg-white/20 transition-colors"
                >
                  Start Over
                </button>
              </div>
            </motion.div>
          )
        ) : (
          <>
            {phase === 'resuming' ? (
              <motion.div
                initial={{ opacity: 0 }}
                animate={{ opacity: 1 }}
                className="flex flex-col items-center gap-4 mb-14"
              >
                <div className="w-7 h-7 rounded-full border-2 border-purple-400 border-t-transparent animate-spin" />
                <p className="text-purple-200 text-sm">Resuming analysis...</p>
              </motion.div>
            ) : (
              <>
                <div className="w-full space-y-5 mb-14">
                  {PHASE_STEPS.map((step, index) => {
                    const isCompleted = displayPhaseIndex > index || (step.key === 'complete' && phase === 'complete');
                    const isActive = displayPhaseIndex === index && phase !== 'complete';

                    return (
                      <motion.div
                        key={step.key}
                        initial={{ opacity: 0, x: -20 }}
                        animate={{ opacity: isActive || isCompleted ? 1 : 0.3, x: 0 }}
                        transition={{ duration: 0.4, delay: index * 0.15 }}
                        className="flex items-center gap-4"
                      >
                        <div className="w-7 h-7 flex-shrink-0 flex items-center justify-center">
                          {isCompleted ? (
                            <motion.div
                              initial={{ scale: 0 }}
                              animate={{ scale: 1 }}
                              transition={{ type: 'spring', stiffness: 300, damping: 20 }}
                              className="w-7 h-7 rounded-full bg-gradient-to-r from-[#4F1DA1] to-[#6C5CE7] flex items-center justify-center"
                            >
                              <Check className="w-4 h-4 text-white" strokeWidth={3} />
                            </motion.div>
                          ) : isActive ? (
                            <div className="w-7 h-7 rounded-full border-2 border-purple-400 border-t-transparent animate-spin" />
                          ) : (
                            <div className="w-7 h-7 rounded-full border-2 border-white/10" />
                          )}
                        </div>
                        <span
                          className={`text-base font-sans transition-colors duration-300 ${
                            isCompleted ? 'text-white' : isActive ? 'text-purple-200' : 'text-white/30'
                          }`}
                        >
                          {isCompleted ? step.labelDone : step.label}
                        </span>
                      </motion.div>
                    );
                  })}
                </div>

                <div className="w-full h-2 bg-white/10 rounded-full overflow-hidden">
                  <motion.div
                    initial={{ width: '0%' }}
                    animate={{ width: `${((displayPhaseIndex + (phase === 'complete' ? 1 : 0.5)) / PHASE_STEPS.length) * 100}%` }}
                    transition={{ duration: 0.8, ease: 'easeInOut' }}
                    className="h-full bg-gradient-to-r from-[#4F1DA1] to-[#6C5CE7] rounded-full"
                  />
                </div>

                <p className="text-white/40 text-xs mt-4">
                  AI가 마케팅 데이터를 분석하고 있습니다. 약 1~2분 소요됩니다.
                </p>
              </>
            )}
          </>
        )}
      </div>
    </div>
  );
}
