import React, { useState, useEffect, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
  Lightbulb,
  AlertTriangle,
  AlertCircle,
  Info,
  ChevronRight,
  ChevronDown,
  ChevronUp,
  Shield,
  RefreshCw,
  CheckCircle2,
  Dumbbell,
  Apple,
  Moon,
  Heart,
  Droplets,
  TestTube,
  Stethoscope,
  Sparkles,
  XCircle,
} from 'lucide-react';
import { API_BASE_URL } from '../config/api';
import './RecommendationsPanel.css';

// Types
interface Action {
  type: string;
  text: string;
}

interface Source {
  name: string;
  url?: string;
}

interface Provenance {
  memory?: boolean;
  graph?: boolean;
  metrics?: boolean;
  profile?: boolean;
}

interface Recommendation {
  id: string;
  title: string;
  severity: 'URGENT' | 'WARNING' | 'INFO';
  why: string;
  actions: Action[];
  followup: Action[];
  sources: Source[];
  provenance?: Provenance;
}

interface RecommendationsResponse {
  updated_at: string;
  disclaimer: string;
  items: Recommendation[];
  total_count: number;
  urgent_count: number;
  warning_count: number;
}

/** Stored API returns priority as "high"|"medium"|"low" and description instead of why */
interface StoredItem {
  id: string;
  title: string;
  description?: string;
  priority: string;
  actions?: string[] | { type?: string; text: string }[];
  evidence?: string[];
  provenance?: Provenance;
}

interface RecommendationsPanelProps {
  authToken?: string;
  apiBaseUrl?: string;
  maxInitialDisplay?: number;
  refreshTrigger?: number; // Increment this to trigger a refresh (from WebSocket events)
  showGenerateButton?: boolean; // Show generate button for generating new recommendations
  onRecommendationsGenerated?: () => void; // Callback after generating recommendations
  variant?: 'dashboard' | 'page'; // Layout variant
}

// Action type to icon mapping
const actionIcons: Record<string, React.ReactNode> = {
  EXERCISE: <Dumbbell size={14} />,
  DIET: <Apple size={14} />,
  HABIT: <Sparkles size={14} />,
  SLEEP: <Moon size={14} />,
  STRESS: <Heart size={14} />,
  HYDRATION: <Droplets size={14} />,
  TEST: <TestTube size={14} />,
  DOCTOR: <Stethoscope size={14} />,
  GENERAL: <CheckCircle2 size={14} />,
};

// Severity icons
const severityIcons: Record<string, React.ReactNode> = {
  URGENT: <AlertCircle size={18} />,
  WARNING: <AlertTriangle size={18} />,
  INFO: <Info size={18} />,
};

function mapStoredToRecommendation(stored: StoredItem): Recommendation {
  const severityMap = { high: 'URGENT' as const, medium: 'WARNING' as const, low: 'INFO' as const };
  const severity = severityMap[stored.priority as keyof typeof severityMap] ?? 'INFO';
  const rawActions = stored.actions ?? [];
  const actions: Action[] = rawActions.map((a) => {
    if (typeof a === 'string') return { type: 'GENERAL' as const, text: a };
    const text = a?.text != null ? String(a.text) : '';
    return { type: ((a?.type as Action['type']) ?? 'GENERAL'), text };
  });
  return {
    id: stored.id,
    title: stored.title ?? '',
    severity,
    why: stored.description ?? '',
    actions,
    followup: [],
    sources: [],
    provenance: stored.provenance,
  };
}

// Provenance tooltip component - shows data sources
const ProvenanceTooltip: React.FC<{ provenance?: Provenance }> = ({ provenance }) => {
  if (!provenance) return null;

  const sources = [];
  if (provenance.memory) sources.push({ label: 'Memory', icon: '🧠', desc: 'Your preferences & facts' });
  if (provenance.graph) sources.push({ label: 'Graph', icon: '🕸️', desc: 'Health relationships' });
  if (provenance.metrics) sources.push({ label: 'Metrics', icon: '📊', desc: 'Lab values & observations' });
  if (provenance.profile) sources.push({ label: 'Profile', icon: '👤', desc: 'Your health profile' });

  if (sources.length === 0) return null;

  return (
    <div className="provenance-badge" title="Powered by">
      <span className="provenance-trigger">✨ Sources</span>
      <div className="provenance-tooltip">
        <span className="provenance-title">Recommendation Sources</span>
        {sources.map((src, i) => (
          <div key={i} className="provenance-item">
            <span className="provenance-icon">{src.icon}</span>
            <span className="provenance-label">{src.label}</span>
            <span className="provenance-desc">{src.desc}</span>
          </div>
        ))}
      </div>
    </div>
  );
};

