import { useCallback, useEffect, useState } from 'react';
import { getTracker, toggleBillPaid, type TrackerData, type Bill } from './api';

interface Props {
  baseUrl: string;
  /** Called when the API reports the session is no longer valid (401). */
  onUnauthenticated: () => void;
}

const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const MONTHS_SHORT = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

const money = (n: number) => n.toLocaleString('en-US', { style: 'currency', currency: 'USD' });

/** "2026-07-01" → "Jul 1" without tripping over timezones. */
function shortDate(iso: string): string {
  const [, m, d] = iso.split('-').map(Number);
  return `${MONTHS_SHORT[(m || 1) - 1]} ${d}`;
}

function billTone(b: Bill): 'paid' | 'overdue' | 'upcoming' {
  if (b.is_settled || b.status === 'paid') return 'paid';
  if (b.status === 'missed') return 'overdue';
  return 'upcoming';
}

function statusLabel(b: Bill): string {
  const tone = billTone(b);
  if (tone === 'paid') return 'Paid';
  if (tone === 'overdue') return 'Overdue';
  return 'Upcoming';
}

const CheckIcon = (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
    <path d="M20 6 9 17l-5-5" />
  </svg>
);

export default function TrackerScreen({ baseUrl, onUnauthenticated }: Props) {
  const [ym, setYm] = useState<{ year: number; month: number } | null>(null);
  const [data, setData] = useState<TrackerData | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [busyId, setBusyId] = useState<number | null>(null);

  const load = useCallback(
    async (target?: { year: number; month: number }) => {
      setLoading(true);
      setError('');
      const res = await getTracker(baseUrl, target?.year, target?.month);
      if (res.status === 401) {
        onUnauthenticated();
        return;
      }
      if (!res.ok || !res.data) {
        setError(res.error || 'Could not load your bills.');
        setLoading(false);
        return;
      }
      setData(res.data);
      setYm({ year: res.data.year, month: res.data.month });
      setLoading(false);
    },
    [baseUrl, onUnauthenticated],
  );

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

  function nav(delta: number) {
    if (!ym) return;
    let month = ym.month + delta;
    let year = ym.year;
    if (month < 1) { month = 12; year -= 1; }
    if (month > 12) { month = 1; year += 1; }
    load({ year, month });
  }

  async function toggle(bill: Bill) {
    setBusyId(bill.id);
    const res = await toggleBillPaid(baseUrl, bill.id);
    setBusyId(null);
    if (res.status === 401) { onUnauthenticated(); return; }
    if (res.ok) load(ym ?? undefined);
  }

  if (loading && !data) {
    return (
      <div className="app-state">
        <div className="spinner" />
      </div>
    );
  }

  if (error && !data) {
    return (
      <div className="app-state">
        <h2>Couldn't load your bills</h2>
        <p>{error}</p>
        <button className="btn-primary" style={{ maxWidth: 200 }} onClick={() => load(ym ?? undefined)}>Try again</button>
      </div>
    );
  }

  const d = data!;
  const rows = d.rows || [];
  const s = d.summary;
  const unpaid = rows.length - s.count_paid;
  const lastDay = new Date(d.year, d.month, 0).getDate();

  return (
    <>
      <div>
        <div className="tracker-kicker">Monthly tracker</div>
        <h1 className="tracker-title">{MONTHS[d.month - 1]} {d.year}</h1>
        <div className="tracker-range">{MONTHS_SHORT[d.month - 1]} 1 – {MONTHS_SHORT[d.month - 1]} {lastDay}</div>
      </div>

      <div className="stat-grid">
        <div className="stat stat--paid">
          <span className="stat__label">Paid</span>
          <span className="stat__value">{s.count_paid}</span>
        </div>
        <div className={'stat' + (unpaid > 0 ? ' stat--warn' : '')}>
          <span className="stat__label">Needs action</span>
          <span className="stat__value">{unpaid}</span>
        </div>
        <div className="stat">
          <span className="stat__label">Bills</span>
          <span className="stat__value">{rows.length}</span>
        </div>
        <div className="stat">
          <span className="stat__label">Remaining</span>
          <span className="stat__value">{money(s.total_remaining)}</span>
        </div>
      </div>

      <div className="month-nav">
        <div className="month-nav__pager">
          <button onClick={() => nav(-1)} aria-label="Previous month">‹</button>
          <span>{MONTHS[d.month - 1]} {d.year}</span>
          <button onClick={() => nav(1)} aria-label="Next month">›</button>
        </div>
      </div>

      {rows.length === 0 ? (
        <div className="app-state">
          <h2>No bills this month</h2>
          <p>When you add bills, they'll show up here with what's paid and what's due.</p>
        </div>
      ) : (
        <div className="bill-list">
          {rows.map(b => {
            const tone = billTone(b);
            return (
              <div key={b.id} className={`bill bill--${tone}`}>
                <button
                  className="bill__toggle"
                  onClick={() => toggle(b)}
                  disabled={busyId === b.id}
                  aria-pressed={tone === 'paid'}
                  aria-label={tone === 'paid' ? `Mark ${b.name} unpaid` : `Mark ${b.name} paid`}
                >
                  {CheckIcon}
                </button>
                <div className="bill__body">
                  <span className="bill__name">{b.name}</span>
                  <span className="bill__meta">
                    {b.category_name ? `${b.category_name} · ` : ''}due {shortDate(b.due_date)}
                  </span>
                </div>
                <div className="bill__right">
                  <div className="bill__amount">{money(b.expected_amount)}</div>
                  <div className="bill__status">{statusLabel(b)}</div>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </>
  );
}
