import { useState, useRef, useCallback, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { useNavigate } from 'react-router-dom';
import { api } from '@/shared/lib/apiClient';
import { unwrapArray, unwrapObject } from '@/shared/lib/apiShape';
import { OracleResultCard } from './OracleResultCard';
import styles from './OracleBar.module.css';

type QueryState = 'idle' | 'thinking' | 'result';
type OracleEnvelope = { status?: string; data?: unknown; detail?: string; message?: string; error?: string };
type OracleRow = Record<string, unknown>;

function normalizeOracleResult(payload: unknown) {
  const root = unwrapObject<Record<string, unknown>>(payload) ?? {};
  const rows = unwrapArray<OracleRow>(root, ['rows', 'dataRows']);
  const components = unwrapArray<Record<string, unknown>>(root, ['components']);
  const firstComponent = components[0];
  const componentRows = rows.length > 0 ? rows : unwrapArray<OracleRow>(firstComponent, ['rows', 'dataRows']);
  const columns = Array.isArray(root.columns)
    ? root.columns.filter((item): item is string => typeof item === 'string')
    : componentRows[0]
      ? Object.keys(componentRows[0])
      : [];

  return {
    ...root,
    title: root.title ?? firstComponent?.title,
    summary: root.summary ?? firstComponent?.summary,
    rows: componentRows,
    columns,
    rowCount: typeof root.rowCount === 'number' ? root.rowCount : componentRows.length,
    componentType: root.componentType ?? firstComponent?.type ?? firstComponent?.componentType,
    sourceTables: Array.isArray(root.sourceTables) ? root.sourceTables : [],
  };
}

/**
 * OracleBar
 * The persistent natural-language prompt bar for Pillar 1.
 * UX Master Plan §4.5 choreography:
 *   - Bar expands 48px → 80px on focus (200ms)
 *   - Ghost-text autocomplete suggestion
 *   - "Thinking" state: Velocity logo pulses inside bar
 *   - Placeholder result card at opacity 0.3, scale 0.98 (layout reserved)
 *   - Response: stagger-fades each data row at 100ms intervals
 *   - Oracle machinery (canvas ID, fork/merge, schema catalog) NEVER shown
 */

const SUGGESTIONS = [
  'Which leads are closest to closing this week?',
  'Show me site visit trends for April',
  'Who hasn\'t been contacted in 7 days?',
  'What is the average QD score by project?',
];

const NUMBER_WORDS: Record<string, number> = {
  one: 1,
  two: 2,
  three: 3,
  four: 4,
  five: 5,
  six: 6,
  seven: 7,
  eight: 8,
  nine: 9,
  ten: 10,
  eleven: 11,
  twelve: 12,
  fifteen: 15,
  twenty: 20,
  thirty: 30,
  fifty: 50,
};

const ORACLE_CHAT_STORAGE_KEY = 'velocity-oracle-chat-sessions-v1';

function createChatSessionFromCommand(prompt: string, result: any) {
  const now = new Date().toISOString();
  const title = prompt.trim().length > 58 ? `${prompt.trim().slice(0, 55)}...` : prompt.trim();
  const session = {
    id: `oracle_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
    title: title || 'Oracle Chat',
    createdAt: now,
    updatedAt: now,
    turns: [{
      id: `turn_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
      prompt,
      createdAt: now,
      status: result?.title === 'Oracle query failed' ? 'failed' : 'done',
      result,
      error: result?.title === 'Oracle query failed' ? result?.summary : undefined,
    }],
  };

  try {
    const current = JSON.parse(localStorage.getItem(ORACLE_CHAT_STORAGE_KEY) ?? '[]');
    const sessions = Array.isArray(current) ? current : [];
    localStorage.setItem(ORACLE_CHAT_STORAGE_KEY, JSON.stringify([session, ...sessions].slice(0, 30)));
  } catch {
    localStorage.setItem(ORACLE_CHAT_STORAGE_KEY, JSON.stringify([session]));
  }
}

function deriveRowLimit(prompt: string): number {
  const lowered = prompt.toLowerCase();
  const numericMatch = lowered.match(/\b(?:top|last|first|lowest|highest|best|worst)\s+(\d{1,3})\b|\b(\d{1,3})\s+(?:clients|leads|properties|projects|records|rows)\b/);
  const numericLimit = Number(numericMatch?.[1] ?? numericMatch?.[2]);
  if (Number.isFinite(numericLimit) && numericLimit > 0) {
    return Math.min(100, Math.max(1, numericLimit));
  }

  for (const [word, value] of Object.entries(NUMBER_WORDS)) {
    const phrase = new RegExp(`\\b(?:top|last|first|lowest|highest|best|worst)\\s+${word}\\b|\\b${word}\\s+(?:clients|leads|properties|projects|records|rows)\\b`);
    if (phrase.test(lowered)) {
      return value;
    }
  }

  return 25;
}