const RecommendationsPanel: React.FC<RecommendationsPanelProps> = ({
  authToken,
  apiBaseUrl = API_BASE_URL,
  maxInitialDisplay = 3,
  refreshTrigger = 0,
  showGenerateButton = true,
  onRecommendationsGenerated,
  variant = 'dashboard',
}) => {
  const [recommendations, setRecommendations] = useState<RecommendationsResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [generating, setGenerating] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [expanded, setExpanded] = useState(false);
  const [expandedCards, setExpandedCards] = useState<Set<string>>(new Set());

  const fetchRecommendations = useCallback(async () => {
    if (!authToken) {
      setError('Authentication required');
      setLoading(false);
      return;
    }

    setLoading(true);
    setError(null);

    const headers = {
      Authorization: `Bearer ${authToken}`,
      'Content-Type': 'application/json',
    };

    try {
      // Prefer stored (Grok-generated) when available; otherwise use rule-based
      const [storedRes, ruleRes] = await Promise.all([
        fetch(`${apiBaseUrl}/api/recommendations/stored`, { headers }),
        fetch(`${apiBaseUrl}/api/recommendations`, { headers }),
      ]);

      if (storedRes.ok) {
        const storedData = await storedRes.json();
        if (storedData.items?.length > 0) {
          const mapped: RecommendationsResponse = {
            ...storedData,
            items: storedData.items.map((item: StoredItem) => mapStoredToRecommendation(item)),
          };
          setRecommendations(mapped);
          return;
        }
      }

      if (!ruleRes.ok) {
        throw new Error(`Failed to fetch recommendations: ${ruleRes.status}`);
      }
      const ruleData: RecommendationsResponse = await ruleRes.json();
      setRecommendations(ruleData);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load recommendations');
    } finally {
      setLoading(false);
    }
  }, [authToken, apiBaseUrl]);

  useEffect(() => {
    fetchRecommendations();
  }, [fetchRecommendations]);

  // Refresh when refreshTrigger changes (triggered by WebSocket events from parent)
  useEffect(() => {
    if (refreshTrigger > 0) {
      fetchRecommendations();
    }
  }, [refreshTrigger, fetchRecommendations]);

  // Generate new recommendations
  const handleGenerateRecommendations = async () => {
    if (!authToken) return;

    setGenerating(true);
    setError(null);
    try {
      const response = await fetch(`${apiBaseUrl}/api/recommendations/generate`, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${authToken}`,
          'Content-Type': 'application/json',
        },
      });

      if (response.ok) {
        await fetchRecommendations();
        onRecommendationsGenerated?.();
      } else {
        let message = `Generate failed (${response.status})`;
        try {
          const body = await response.json();
          if (body?.error && typeof body.error === 'string') {
            message = body.error;
          }
        } catch {
          // ignore parse error
        }
        setError(message);
      }
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Failed to generate recommendations';
      setError(message);
      console.error('Error generating recommendations:', err);
    } finally {
      setGenerating(false);
    }
  };

  const toggleCardExpanded = (id: string) => {
    setExpandedCards(prev => {
      const next = new Set(prev);
      if (next.has(id)) {
        next.delete(id);
      } else {
        next.add(id);
      }
      return next;
    });
  };

  const displayedItems = recommendations?.items.slice(
    0,
    expanded ? undefined : maxInitialDisplay
  ) || [];

  const hasMore = (recommendations?.items.length || 0) > maxInitialDisplay;

  if (loading) {
    return (
      <div className="recommendations-panel">
        <div className="recommendations-loading">
          <div className="spinner" />
          <p>Loading personalized recommendations...</p>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="recommendations-panel">
        <div className="recommendations-error">
          <XCircle size={48} />
          <p>{error}</p>
          <button className="retry-button" onClick={fetchRecommendations}>
            <RefreshCw size={16} />
            Retry
          </button>
        </div>
      </div>
    );
  }

  if (!recommendations || recommendations.items.length === 0) {
    return (
      <div className={`recommendations-panel ${variant === 'page' ? 'recommendations-panel-page' : ''}`}>
        <div className="recommendations-header">
          <h2>
            <Lightbulb size={22} />
            Recommendations
          </h2>
          {showGenerateButton && (
            <button
              className="recommendations-generate-btn"
              onClick={handleGenerateRecommendations}
              disabled={generating}
            >
              {generating ? (
                <><RefreshCw size={16} className="spinning" /> Generating...</>
              ) : (
                <><Sparkles size={16} /> Generate</>)}
            </button>
          )}
        </div>
        <div className="recommendations-empty">
          <Sparkles size={48} />
          <h3>No recommendations yet</h3>
          <p>
            Generate personalized recommendations based on your health profile and reports.
          </p>
          {showGenerateButton && (
            <button
              className="recommendations-generate-btn recommendations-generate-btn-lg"
              onClick={handleGenerateRecommendations}
              disabled={generating}
            >
              {generating ? (
                <><RefreshCw size={18} className="spinning" /> Generating...</>
              ) : (
                <><Sparkles size={18} /> Generate Recommendations</>)}
            </button>
          )}
        </div>
        <div className="recommendations-disclaimer">
          <Shield size={18} />
          <p>{recommendations?.disclaimer || 'This is wellness guidance, not medical advice.'}</p>
        </div>
      </div>
    );
  }

  return (
    <div className={`recommendations-panel ${variant === 'page' ? 'recommendations-panel-page' : ''}`}>
      <div className="recommendations-header">
        <div className="recommendations-header-left">
          <h2>
            <Lightbulb size={22} />
            Recommendations
          </h2>
          {showGenerateButton && (
            <button
              className="recommendations-generate-btn"
              onClick={handleGenerateRecommendations}
              disabled={generating}
            >
              {generating ? (
                <><RefreshCw size={16} className="spinning" /> Generating...</>
              ) : (
                <><RefreshCw size={16} /> Refresh</>)}
            </button>
          )}
        </div>
        <div className="recommendations-badges">
          {recommendations.urgent_count > 0 && (
            <span className="badge urgent">
              <AlertCircle size={14} />
              {recommendations.urgent_count} Urgent
            </span>
          )}
          {recommendations.warning_count > 0 && (
            <span className="badge warning">
              <AlertTriangle size={14} />
              {recommendations.warning_count} Attention
            </span>
          )}
          {recommendations.total_count - recommendations.urgent_count - recommendations.warning_count > 0 && (
            <span className="badge info">
              <Info size={14} />
              {recommendations.total_count - recommendations.urgent_count - recommendations.warning_count} Tips
            </span>
          )}
        </div>
      </div>

      <div className="recommendations-list">
        <AnimatePresence mode="popLayout">
          {displayedItems.map((item, index) => (
            <motion.div
              key={item.id}
              initial={{ opacity: 0, y: 20 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -20 }}
              transition={{ delay: index * 0.05 }}
              className={`recommendation-card ${(item.severity ?? 'info').toLowerCase()}`}
            >
              <div className="recommendation-header">
                <h3 className="recommendation-title">{item.title ?? ''}</h3>
                <div className="recommendation-header-right">
                  <ProvenanceTooltip provenance={item.provenance} />
                  <span className={`severity-tag ${(item.severity ?? 'info').toLowerCase()}`}>
                    {severityIcons[item.severity ?? 'INFO']}
                    {item.severity ?? 'INFO'}
                  </span>
                </div>
              </div>

              <p className="recommendation-why">{item.why}</p>

              <div className="recommendation-actions">
                <h4>Suggested Actions</h4>
                <div className="actions-list">
                  {(item.actions ?? []).slice(0, expandedCards.has(item.id) ? undefined : 3).map((action, idx) => (
                    <span key={idx} className={`action-tag ${(action.type ?? 'general').toLowerCase()}`}>
                      {actionIcons[action.type] || <ChevronRight size={14} />}
                      {action.text ?? ''}
                    </span>
                  ))}
                  {(item.actions ?? []).length > 3 && !expandedCards.has(item.id) && (
                    <button
                      className="action-tag"
                      onClick={() => toggleCardExpanded(item.id)}
                      style={{ cursor: 'pointer', background: '#f0f0f0' }}
                    >
                      +{(item.actions ?? []).length - 3} more
                    </button>
                  )}
                </div>
              </div>

              {(item.followup ?? []).length > 0 && (
                <div className="recommendation-followup">
                  <h4>Follow-up</h4>
                  <div className="followup-list">
                    {(item.followup ?? []).map((follow, idx) => (
                      <div key={idx} className="followup-item">
                        {actionIcons[follow.type] || <ChevronRight size={14} />}
                        {follow.text ?? ''}
                      </div>
                    ))}
                  </div>
                </div>
              )}

              {(item.sources ?? []).length > 0 && expandedCards.has(item.id) && (
                <div className="recommendation-sources">
                  <div className="sources-list">
                    {(item.sources ?? []).map((source, idx) => (
                      source.url ? (
                        <a
                          key={idx}
                          href={source.url}
                          target="_blank"
                          rel="noopener noreferrer"
                          className="source-link"
                        >
                          📎 {source.name ?? 'Source'}
                        </a>
                      ) : (
                        <span key={idx} className="source-link">
                          📎 {source.name ?? 'Source'}
                        </span>
                      )
                    ))}
                  </div>
                </div>
              )}

              {((item.actions ?? []).length > 3 || (item.sources ?? []).length > 0) && (
                <button
                  className="expand-toggle"
                  onClick={() => toggleCardExpanded(item.id)}
                  style={{ marginTop: '12px' }}
                >
                  {expandedCards.has(item.id) ? (
                    <>
                      <ChevronUp size={16} />
                      Show less
                    </>
                  ) : (
                    <>
                      <ChevronDown size={16} />
                      Show more details
                    </>
                  )}
                </button>
              )}
            </motion.div>
          ))}
        </AnimatePresence>
      </div>

      {hasMore && (
        <button className="expand-toggle" onClick={() => setExpanded(!expanded)}>
          {expanded ? (
            <>
              <ChevronUp size={16} />
              Show fewer recommendations
            </>
          ) : (
            <>
              <ChevronDown size={16} />
              Show {recommendations.items.length - maxInitialDisplay} more recommendations
            </>
          )}
        </button>
      )}

      <div className="recommendations-disclaimer">
        <Shield size={18} />
        <p>{recommendations.disclaimer}</p>
      </div>
    </div>
  );
};

export default RecommendationsPanel;
