import { useCallback, useEffect, useRef, useState } from 'react';
import {
  Sparkles, Send, RefreshCw, Copy, Check, PanelLeftOpen,
  PanelLeftClose, Plus, Trash2, ChevronDown, Loader2, ExternalLink,
} from 'lucide-react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { useAppStore, type ModelInfo } from '@/stores/app';
import { terraformApi, type ChatSession } from '@/api/endpoints/terraform';
import { useI18n } from '@/i18n';

/* ── Constants ── */

const TFP_EXAMPLES = [
  'VCN com subnets publica e privada, internet gateway, NAT gateway e 2 compute instances Ubuntu',
  'Ambiente multi-region MAD1 + MAD3 com DRG, RPC e VCNs espelhadas',
  'Cluster OKE com 3 node pools, load balancer e container registry',
  'Banco Autonomous Database com vault, encryption key e bastion para acesso',
  'Infraestrutura completa: VCN, compute, block storage, object storage, IAM policies e monitoring',
];

const TFP_ALLOWED = [
  'openai.gpt-4.1', 'openai.o3', 'openai.o4-mini',
  'openai.gpt-5.1', 'openai.gpt-5.2',
  'google.gemini-2.5-pro', 'google.gemini-2.5-flash',
];

const PROV_ORDER = ['openai', 'google'];

interface Msg {
  role: 'user' | 'assistant';
  content: string;
  raw?: string;
  failed?: boolean;
  copied?: boolean;
}

/* ── Component ── */

