import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Loader2, Receipt, Search, X } from 'lucide-react';
import { toast } from 'sonner';
import { api } from '@/api';
import { cn, fmt } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';

function amountSearchText(...values) {
  return values
    .filter(value => value !== null && value !== undefined && Number.isFinite(Number(value)))
    .flatMap(value => {
      const num = Number(value);
      return [String(num), num.toFixed(2), `$${num.toFixed(2)}`];
    })
    .join(' ');
}

function billSearchText(bill) {
  return [
    bill.name,
    bill.category_name,
    bill.notes,
    bill.billing_cycle,
    bill.bucket,
    bill.website,
    amountSearchText(
      bill.expected_amount,
      bill.current_balance,
      bill.minimum_payment,
      bill.interest_rate,
    ),
  ].filter(Boolean).join(' ').toLowerCase();
}

function shortcutLabel() {
  if (typeof navigator !== 'undefined' && /Mac|iPhone|iPad|iPod/i.test(navigator.platform)) {
    return 'Cmd K';
  }
  return 'Ctrl K';
}

export default function CommandPalette() {
  const navigate = useNavigate();
  const inputRef = useRef(null);
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState('');
  const [bills, setBills] = useState([]);
  const [loading, setLoading] = useState(false);
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    const openPalette = () => setOpen(true);
    const onKeyDown = (event) => {
      if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'k') {
        event.preventDefault();
        setOpen(value => !value);
      }
    };

    window.addEventListener('command-palette:open', openPalette);
    window.addEventListener('keydown', onKeyDown);
    return () => {
      window.removeEventListener('command-palette:open', openPalette);
      window.removeEventListener('keydown', onKeyDown);
    };
  }, []);

  useEffect(() => {
    if (!open) return;
    window.setTimeout(() => inputRef.current?.focus(), 0);
    if (loaded || loading) return;

    setLoading(true);
    api.allBills({ inactive: true })
      .then(rows => {
        setBills(Array.isArray(rows) ? rows : []);
        setLoaded(true);
      })
      .catch(err => {
        toast.error(err.message || 'Failed to load bills');
      })
      .finally(() => setLoading(false));
  }, [loaded, loading, open]);

  const results = useMemo(() => {
    const q = query.trim().toLowerCase();
    const sorted = [...bills].sort((a, b) => {
      if (!!a.active !== !!b.active) return a.active ? -1 : 1;
      return String(a.name || '').localeCompare(String(b.name || ''));
    });
    if (!q) return sorted.slice(0, 8);
    return sorted
      .filter(bill => billSearchText(bill).includes(q))
      .slice(0, 12);
  }, [bills, query]);

  const close = () => {
    setOpen(false);
    setQuery('');
  };

  const openBills = (bill) => {
    const params = new URLSearchParams({ search: bill.name });
    if (!bill.active) params.set('inactive', '1');
    navigate(`/bills?${params.toString()}`);
    close();
  };

  const openTracker = (bill) => {
    const params = new URLSearchParams({ search: bill.name });
    navigate(`/?${params.toString()}`);
    close();
  };

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogContent className="gap-0 overflow-hidden p-0 sm:max-w-2xl">
        <DialogHeader className="sr-only">
          <DialogTitle>Command palette</DialogTitle>
        </DialogHeader>

        <div className="flex items-center gap-2 border-b border-border/70 px-4 py-3">
          <Search className="h-4 w-4 shrink-0 text-muted-foreground" />
          <Input
            ref={inputRef}
            value={query}
            onChange={event => setQuery(event.target.value)}
            onKeyDown={event => {
              if (event.key === 'Enter' && results[0]) openBills(results[0]);
            }}
            placeholder="Find a bill by name, category, notes, or amount"
            className="h-9 border-0 bg-transparent px-0 text-base shadow-none focus-visible:ring-0"
          />
          {query && (
            <Button
              type="button"
              size="icon"
              variant="ghost"
              className="h-7 w-7 shrink-0"
              onClick={() => setQuery('')}
              aria-label="Clear search"
            >
              <X className="h-4 w-4" />
            </Button>
          )}
        </div>

        <div className="max-h-[min(28rem,70svh)] overflow-y-auto p-2">
          {loading ? (
            <div className="flex items-center justify-center gap-2 px-4 py-12 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading bills...
            </div>
          ) : results.length > 0 ? (
            <div className="space-y-1">
              {results.map(bill => (
                <div
                  key={bill.id}
                  className={cn(
                    'group grid gap-2 rounded-lg border border-transparent p-2 transition-colors',
                    'hover:border-border/70 hover:bg-accent/65 sm:grid-cols-[1fr_auto]',
                  )}
                >
                  <button
                    type="button"
                    onClick={() => openBills(bill)}
                    className="flex min-w-0 items-center gap-3 rounded-md text-left focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50"
                  >
                    <span className="flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary">
                      <Receipt className="h-4 w-4" />
                    </span>
                    <span className="min-w-0">
                      <span className="flex min-w-0 items-center gap-2">
                        <span className="truncate text-sm font-semibold text-foreground">{bill.name}</span>
                        {!bill.active && (
                          <span className="shrink-0 rounded-full border border-border px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
                            Inactive
                          </span>
                        )}
                      </span>
                      <span className="mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-muted-foreground">
                        <span>{bill.category_name || 'Uncategorized'}</span>
                        <span>Due {bill.due_day}</span>
                        <span>{fmt(bill.expected_amount || 0)}</span>
                      </span>
                    </span>
                  </button>
                  <div className="flex items-center justify-end gap-1 pl-12 sm:pl-0">
                    <Button type="button" size="sm" variant="ghost" className="h-8 px-2.5 text-xs" onClick={() => openTracker(bill)}>
                      Tracker
                    </Button>
                    <Button type="button" size="sm" variant="default" className="h-8 px-2.5 text-xs" onClick={() => openBills(bill)}>
                      Bills
                    </Button>
                  </div>
                </div>
              ))}
            </div>
          ) : (
            <div className="px-4 py-12 text-center text-sm text-muted-foreground">
              No bills found.
            </div>
          )}
        </div>

        <div className="flex items-center justify-between border-t border-border/70 px-4 py-2 text-xs text-muted-foreground">
          <span>Enter opens Bills</span>
          <span>{shortcutLabel()}</span>
        </div>
      </DialogContent>
    </Dialog>
  );
}
