import React, { useState, useEffect, useRef } from 'react';
import { Box, Text, useInput } from 'ink';
import { getTagSummary, getAllTags, type MonthlySummary, type Tag } from '../core/queries.js';
import { createTag, renameTag, deleteTag } from '../core/tags.js';
import type { Screen, TxFilter } from './App.js';
import { fmt, bar, truncate, Divider } from './fmt.js';
import { handleNavKey } from './nav.js';
import { useTerminalWidth, C_POSITIVE, C_NEGATIVE, C_WARNING, C_ACCENT } from './ui.js';
import { StatCard, ModalPanel, SectionHeader, TextInput, SelectableRow, useStatusMessage, PageHeader, SearchBar } from './components/index.js';
import { useSetTyping } from './TypingContext.js';
import { useRefreshKey } from './RefreshContext.js';

type Mode = 'list' | 'search' | 'add' | 'detail' | 'rename';

export function Tags({ onNavigate, isActive, showHints, initialFilter }: { onNavigate: (s: Screen, f?: TxFilter) => void; isActive?: boolean; showHints: boolean; initialFilter?: TxFilter }) {
  const refreshKey = useRefreshKey();
  const [tags, setTags] = useState<Tag[]>([]);
  const [cursor, setCursor] = useState(0);
  const [mode, setMode] = useState<Mode>('list');
  const [newName, setNewName] = useState('');
  const { statusMsg, showStatus } = useStatusMessage();
  const [search, setSearch] = useState('');
  const [tagSummary, setTagSummary] = useState<MonthlySummary | null>(null);
  const [catCursor, setCatCursor] = useState(0);

  function load() { void getAllTags().then(setTags); }

  const initialNavDone = useRef(false);
  useEffect(() => {
    void getAllTags().then((loaded) => {
      setTags(loaded);
      if (!initialNavDone.current) {
        initialNavDone.current = true;
        const target = initialFilter?.tag;
        if (target) {
          const idx = loaded.findIndex((t) => t.name.toLowerCase() === target.toLowerCase());
          if (idx >= 0) { setCursor(idx); openDetail(loaded[idx]); }
        }
      }
    });
  }, [refreshKey]);

  const setTyping = useSetTyping();
  useEffect(() => { setTyping(mode === 'search' || mode === 'add' || mode === 'rename'); }, [mode]);

  function openDetail(tag: Tag) {
    void getTagSummary(tag.name).then(setTagSummary);
    setCatCursor(0);
    setMode('detail');
  }

  const visibleTags = search
    ? tags.filter((t) => t.name.toLowerCase().includes(search.toLowerCase()))
    : tags;

  const termW = useTerminalWidth();
  const inner = Math.max(60, termW) - 4;
  // [sel=2] gap [name] gap [count=6] gap [inflow=10] gap [outflow=10] — 4 gaps of 2
  const tagNameW = Math.max(10, inner - 36);

  useInput((input, key) => {
    if (mode === 'search') {
      if (key.escape) { setSearch(''); setMode('list'); setCursor(0); return; }
      if (key.return) { setMode('list'); return; }
      if (key.backspace || key.delete) { setSearch((s) => { const next = s.slice(0, -1); if (!next) setMode('list'); return next; }); return; }
      if (key.upArrow)   { setCursor((c) => Math.max(0, c - 1)); return; }
      if (key.downArrow) { setCursor((c) => Math.min(visibleTags.length - 1, c + 1)); return; }
      if (input && !key.ctrl && !key.meta) { setSearch((s) => s + input); setCursor(0); return; }
      return;
    }

    if (mode === 'add') {
      if (key.escape) { setMode('list'); setNewName(''); return; }
      if (key.return && newName.trim()) {
        createTag(newName.trim());
        setNewName('');
        setMode('list');
        load();
        return;
      }
      if (key.backspace || key.delete) { setNewName((n) => n.slice(0, -1)); return; }
      if (input && !key.ctrl && !key.meta) { setNewName((n) => n + input); return; }
      return;
    }

    if (mode === 'rename') {
      if (key.escape) { setMode('list'); setNewName(''); return; }
      if (key.return && newName.trim()) {
        const tag = visibleTags[cursor];
        if (tag) {
          renameTag(tag.id, newName.trim());
          load();
        }
        setNewName('');
        setMode('list');
        return;
      }
      if (key.backspace || key.delete) { setNewName((n) => n.slice(0, -1)); return; }
      if (input && !key.ctrl && !key.meta) { setNewName((n) => n + input); return; }
      return;
    }

    if (mode === 'detail') {
      if (key.escape) { setMode('list'); return; }
      if (key.leftArrow) {
        const next = Math.max(0, cursor - 1);
        setCursor(next);
        if (visibleTags[next]) { void getTagSummary(visibleTags[next].name).then(setTagSummary); setCatCursor(0); }
        return;
      }
      if (key.rightArrow) {
        const next = Math.min(visibleTags.length - 1, cursor + 1);
        setCursor(next);
        if (visibleTags[next]) { void getTagSummary(visibleTags[next].name).then(setTagSummary); setCatCursor(0); }
        return;
      }
      if (key.upArrow) { setCatCursor((c) => Math.max(0, c - 1)); return; }
      if (key.downArrow) { setCatCursor((c) => Math.min((tagSummary?.byCategory.length ?? 1) - 1, c + 1)); return; }
      if (key.return) {
        const tag = visibleTags[cursor];
        const cat = tagSummary?.byCategory[catCursor];
        if (tag) onNavigate('transactions', { tag: tag.name, category: cat?.category });
        return;
      }
      if (input === 't' && visibleTags[cursor]) {
        onNavigate('transactions', { tag: visibleTags[cursor].name });
        return;
      }
      if (handleNavKey(input, 'tags', onNavigate)) return;
      return;
    }

    // list mode
    if (handleNavKey(input, 'tags', onNavigate)) return;
    if (key.escape) {
      if (search) { setSearch(''); setCursor(0); return; }
      onNavigate('dashboard'); return;
    }
    if (input === '/') { setMode('search'); return; }
    if (key.upArrow) { setCursor((c) => Math.max(0, c - 1)); return; }
    if (key.downArrow) { setCursor((c) => Math.min(visibleTags.length - 1, c + 1)); return; }
    if (input === 'a') { setNewName(''); setMode('add'); return; }
    if (input === 'n' && visibleTags[cursor]) { setNewName(visibleTags[cursor].name); setMode('rename'); return; }
    if (input === 'x' && visibleTags[cursor]) {
      const tag = visibleTags[cursor];
      deleteTag(tag.id);
      showStatus(`Deleted "${tag.name}"`);
      setCursor((c) => Math.max(0, c - 1));
      load();
      return;
    }
    if (key.return && visibleTags[cursor]) {
      openDetail(visibleTags[cursor]);
      return;
    }
    if (input === 't' && visibleTags[cursor]) {
      onNavigate('transactions', { tag: visibleTags[cursor].name });
      return;
    }
  }, { isActive: isActive !== false });

  const tag = visibleTags[cursor];
  const maxCategorySpend = tagSummary?.byCategory[0]?.total ?? 1;

  return (
    <Box flexDirection="column" paddingX={2} paddingY={1}>
      <PageHeader current="tags" showHints={showHints} />

      {mode === 'detail' && tag && tagSummary ? (
        <>
          <Box flexDirection="column" marginTop={1} marginBottom={1}>
            <Text bold>Tags <Text dimColor>— # {tag.name}  ← {cursor + 1} / {tags.length} →</Text></Text>
            {showHints && <Text dimColor>← → tag  ·  ↑↓ category  ·  Enter txns  ·  [t] all txns  ·  Esc back</Text>}
          </Box>

          <Divider />

          <Box gap={6} marginY={1}>
            <StatCard label="Income" value={fmt(tagSummary.income)} color={C_POSITIVE} />
            <StatCard label="Expenses" value={fmt(tagSummary.expenses)} color={C_NEGATIVE} />
            <StatCard label="Net" value={(tagSummary.net >= 0 ? '+' : '-') + fmt(tagSummary.net)} color={tagSummary.net >= 0 ? C_POSITIVE : C_NEGATIVE} />
            <StatCard label="Transactions" value={String(tag.count)} />
          </Box>

          <Divider />

          <Box flexDirection="column" marginTop={1}>
            <SectionHeader>SPENDING BY CATEGORY</SectionHeader>
            <Box flexDirection="column" marginTop={1}>
              {tagSummary.byCategory.length === 0 ? (
                <Text dimColor>No expense data for this tag.</Text>
              ) : (
                tagSummary.byCategory.map((row, i) => {
                  const isSelected = catCursor === i;
                  return (
                    <SelectableRow key={row.category} selected={isSelected}>
                      <Text color={isSelected ? C_ACCENT : undefined}>
                        {truncate(row.category, 20).padEnd(20)}
                      </Text>
                      <Text color={C_WARNING}>{fmt(row.total).padStart(10)}</Text>
                      <Text color={C_ACCENT} dimColor={!isSelected}>{bar(row.total, maxCategorySpend)}</Text>
                    </SelectableRow>
                  );
                })
              )}
            </Box>
          </Box>
        </>
      ) : (
        <>
          <Box marginTop={1}>
            <Text bold>Tags{search ? <Text color={C_WARNING}>  /{search}</Text> : null}</Text>
          </Box>
          <Text dimColor>
            {showHints
              ? '[/] search  ·  [a] add  [n] rename  [x] delete  ·  Enter detail  ·  [t] transactions'
              : '[/] search'}
          </Text>
          {mode === 'search' && <SearchBar value={search} />}
          <Box marginTop={1}><Divider /></Box>

          {visibleTags.length === 0 ? (
            <Box marginTop={1}><Text dimColor>{search ? `No tags matching "${search}".` : 'No tags yet. [a] to create one.'}</Text></Box>
          ) : (
            <Box flexDirection="column" marginTop={1}>
              {visibleTags.map((t, i) => {
                const isSelected = i === cursor;
                return (
                  <SelectableRow key={t.id} selected={isSelected}>
                    <Text color={isSelected ? C_ACCENT : undefined} dimColor={!isSelected}>
                      {t.name.length > tagNameW ? t.name.slice(0, tagNameW - 1) + '…' : t.name.padEnd(tagNameW)}
                    </Text>
                    <Text dimColor>{(t.count + ' tx').padEnd(6)}</Text>
                    <Text color={C_POSITIVE} dimColor={!isSelected}>{fmt(t.inflow).padStart(10)}</Text>
                    <Text color={C_NEGATIVE} dimColor={!isSelected}>{fmt(t.outflow).padStart(10)}</Text>
                  </SelectableRow>
                );
              })}
            </Box>
          )}

          <Box marginTop={1}><Divider /></Box>
          <Text dimColor>{search ? `${visibleTags.length} of ${tags.length}` : `${tags.length}`} tag{tags.length !== 1 ? 's' : ''}</Text>
          {statusMsg && <Text color={C_POSITIVE}>{statusMsg}</Text>}

          {mode === 'add' && (
            <ModalPanel title="New Tag">
              <Text dimColor>Type name · Enter save · Esc cancel</Text>
              <Box marginTop={1} gap={1}>
                <Text>Name: </Text>
                <TextInput value={newName} color={C_WARNING} />
              </Box>
            </ModalPanel>
          )}
          {mode === 'rename' && visibleTags[cursor] && (
            <ModalPanel title="Rename Tag" borderColor={C_WARNING}>
              <Text dimColor>Enter save · Esc cancel</Text>
              <Box marginTop={1} gap={1}>
                <Text>Name: </Text>
                <TextInput value={newName} color={C_WARNING} />
              </Box>
            </ModalPanel>
          )}
        </>
      )}
    </Box>
  );
}
