import { useEffect, useMemo, useState } from 'react';
import { type Category, type Transaction, type BalancePoint, deleteTransaction, getCategories, getTransactions, createTransaction, updateTransaction, getBalanceSeries } from '../api';
import AccountPage from './AccountPage';
import AppearancePage from './AppearancePage';
import BalanceChart from './BalanceChart';
import ManualManagement from './ManualManagement';
import CategoryPieChart from './CategoryPieChart';
import MockBankModal, { type MockGenerationOptions } from './MockBankModal';
import { BACKEND_URL } from '../config';

function formatAmount(n: number) {
  return new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(n);
}

//https://unirateapi.com/


// Define the structure for the rate data we care about
type RateData = {
  currencyCode: string;
  rate: number;
};

// The currencies you want to display
const TARGET_CURRENCIES = ['EUR', 'USD', 'NOK'];

function CurrencyRates() {
  const [rates, setRates] = useState<RateData[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    async function fetchRates() {
      setLoading(true);
      setError(null);

      try {
        const base = BACKEND_URL.replace(/\/$/, '');
        const url = `${base}/exchange-rates?symbols=${TARGET_CURRENCIES.join(',')}`;
        const token = localStorage.getItem('token');
        const res = await fetch(url, {
          headers: token ? { Authorization: `Bearer ${token}` } : undefined,
          credentials: 'include',
        });
        if (!res.ok) {
          const text = await res.text();
          throw new Error(text || `Failed to load rates (${res.status})`);
        }
        const data: RateData[] = await res.json();
        setRates(data);
      } catch (err: any) {
        setError(err.message || 'Could not load rates');
      } finally {
        setLoading(false);
      }
    }

    fetchRates();
  }, []); // Runs once on component mount

  return (
    // This component will push itself to the bottom of the sidebar
    <div
      className="currency-rates"
      style={{
        padding: '0 1.5rem',
        marginTop: 'auto', // Pushes to bottom
        paddingBottom: '1.5rem' // Adds some spacing at the end
      }}
    >
      <h4 style={{
        margin: '1.5rem 0 0.75rem 0',
        color: '#8a91b4', // Muted color to match dark sidebar
        fontWeight: 500,
        fontSize: '0.9em',
        textTransform: 'uppercase',
      }}>
        Rates (vs CZK)
      </h4>
      {loading && <div style={{ fontSize: '0.9em', color: '#ccc' }}>Loading...</div>}
      {error && <div style={{ fontSize: '0.9em', color: 'crimson' }}>{error}</div>}
      {!loading && !error && (
        <ul style={{ listStyle: 'none', padding: 0, margin: 0, fontSize: '0.9em', color: '#fff' }}>
          {rates.length > 0 ? rates.map(rate => (
            <li key={rate.currencyCode} style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '0.5rem' }}>
              <strong>{rate.currencyCode}</strong>
              <span>{rate.rate.toFixed(3)}</span>
            </li>
          )) : <li style={{color: '#8a91b4'}}>No rates found.</li>}
        </ul>
      )}

      <a
        href="https://unirateapi.com"
        target="_blank"
        rel="noopener noreferrer"
        style={{
          display: 'block',
          marginTop: '1rem',
          fontSize: '0.8em',
          color: '#8a91b4', // Muted color
          textDecoration: 'none'
        }}
      >
        Exchange Rates By UniRateAPI
      </a>
    </div>
  );
}