export default function PromptGeneratorPage() {
  const { models, genaiCfg, ociCfg } = useAppStore();
  const { t } = useI18n();

  /* state */
  const [msgs, setMsgs] = useState<Msg[]>([]);
  const [loading, setLoading] = useState(false);
  const [input, setInput] = useState('');
  const [sid, setSid] = useState<string | null>(null);

  /* model selection */
  const [selectedModel, setSelectedModel] = useState('');
  const [ddOpen, setDdOpen] = useState(false);
  const [ddSearch, setDdSearch] = useState('');

  /* OCI config (for direct models) */
  const [ociId, setOciId] = useState('');
  const [region, setRegion] = useState('');
  const [compartment, setCompartment] = useState('');

  /* history sidebar */
  const [histOpen, setHistOpen] = useState(false);
  const [history, setHistory] = useState<ChatSession[]>([]);

  const chatRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLTextAreaElement>(null);
  const ddRef = useRef<HTMLDivElement>(null);

  /* ── auto-scroll ── */
  const scrollBottom = useCallback(() => {
    if (chatRef.current) chatRef.current.scrollTop = chatRef.current.scrollHeight;
  }, []);

  useEffect(() => { scrollBottom(); }, [msgs, loading, scrollBottom]);

  /* ── close dropdown on outside click ── */
  useEffect(() => {
    function handleClick(e: MouseEvent) {
      if (ddRef.current && !ddRef.current.contains(e.target as Node)) setDdOpen(false);
    }
    document.addEventListener('mousedown', handleClick);
    return () => document.removeEventListener('mousedown', handleClick);
  }, []);

  /* ── history ── */
  const loadHistory = useCallback(async () => {
    try {
      const h = await terraformApi.listSessions('tf-prompt');
      setHistory(h);
    } catch { setHistory([]); }
  }, []);

  const loadSession = useCallback(async (sessionId: string) => {
    try {
      const d = await terraformApi.loadSession(sessionId);
      setSid(sessionId);
      setMsgs(
        d.messages.map((m) => ({
          role: m.role,
          content: m.content,
          raw: m.role === 'assistant' ? m.content : undefined,
        })),
      );
    } catch { /* noop */ }
  }, []);

  const deleteSession = useCallback(async (sessionId: string) => {
    try { await terraformApi.deleteSession(sessionId); } catch { /* noop */ }
    if (sid === sessionId) { setSid(null); setMsgs([]); }
    loadHistory();
  }, [sid, loadHistory]);

  const newConversation = () => { setSid(null); setMsgs([]); };

  /* ── resolve genai config ── */
  const resolveGenai = (): Record<string, string | undefined> => {
    if (selectedModel.startsWith('cfg:')) return { genai_config_id: selectedModel.slice(4) };
    if (selectedModel && ociId) return { oci_config_id: ociId, model_id: selectedModel, genai_region: region, compartment_id: compartment };
    const def = genaiCfg.find((g) => g.is_default) || genaiCfg[0];
    if (def) return { genai_config_id: def.id };
    if (!ociCfg.length) return {};
    const oc = ociCfg[0];
    return { oci_config_id: oc.id, model_id: 'openai.gpt-4.1', genai_region: oc.region, compartment_id: oc.compartment_id };
  };

  /* ── pick model ── */
  const pickModel = (v: string) => {
    setSelectedModel(v);
    setDdOpen(false);
    if (v && !v.startsWith('cfg:') && !ociId && ociCfg.length) {
      setOciId(ociCfg[0].id);
      setRegion(ociCfg[0].region);
      setCompartment(ociCfg[0].compartment_id || '');
    } else if (v.startsWith('cfg:')) {
      const g = genaiCfg.find((x) => x.id === v.slice(4));
      if (g?.oci_config_id && !ociId) {
        setOciId(g.oci_config_id);
        const c = ociCfg.find((x) => x.id === g.oci_config_id);
        if (c) { setRegion(c.region); setCompartment(c.compartment_id || ''); }
      }
    }
  };

  /* ── send ── */
  const send = async (overrideMsg?: string) => {
    const m = overrideMsg || input.trim();
    if (!m || loading) return;
    if (!overrideMsg) setInput('');

    const newMsgs: Msg[] = [...msgs, { role: 'user', content: m }];
    setMsgs(newMsgs);
    setLoading(true);

    try {
      const gc = resolveGenai();
      const hist = newMsgs.slice(0, -1)
        .filter((x) => x.role === 'user' || x.role === 'assistant')
        .map((x) => ({ role: x.role === 'user' ? 'USER' : 'CHATBOT', content: x.raw || x.content }));

      const body = {
        message: m,
        genai_config: gc,
        history: hist.length ? hist : null,
        ...(sid ? { session_id: sid } : {}),
      };

      const d = await terraformApi.generatePrompt(body);
      if (d.session_id) setSid(d.session_id);

      if (d.status === 'processing' && d.message_id) {
        await pollResult(d.message_id, newMsgs);
      } else if (d.prompt) {
        setMsgs([...newMsgs, { role: 'assistant', content: d.prompt, raw: d.prompt }]);
        setLoading(false);
      }
    } catch (e: unknown) {
      setMsgs([...newMsgs, { role: 'assistant', content: 'Erro: ' + (e as Error).message, failed: true }]);
      setLoading(false);
    }
  };

  const pollResult = async (mid: string, currentMsgs: Msg[]) => {
    for (let i = 0; i < 600; i++) {
      await new Promise((r) => setTimeout(r, i < 10 ? 1000 : 3000));
      try {
        const r = await terraformApi.pollMessageStatus(mid);
        if (r.status === 'done') {
          setMsgs([...currentMsgs, { role: 'assistant', content: r.content, raw: r.content }]);
          setLoading(false);
          return;
        }
        if (r.status === 'failed') {
          setMsgs([...currentMsgs, { role: 'assistant', content: r.content, failed: true }]);
          setLoading(false);
          return;
        }
      } catch { /* keep polling */ }
    }
    setMsgs([...currentMsgs, { role: 'assistant', content: t('pg.timeout'), failed: true }]);
    setLoading(false);
  };

  /* ── retry ── */
  const retry = (idx: number) => {
    let userMsg = '';
    for (let i = idx - 1; i >= 0; i--) { if (msgs[i].role === 'user') { userMsg = msgs[i].content; break; } }
    if (!userMsg) return;
    const next = [...msgs];
    next.splice(idx, 1);
    setMsgs(next);
    send(userMsg);
  };

  /* ── copy ── */
  const copyPrompt = async (idx: number) => {
    const m = msgs[idx];
    if (!m?.raw) return;
    await navigator.clipboard.writeText(m.raw);
    setMsgs((prev) => prev.map((msg, i) => (i === idx ? { ...msg, copied: true } : msg)));
    setTimeout(() => {
      setMsgs((prev) => prev.map((msg, i) => (i === idx ? { ...msg, copied: false } : msg)));
    }, 2000);
  };

  /* ── model dropdown data ── */
  const provGroups: Record<string, { id: string; name: string }[]> = {};
  TFP_ALLOWED.forEach((mid) => {
    const mi: ModelInfo | undefined = models[mid];
    if (mi) {
      const p = mi.provider || 'other';
      if (!provGroups[p]) provGroups[p] = [];
      provGroups[p].push({ id: mid, name: mi.name });
    }
  });

  const cfgFiltered = genaiCfg.filter((g) => TFP_ALLOWED.includes(g.model_id));

  let curLabel = t('pg.selectModel');
  if (selectedModel.startsWith('cfg:')) {
    const g = genaiCfg.find((x) => x.id === selectedModel.slice(4));
    curLabel = g ? (g.name || g.model_id) : 'Config...';
  } else if (selectedModel) {
    const mi = models[selectedModel];
    curLabel = mi ? mi.name : selectedModel;
  }

  const isDirect = selectedModel && !selectedModel.startsWith('cfg:');

  /* ── auto-grow textarea ── */
  const autoGrow = (el: HTMLTextAreaElement) => {
    el.style.height = 'auto';
    el.style.height = Math.min(el.scrollHeight, 200) + 'px';
  };

  /* ── history date grouping ── */
  const histDateGroup = (ts: string | undefined) => {
    const tFn = useI18n.getState().t;
    if (!ts) return '';
    const dt = ts.slice(0, 10);
    const today = new Date().toISOString().slice(0, 10);
    const yesterday = new Date(Date.now() - 86400000).toISOString().slice(0, 10);
    if (dt === today) return tFn('chat.today');
    if (dt === yesterday) return tFn('chat.yesterday');
    const d = new Date(dt + 'T00:00:00');
    const diff = Math.floor((Date.now() - d.getTime()) / 86400000);
    if (diff < 7) return d.toLocaleDateString('pt-BR', { weekday: 'long' });
    return d.toLocaleDateString('pt-BR', { day: '2-digit', month: 'short', year: 'numeric' });
  };

  /* ── render ── */
  return (
    <div className="page-full flex">
      {/* ── History sidebar ── */}
      {histOpen && (
        <div className="flex flex-col w-64 border-r shrink-0"
             style={{ background: 'var(--bg1)', borderColor: 'var(--bd)' }}>
          <div className="flex items-center justify-between px-3 py-3 border-b"
               style={{ borderColor: 'var(--bd)' }}>
            <span className="text-xs font-semibold" style={{ color: 'var(--t2)' }}>{t('pg.history')}</span>
            <button onClick={newConversation}
              className="flex items-center gap-1 px-2 py-1 rounded-md text-[.66rem] cursor-pointer"
              style={{ background: 'var(--ppl)', color: 'var(--pp)', border: 'none' }}>
              <Plus size={12} /> {t('pg.new')}
            </button>
          </div>
          <div className="flex-1 overflow-y-auto p-1.5">
            {history.length === 0 && (
              <p className="text-center text-[.7rem] p-4" style={{ color: 'var(--t4)' }}>
                {t('pg.noConversations')}
              </p>
            )}
            {(() => {
              let lastGroup = '';
              return history.map((s) => {
                const g = histDateGroup(s.updated_at || s.created_at);
                const showGroup = g !== lastGroup;
                lastGroup = g;
                return (
                  <div key={s.id}>
                    {showGroup && (
                      <div className="text-[.62rem] font-semibold uppercase tracking-wider px-2 pt-3 pb-1"
                           style={{ color: 'var(--t4)' }}>{g}</div>
                    )}
                    <div
                      className="flex items-center gap-1.5 px-2 py-1.5 rounded-md cursor-pointer group transition-colors"
                      style={{
                        background: s.id === sid ? 'var(--ppl)' : 'transparent',
                        color: s.id === sid ? 'var(--pp)' : 'var(--t2)',
                      }}
                      onClick={() => loadSession(s.id)}>
                      <span className="flex-1 truncate text-[.72rem]">{s.title || t('tf.newConversation')}</span>
                      <button
                        className="opacity-0 group-hover:opacity-100 p-0.5 rounded cursor-pointer"
                        style={{ color: 'var(--rd)', background: 'none', border: 'none' }}
                        onClick={(e) => { e.stopPropagation(); deleteSession(s.id); }}
                        title={t('common.delete')}>
                        <Trash2 size={11} />
                      </button>
                    </div>
                  </div>
                );
              });
            })()}
          </div>
        </div>
      )}

      {/* ── Main chat area ── */}
      <div className="flex flex-col flex-1 min-w-0">
        {/* toolbar */}
        <div className="flex items-center gap-2 px-4 py-2 border-b"
             style={{ background: 'var(--bg1)', borderColor: 'var(--bd)' }}>
          <button onClick={() => { setHistOpen(!histOpen); if (!histOpen) loadHistory(); }}
            className="p-1.5 rounded-md cursor-pointer transition-colors"
            style={{
              background: histOpen ? 'var(--ppl)' : 'transparent',
              color: histOpen ? 'var(--pp)' : 'var(--t3)',
              border: 'none',
            }}
            title={t('pg.history')}>
            {histOpen ? <PanelLeftClose size={16} /> : <PanelLeftOpen size={16} />}
          </button>

          <Sparkles size={16} style={{ color: 'var(--pp)' }} />

          {/* Model dropdown */}
          <div className="relative" ref={ddRef}>
            <button onClick={() => setDdOpen(!ddOpen)}
              className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-[.72rem] font-medium cursor-pointer"
              style={{ background: 'var(--bg2)', color: 'var(--t2)', border: '1px solid var(--bd)' }}>
              {curLabel}
              <ChevronDown size={13} className={`transition-transform ${ddOpen ? 'rotate-180' : ''}`} />
            </button>

            {ddOpen && (
              <div className="absolute top-full left-0 mt-1 w-64 rounded-xl overflow-hidden z-50 animate-[fadeIn_.15s_ease]"
                   style={{ background: 'var(--bg1)', border: '1px solid var(--bd)', boxShadow: 'var(--sh3)' }}>
                <div className="p-2">
                  <input type="text" placeholder={t('pg.search')}
                    value={ddSearch} onChange={(e) => setDdSearch(e.target.value)}
                    className="w-full px-2.5 py-1.5 rounded-md text-[.72rem]"
                    style={{ background: 'var(--bg2)', color: 'var(--t1)', border: '1px solid var(--bd)' }}
                    autoFocus />
                </div>
                <div className="max-h-60 overflow-y-auto px-1 pb-1">
                  {cfgFiltered.length > 0 && (
                    <>
                      <div className="px-2 py-1 text-[.62rem] font-semibold uppercase tracking-wider"
                           style={{ color: 'var(--t4)' }}>{t('chat.savedConfigs')}</div>
                      {cfgFiltered
                        .filter((g) => !ddSearch || (g.name || g.model_id).toLowerCase().includes(ddSearch.toLowerCase()))
                        .map((g) => {
                          const mi = models[g.model_id];
                          return (
                            <DdItem key={'cfg:' + g.id} label={g.name || mi?.name || g.model_id}
                              selected={selectedModel === 'cfg:' + g.id}
                              onClick={() => pickModel('cfg:' + g.id)} />
                          );
                        })}
                    </>
                  )}
                  {PROV_ORDER.filter((p) => provGroups[p]).map((p) => (
                    <div key={p}>
                      <div className="px-2 py-1 text-[.62rem] font-semibold uppercase tracking-wider"
                           style={{ color: 'var(--t4)' }}>{p[0].toUpperCase() + p.slice(1)}</div>
                      {provGroups[p]
                        .filter((m) => !ddSearch || m.name.toLowerCase().includes(ddSearch.toLowerCase()))
                        .map((m) => (
                          <DdItem key={m.id} label={m.name}
                            selected={selectedModel === m.id}
                            onClick={() => pickModel(m.id)} />
                        ))}
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>

          {/* OCI config selector (direct models only) */}
          {isDirect && (
            <select
              value={ociId}
              onChange={(e) => {
                setOciId(e.target.value);
                const c = ociCfg.find((x) => x.id === e.target.value);
                if (c) { setRegion(c.region); setCompartment(c.compartment_id || ''); }
              }}
              className="px-2 py-1.5 rounded-lg text-[.72rem] max-w-[180px]"
              style={{ background: 'var(--bg2)', color: 'var(--t2)', border: '1px solid var(--bd)' }}>
              <option value="">{t('tf.ociConfig')}</option>
              {ociCfg.map((c) => (
                <option key={c.id} value={c.id}>{c.tenancy_name} ({c.region})</option>
              ))}
            </select>
          )}

          <div className="flex-1" />
        </div>

        {/* messages area */}
        <div ref={chatRef} className="flex-1 overflow-y-auto px-4 py-4 space-y-4">
          {msgs.length === 0 && !loading && (
            <div className="flex flex-col items-center justify-center h-full text-center">
              <Sparkles size={32} className="mb-3 opacity-30" style={{ color: 'var(--pp)' }} />
              <p className="text-sm font-medium mb-1" style={{ color: 'var(--t2)' }}>
                {t('pg.emptyTitle')}
              </p>
              <p className="text-xs mb-5 opacity-60" style={{ color: 'var(--t3)' }}>
                {t('pg.emptySubtitle')}
              </p>
              <div className="flex flex-wrap gap-2 justify-center max-w-2xl">
                {TFP_EXAMPLES.map((ex, i) => (
                  <button key={i} onClick={() => { setInput(ex); inputRef.current?.focus(); }}
                    className="px-3 py-2 rounded-lg text-[.68rem] text-left cursor-pointer transition-colors leading-snug"
                    style={{
                      background: 'var(--bg2)', color: 'var(--t3)',
                      border: '1px solid var(--bd)', maxWidth: 280,
                    }}>
                    {ex}
                  </button>
                ))}
              </div>
            </div>
          )}

          {msgs.map((m, i) => (
            <div key={i} className={`flex ${m.role === 'user' ? 'justify-end' : 'justify-start'}`}>
              <div className="max-w-[80%] animate-[fadeIn_.25s_ease]">
                <div className="rounded-xl px-4 py-3 text-[.8rem] leading-relaxed"
                  style={{
                    background: m.role === 'user' ? 'var(--pp)' : 'var(--bg2)',
                    color: m.role === 'user' ? '#fff' : 'var(--t1)',
                    border: m.role === 'user' ? 'none' : '1px solid var(--bd)',
                  }}>
                  {m.role === 'assistant' ? (
                    <div className="prose-sm prose-invert max-w-none [&_pre]:rounded-lg [&_pre]:p-3 [&_pre]:text-[.72rem] [&_pre]:overflow-auto [&_code]:text-[.72rem] [&_pre]:relative [&_pre]:group"
                         style={{
                           ['--tw-prose-body' as string]: 'var(--t1)',
                           ['--tw-prose-headings' as string]: 'var(--t1)',
                           ['--tw-prose-code' as string]: 'var(--pp)',
                         }}>
                      <ReactMarkdown remarkPlugins={[remarkGfm]}
                        components={{
                          pre: ({ children }) => (
                            <div className="relative group">
                              <pre className="rounded-lg p-3 text-[.72rem] overflow-auto"
                                   style={{ background: 'var(--bg3)', fontFamily: 'var(--fm)', color: 'var(--t2)' }}>
                                {children}
                              </pre>
                              <CopyCodeBtn>{children}</CopyCodeBtn>
                            </div>
                          ),
                          code: ({ children, className }) => {
                            if (className?.includes('language-')) return <code className={className}>{children}</code>;
                            return (
                              <code className="px-1 py-0.5 rounded text-[.72rem]"
                                    style={{ background: 'var(--bg3)', color: 'var(--pp)', fontFamily: 'var(--fm)' }}>
                                {children}
                              </code>
                            );
                          },
                        }}>
                        {m.content}
                      </ReactMarkdown>
                    </div>
                  ) : (
                    <span style={{ whiteSpace: 'pre-wrap' }}>{m.content}</span>
                  )}
                </div>

                {/* assistant actions */}
                {m.role === 'assistant' && m.raw && !m.failed && (
                  <div className="flex gap-1.5 mt-1.5">
                    <button onClick={() => copyPrompt(i)}
                      className="flex items-center gap-1 px-2 py-1 rounded-md text-[.64rem] cursor-pointer transition-colors"
                      style={{ background: 'var(--bg3)', color: m.copied ? 'var(--gn)' : 'var(--t3)', border: '1px solid var(--bd)' }}>
                      {m.copied ? <Check size={11} /> : <Copy size={11} />}
                      {m.copied ? t('pg.copied') : t('pg.copy')}
                    </button>
                    <button onClick={() => {
                      const url = `/terraform`;
                      window.open(url, '_blank');
                    }}
                      className="flex items-center gap-1 px-2 py-1 rounded-md text-[.64rem] cursor-pointer transition-colors"
                      style={{ background: 'var(--ppl)', color: 'var(--pp)', border: '1px solid var(--pp)' }}>
                      <ExternalLink size={11} /> Terraform
                    </button>
                  </div>
                )}

                {/* retry on failure */}
                {m.failed && (
                  <button onClick={() => retry(i)}
                    className="flex items-center gap-1 mt-1.5 px-2 py-1 rounded-md text-[.64rem] cursor-pointer"
                    style={{ background: 'var(--rdl)', color: 'var(--rd)', border: '1px solid var(--rd)' }}>
                    <RefreshCw size={11} /> {t('pg.retry')}
                  </button>
                )}
              </div>
            </div>
          ))}

          {/* loading indicator */}
          {loading && (
            <div className="flex justify-start">
              <div className="rounded-xl px-4 py-3 text-[.8rem] flex items-center gap-2"
                   style={{ background: 'var(--bg2)', border: '1px solid var(--bd)', color: 'var(--t3)' }}>
                <Loader2 size={14} className="animate-spin" />
                {t('pg.loading')}
              </div>
            </div>
          )}
        </div>

        {/* input area */}
        <div className="px-4 py-3 border-t" style={{ borderColor: 'var(--bd)', background: 'var(--bg1)' }}>
          <div className="flex items-end gap-2 max-w-3xl mx-auto">
            <textarea
              ref={inputRef}
              value={input}
              onChange={(e) => { setInput(e.target.value); autoGrow(e.target); }}
              onKeyDown={(e) => {
                if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); }
              }}
              placeholder={t('pg.placeholder')}
              rows={1}
              className="flex-1 px-3 py-2.5 rounded-xl text-[.8rem] resize-none outline-none"
              style={{
                background: 'var(--bg2)', color: 'var(--t1)',
                border: '1px solid var(--bd)', maxHeight: 200, overflow: 'auto',
              }}
            />
            <button onClick={() => send()} disabled={loading || !input.trim()}
              className="p-2.5 rounded-xl cursor-pointer transition-colors disabled:opacity-40"
              style={{ background: '#7b42bc', color: '#fff', border: 'none' }}>
              <Send size={16} />
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── Copy code block button ── */

function CopyCodeBtn({ children }: { children: React.ReactNode }) {
  const extractText = (node: React.ReactNode): string => {
    if (typeof node === 'string') return node;
    if (Array.isArray(node)) return node.map(extractText).join('');
    if (node && typeof node === 'object' && 'props' in node) {
      return extractText((node as React.ReactElement<{ children?: React.ReactNode }>).props.children);
    }
    return '';
  };

  return (
    <button
      className="absolute top-2 right-2 p-1 rounded opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer"
      style={{ background: 'var(--bg4)', color: 'var(--t3)' }}
      onClick={() => navigator.clipboard.writeText(extractText(children))}
      title={useI18n.getState().t('common.copy')}>
      <Copy size={12} />
    </button>
  );
}

/* ── Dropdown item ── */

function DdItem({ label, selected, onClick }: { label: string; selected: boolean; onClick: () => void }) {
  return (
    <button onClick={onClick}
      className="w-full text-left px-2.5 py-1.5 rounded-md text-[.72rem] cursor-pointer transition-colors"
      style={{
        background: selected ? 'var(--ppl)' : 'transparent',
        color: selected ? 'var(--pp)' : 'var(--t2)',
        border: 'none',
      }}>
      {label}
    </button>
  );
}