export function OracleBar() {
  const navigate = useNavigate();
  const [queryState, setQueryState] = useState<QueryState>('idle');
  const [query, setQuery] = useState('');
  const [isFocused, setIsFocused] = useState(false);
  const [suggestion, setSuggestion] = useState('');
  const [result, setResult] = useState<any>(null);
  const inputRef = useRef<HTMLTextAreaElement>(null);

  // Rotate ghost-text suggestions
  useEffect(() => {
    const idx = Math.floor(Math.random() * SUGGESTIONS.length);
    setSuggestion(SUGGESTIONS[idx]);
  }, []);

  const handleSubmit = useCallback(async () => {
    if (!query.trim() || queryState === 'thinking') return;
    setQueryState('thinking');
    setResult(null);

    try {
      const payload = await api.post<OracleEnvelope>('/oracle/query', {
        prompt: query,
        row_limit: deriveRowLimit(query),
        context: { surface: 'command_pillar' },
      });
      const normalized = normalizeOracleResult(payload.data ?? payload);
      setResult(normalized);
      createChatSessionFromCommand(query, normalized);
      setQueryState('result');
    } catch (error) {
      const failed = {
        title: 'Oracle query failed',
        summary: error instanceof Error ? error.message : 'Unable to run Oracle query.',
        rows: [],
        columns: [],
        warnings: ['Check the Oracle API route and backend logs.'],
      };
      setResult(failed);
      createChatSessionFromCommand(query, failed);
      setQueryState('result');
    }
  }, [query, queryState]);

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      void handleSubmit();
    }
    if (e.key === 'Escape') {
      setIsFocused(false);
      inputRef.current?.blur();
    }
  };

  const handleReset = () => {
    setQuery('');
    setResult(null);
    setQueryState('idle');
    inputRef.current?.focus();
  };

  return (
    <div className={styles.wrapper}>
      {/* ── Prompt bar ─────────────────────────────────────── */}
      <motion.div
        className={`${styles.bar} ${isFocused ? styles.focused : ''} glass`}
        animate={{ height: isFocused ? 80 : 48 }}
        transition={{ duration: 0.2, ease: [0.4, 0, 0.2, 1] }}
      >
        {/* Velocity logo / thinking pulse */}
        <motion.div
          className={styles.logoMark}
          animate={queryState === 'thinking'
            ? { opacity: [0.4, 1, 0.4], scale: [0.95, 1.05, 0.95] }
            : { opacity: 1, scale: 1 }
          }
          transition={queryState === 'thinking'
            ? { duration: 1.5, repeat: Infinity }
            : { duration: 0.2 }
          }
        >
          <span>✦</span>
        </motion.div>

        {/* Text input */}
        <div className={styles.inputWrap}>
          {!query && !isFocused && (
            <span className={styles.ghostText}>{suggestion}</span>
          )}
          <textarea
            ref={inputRef}
            className={styles.input}
            value={query}
            onChange={e => setQuery(e.target.value)}
            onFocus={() => setIsFocused(true)}
            onBlur={() => !query && setIsFocused(false)}
            onKeyDown={handleKeyDown}
            placeholder=""
            rows={1}
            disabled={queryState === 'thinking'}
            aria-label="Ask Oracle anything about your pipeline"
          />
        </div>

        {/* Submit / clear */}
        <AnimatePresence mode="wait">
          {query && queryState !== 'thinking' && (
            <motion.button
              className={styles.submitBtn}
              onClick={() => void handleSubmit()}
              initial={{ scale: 0, opacity: 0 }}
              animate={{ scale: 1, opacity: 1 }}
              exit={{ scale: 0, opacity: 0 }}
              transition={{ type: 'spring', stiffness: 400, damping: 30 }}
              aria-label="Submit query"
            >
              ↵
            </motion.button>
          )}
          {(result || queryState === 'result') && (
            <motion.button
              className={styles.clearBtn}
              onClick={handleReset}
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              aria-label="Clear result"
            >
              ✕
            </motion.button>
          )}
        </AnimatePresence>
      </motion.div>

      {/* ── Placeholder card (layout reserved before content) ─ */}
      <AnimatePresence mode="wait">
        {queryState === 'thinking' && (
          <motion.div
            className={`${styles.placeholderCard} glass shimmer`}
            initial={{ opacity: 0, scale: 0.98 }}
            animate={{ opacity: 0.35, scale: 0.99 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            aria-hidden
          />
        )}

        {/* ── Result card ──────────────────────────────────── */}
        {queryState === 'result' && result && (
          <>
            <div className={styles.resultActions}>
              <button type="button" className={styles.openOracleBtn} onClick={() => navigate('/oracle')}>
                Open full Oracle chat
              </button>
            </div>
            <OracleResultCard result={result} query={query} />
          </>
        )}
      </AnimatePresence>
    </div>
  );
}