export default function Dashboard({ onLogout }: { onLogout: () => void }) {
  const [current, setCurrent] = useState<'home' | 'manual' | 'account' | 'appearance'>('home');
  const [transactions, setTransactions] = useState<Transaction[]>([]);
  const [categories, setCategories] = useState<Category[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [isMockModalOpen, setMockModalOpen] = useState(false);
  const [isGenerating, setIsGenerating] = useState(false);

  // Start CSAS (George) OAuth after login
  async function startOauthCsas() {
    const base = BACKEND_URL.replace(/\/$/, '');
    const url = `${base}/auth/csas/authorize`;
    try {
      const token = localStorage.getItem('token');
      const res = await fetch(url, {
        credentials: 'include',
        headers: token ? { Authorization: `Bearer ${token}` } : undefined,
      });
      const data = await res.json();
      if (data && typeof data.authorization_url === 'string') {
        window.location.assign(data.authorization_url);
      } else {
        alert('Cannot start CSAS OAuth.');
      }
    } catch (e) {
      alert('Cannot start CSAS OAuth.');
    }
  }

  // Filters
  const [minAmount, setMinAmount] = useState<string>('');
  const [maxAmount, setMaxAmount] = useState<string>('');
  const [filterCategoryId, setFilterCategoryId] = useState<number | ''>('');
  const [searchText, setSearchText] = useState('');

  // Date-range filter
  const [startDate, setStartDate] = useState<string>(''); // YYYY-MM-DD
  const [endDate, setEndDate] = useState<string>('');

  // Pagination over filtered transactions (20 per page), 0 = latest (most recent)
  const pageSize = 20;
  const [page, setPage] = useState<number>(0);

  // Balance chart series for current date filter
  const [balanceSeries, setBalanceSeries] = useState<BalancePoint[]>([]);

  // Manual forms moved to ManualManagement page

  // Inline edit state for transaction editing
  const [editingTxId, setEditingTxId] = useState<number | null>(null);
  const [editingCategoryIds, setEditingCategoryIds] = useState<number[]>([]);
  const [editingAmount, setEditingAmount] = useState<string>('');
  const [editingDescription, setEditingDescription] = useState<string>('');
  const [editingDate, setEditingDate] = useState<string>(''); // YYYY-MM-DD

  // Sidebar toggle for mobile
  const [sidebarOpen, setSidebarOpen] = useState(false);



  async function loadAll() {
    setLoading(true);
    setError(null);
    try {
      const [txs, cats, series] = await Promise.all([
        getTransactions(startDate || undefined, endDate || undefined),
        getCategories(),
        getBalanceSeries(startDate || undefined, endDate || undefined),
      ]);
      setTransactions(txs);
      setCategories(cats);
      setBalanceSeries(series);
      // reset paging to most recent
      setPage(0);
    } catch (err: any) {
      setError(err?.message || 'Failed to load data');
    } finally {
      setLoading(false);
    }
  }

  async function handleGenerateMockTransactions(options: MockGenerationOptions) {
    setIsGenerating(true);
    setMockModalOpen(false);

    try {
      const base = BACKEND_URL.replace(/\/$/, '');
      const url = `${base}/mock-bank/generate`;
      const token = localStorage.getItem('token');
      const res = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...(token ? { Authorization: `Bearer ${token}` } : {}),
        },
        credentials: 'include',
        body: JSON.stringify(options),
      });
      if (!res.ok) {
        const text = await res.text();
        throw new Error(text || `Failed to generate mock transactions (${res.status})`);
      }
      const generated: Array<{ amount: number; date: string; category_ids: number[]; description?: string | null }>
        = await res.json();

      const newTransactions: Transaction[] = [];
      for (const g of generated) {
        try {
          const created = await createTransaction({
            amount: g.amount,
            date: g.date,
            category_ids: g.category_ids || [],
            description: g.description || undefined,
          });
          newTransactions.push(created);
        } catch (err) {
          console.error('Failed to create mock transaction:', err);
          // continue creating others
        }
      }

      alert(`${newTransactions.length} mock transactions were successfully generated!`);
    } catch (err: any) {
      console.error(err);
      alert(err?.message || 'Failed to generate mock transactions');
    } finally {
      setIsGenerating(false);
      await loadAll();
    }
  }

  useEffect(() => { loadAll(); }, [startDate, endDate]);

  const filtered = useMemo(() => {
    let arr = [...transactions];
    const min = minAmount !== '' ? Number(minAmount) : undefined;
    const max = maxAmount !== '' ? Number(maxAmount) : undefined;
    if (min !== undefined) arr = arr.filter(t => t.amount >= min);
    if (max !== undefined) arr = arr.filter(t => t.amount <= max);
    if (filterCategoryId !== '') arr = arr.filter(t => t.category_ids.includes(filterCategoryId as number));
    if (searchText.trim()) arr = arr.filter(t => (t.description || '').toLowerCase().includes(searchText.toLowerCase()));
    return arr;
  }, [transactions, minAmount, maxAmount, filterCategoryId, searchText]);

  const sortedDesc = useMemo(() => {
    return [...filtered].sort((a, b) => {
      const ad = (a.date || '') > (b.date || '') ? 1 : (a.date || '') < (b.date || '') ? -1 : 0;
      if (ad !== 0) return -ad; // date desc
      return b.id - a.id; // fallback id desc
    });
  }, [filtered]);

  const totalPages = Math.ceil(sortedDesc.length / pageSize);
  const pageStart = page * pageSize;
  const pageEnd = pageStart + pageSize;
  const visible = sortedDesc.slice(pageStart, pageEnd);

  function categoryNameById(id: number) { return categories.find(c => c.id === id)?.name || `#${id}`; }


  function beginEditTransaction(t: Transaction) {
    setEditingTxId(t.id);
    setEditingCategoryIds([...(t.category_ids || [])]);
    setEditingAmount(String(t.amount));
    setEditingDescription(t.description || '');
    setEditingDate(t.date || '');
  }
  function cancelEditTransaction() {
    setEditingTxId(null);
    setEditingCategoryIds([]);
    setEditingAmount('');
    setEditingDescription('');
    setEditingDate('');
  }
  async function saveEditTransaction() {
    if (editingTxId == null) return;
    const amountNum = Number(editingAmount);
    if (Number.isNaN(amountNum)) {
      alert('Amount must be a number.');
      return;
    }
    try {
      const updated = await updateTransaction(editingTxId, {
        amount: amountNum,
        description: editingDescription,
        date: editingDate || undefined,
        category_ids: editingCategoryIds,
      });
      setTransactions(prev => prev.map(p => (p.id === updated.id ? updated : p)));
      // Optionally refresh balance series to reflect changes immediately
      try { setBalanceSeries(await getBalanceSeries(startDate || undefined, endDate || undefined)); } catch {}
      cancelEditTransaction();
    } catch (err: any) {
      alert(err?.message || 'Failed to update transaction');
    }
  }
  async function handleDeleteTransaction(id: number) {
    if (!confirm('Delete this transaction? This cannot be undone.')) return;
    try {
      await deleteTransaction(id);
      setTransactions(prev => prev.filter(t => t.id !== id));
      try { setBalanceSeries(await getBalanceSeries(startDate || undefined, endDate || undefined)); } catch {}
    } catch (err: any) {
      alert(err?.message || 'Failed to delete transaction');
    }
  }

  return (
    <div className={`app-layout ${sidebarOpen ? 'sidebar-open' : ''}`}>
      <aside className="sidebar" style={{ display: 'flex', flexDirection: 'column' }}>
        <div>
          <div className="logo">Finance Tracker</div>
          <nav className="nav" onClick={() => setSidebarOpen(false)}>
            <button className={current === 'home' ? 'active' : ''} onClick={() => setCurrent('home')}>Home</button>
            <button className={current === 'manual' ? 'active' : ''} onClick={() => setCurrent('manual')}>Manual management</button>
            <button className={current === 'account' ? 'active' : ''} onClick={() => setCurrent('account')}>Account</button>
            <button className={current === 'appearance' ? 'active' : ''} onClick={() => setCurrent('appearance')}>Appearance</button>
          </nav>
        </div>

        <CurrencyRates />

      </aside>
      <div className="content">
        <div className="topbar">
          <button
            className="icon-btn hamburger"
            aria-label="Open menu"
            aria-expanded={sidebarOpen}
            onClick={() => setSidebarOpen(true)}
          >☰</button>
          <h2 style={{ margin: 0 }}>{current === 'home' ? 'Dashboard' : current === 'manual' ? 'Manual management' : current === 'account' ? 'Account' : 'Appearance'}</h2>
          <div className="actions">
            <span className="user muted">Signed in</span>
            <button className="btn" onClick={onLogout}>Logout</button>
          </div>
        </div>
        <main className="page space-y">
          {current === 'home' && (
            <>
              <section className="card space-y">
                  <h3>Bank connections</h3>
                  <div className="connection-row">
                    <p className="muted" style={{ margin: 0 }}>Connect your CSAS (George) account.</p>
                    <button className="btn primary" onClick={startOauthCsas}>Connect CSAS (George)</button>
                  </div>
                  <div className="connection-row">
                    <p className="muted" style={{ margin: 0 }}>Generate data from a mock bank.</p>
                    <button className="btn primary" onClick={() => setMockModalOpen(true)}>Connect Mock Bank</button>
                  </div>
              </section>



              <section className="card">
                <h3>Filters</h3>
                <div className="form-row" style={{ gap: 8, flexWrap: 'wrap' }}>
                  <input className="input" type="date" placeholder="Start date" value={startDate} onChange={(e) => setStartDate(e.target.value)} />
                  <input className="input" type="date" placeholder="End date" value={endDate} onChange={(e) => setEndDate(e.target.value)} />
                  <input className="input" type="number" step="0.01" placeholder="Min amount" value={minAmount} onChange={(e) => setMinAmount(e.target.value)} />
                  <input className="input" type="number" step="0.01" placeholder="Max amount" value={maxAmount} onChange={(e) => setMaxAmount(e.target.value)} />
                  <select className="input" value={filterCategoryId} onChange={(e) => setFilterCategoryId(e.target.value ? Number(e.target.value) : '')}>
                    <option value="">All categories</option>
                    {categories.map(c => (<option key={c.id} value={c.id}>{c.name}</option>))}
                  </select>
                  <input className="input" type="text" placeholder="Search in description" value={searchText} onChange={(e) => setSearchText(e.target.value)} />
                </div>
              </section>

              <section className="card">
                <h3>Balance over time</h3>
                {loading ? (
                  <div>Loading…</div>
                ) : error ? (
                  <div style={{ color: 'crimson' }}>{error}</div>
                ) : (
                  <BalanceChart data={balanceSeries} />
                )}
              </section>

              {/* 3. Add the new section for the Category Pie Chart */}
              <section className="card">
                {loading ? (
                  <div>Loading…</div>
                ) : error ? (
                  <div style={{ color: 'crimson' }}>{error}</div>
                ) : (
                  // Pass the filtered transactions to see the breakdown for the current view
                  <CategoryPieChart transactions={filtered} categories={categories} />
                )}
              </section>

              <section className="card">
                <h3>Transactions</h3>
                {loading ? (
                  <div>Loading…</div>
                ) : error ? (
                  <div style={{ color: 'crimson' }}>{error}</div>
                ) : filtered.length === 0 ? (
                  <div>No transactions</div>
                ) : (
                  <>
                    <div className="table-controls">
                      <div className="muted">
                        Showing {visible.length} of {filtered.length} (page {Math.min(page + 1, Math.max(1, totalPages))}/{Math.max(1, totalPages)})
                      </div>
                      <div className="actions">
                        <button className="btn primary" disabled={page <= 0} onClick={() => setPage(p => Math.max(0, p - 1))}>Previous</button>
                        <button className="btn primary" disabled={page >= totalPages - 1} onClick={() => setPage(p => Math.min(totalPages - 1, p + 1))}>Next</button>
                      </div>
                    </div>
                    <table className="table responsive">
                      <thead>
                        <tr>
                          <th>Date</th>
                          <th style={{ textAlign: 'right' }}>Amount</th>
                          <th>Description</th>
                          <th>Categories</th>
                          <th>Actions</th>
                        </tr>
                      </thead>
                      <tbody>
                        {visible.map(t => (
                          <tr key={t.id}>
                            {/* Date cell */}
                            <td data-label="Date">
                              {editingTxId === t.id ? (
                                <input
                                  className="input"
                                  type="date"
                                  value={editingDate}
                                  onChange={(e) => setEditingDate(e.target.value)}
                                />
                              ) : (
                                t.date || ''
                              )}
                            </td>

                            {/* Amount cell */}
                            <td data-label="Amount" className="amount" style={{ textAlign: 'right' }}>
                              {editingTxId === t.id ? (
                                <input
                                  className="input"
                                  type="number"
                                  step="0.01"
                                  value={editingAmount}
                                  onChange={(e) => setEditingAmount(e.target.value)}
                                  style={{ textAlign: 'right' }}
                                />
                              ) : (
                                formatAmount(t.amount)
                              )}
                            </td>

                            {/* Description cell */}
                            <td data-label="Description">
                              {editingTxId === t.id ? (
                                <input
                                  className="input"
                                  type="text"
                                  value={editingDescription}
                                  onChange={(e) => setEditingDescription(e.target.value)}
                                />
                              ) : (
                                t.description || ''
                              )}
                            </td>

                            {/* Categories cell */}
                            <td data-label="Categories">
                              {editingTxId === t.id ? (
                                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                                  <select
                                    multiple
                                    className="input"
                                    value={editingCategoryIds.map(String)}
                                    onChange={(e) => {
                                      const opts = Array.from(e.currentTarget.selectedOptions).map(o => Number(o.value));
                                      setEditingCategoryIds(opts);
                                    }}
                                  >
                                    {categories.map(c => (
                                      <option key={c.id} value={c.id}>{c.name}</option>
                                    ))}
                                  </select>
                                </div>
                              ) : (
                                <span>{t.category_ids.map(id => categoryNameById(id)).join(', ') || '—'}</span>
                              )}
                            </td>

                            {/* Actions cell */}
                            <td data-label="Actions">
                              {editingTxId === t.id ? (
                                <div className="actions" style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
                                  <button className="btn small" onClick={saveEditTransaction}>Save</button>
                                  <button className="btn small" onClick={cancelEditTransaction}>Cancel</button>
                                  <button className="btn small" onClick={() => handleDeleteTransaction(t.id)}>Delete</button>
                                </div>
                              ) : (
                                <div className="actions" style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
                                  <button className="btn small" onClick={() => beginEditTransaction(t)}>Edit</button>
                                  <button className="btn small" onClick={() => handleDeleteTransaction(t.id)}>Delete</button>
                                </div>
                              )}
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </>
                )}
              </section>
            </>
          )}

          {current === 'account' && (
            // lazy import avoided for simplicity
            <AccountPage onDeleted={onLogout} />
          )}

          {current === 'manual' && (
            <ManualManagement
              categories={categories}
              onTransactionAdded={(t) => setTransactions(prev => [t, ...prev])}
              onCategoryCreated={(c) => setCategories(prev => [...prev, c])}
            />
          )}

          {current === 'appearance' && (
            <AppearancePage />
          )}
        </main>
      </div>
        <MockBankModal
          isOpen={isMockModalOpen}
          isGenerating={isGenerating}
          categories={categories}
          onClose={() => setMockModalOpen(false)}
          onGenerate={handleGenerateMockTransactions}
        />
      {sidebarOpen && <div className="backdrop" onClick={() => setSidebarOpen(false)} />}
    </div>
  );
}
