'use client';

import { useState, useEffect, useCallback } from 'react';
import { listCabinetEvents, getSpendingSummary } from '@/services/cabinet-events';
import { listMedicines } from '@/services/medicines';
import { CabinetEventType } from '@meshitrack/shared';
import type { z } from 'zod/v4';
import type { CabinetEventResponseSchema, SpendingSummaryResponseSchema } from '@meshitrack/shared';

type CabinetEvent = z.infer<typeof CabinetEventResponseSchema>;
type SpendingSummary = z.infer<typeof SpendingSummaryResponseSchema>;

type MedicineOption = {
  _id: string;
  name: string;
};

const EVENT_TYPE_LABELS: Record<string, string> = {
  purchased: 'Purchased',
  consumed: 'Consumed',
  adjusted: 'Adjusted',
  discarded: 'Discarded',
  restored: 'Restored',
  deleted: 'Deleted',
};

const EVENT_TYPE_PILL: Record<string, string> = {
  purchased: 'mt-pill--ok',
  consumed: 'mt-pill--info',
  adjusted: 'mt-pill--warn',
  discarded: 'mt-pill--danger',
  restored: 'mt-pill--brand',
  deleted: 'mt-pill--ghost',
};

function formatDateTime(dateStr: string): string {
  return new Date(dateStr).toLocaleString();
}

/* v8 ignore next 4 */
function _formatQuantityChange(event: CabinetEvent): string {
  const sign = event.quantity > 0 ? '+' : '';
  return `${sign}${event.quantity}`;
}

function QuantityBadge({ quantity }: { quantity: number }) {
  const isPositive = quantity > 0;
  return (
    <span className={`text-sm font-semibold ${isPositive ? 'text-green-600' : 'text-red-600'}`}>
      {isPositive ? '+' : ''}
      {quantity}
    </span>
  );
}

// --- Spending summary ---

function SpendingSummaryView({
  householdId,
  medicines,
}: {
  householdId: string;
  medicines: MedicineOption[];
}) {
  const [summary, setSummary] = useState<SpendingSummary | null>(null);
  const [loading, setLoading] = useState(true);
  const [period, setPeriod] = useState<'month' | 'quarter' | 'year'>('month');
  const [medicineId, setMedicineId] = useState('');
  const [error, setError] = useState('');

  const fetchSummary = useCallback(async () => {
    setLoading(true);
    setError('');
    try {
      const result = await getSpendingSummary(householdId, {
        period,
        medicineId: medicineId || undefined,
      });
      setSummary(result);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load spending summary');
    } finally {
      setLoading(false);
    }
  }, [householdId, period, medicineId]);

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

  const PERIOD_LABELS = { month: 'This month', quarter: 'This quarter', year: 'This year' };

  return (
    <div className="mt-card">
      <div className="flex items-center justify-between mb-4 flex-wrap gap-3">
        <h2 className="text-lg font-semibold">Spending Summary</h2>
        <div className="flex items-center gap-2">
          <select
            value={period}
            onChange={(e) => setPeriod(e.target.value as 'month' | 'quarter' | 'year')}
            className="mt-field"
            style={{ width: 'auto' }}
          >
            {Object.entries(PERIOD_LABELS).map(([v, label]) => (
              <option key={v} value={v}>
                {label}
              </option>
            ))}
          </select>
          <select
            value={medicineId}
            onChange={(e) => setMedicineId(e.target.value)}
            className="mt-field"
            style={{ width: 'auto' }}
          >
            <option value="">All medicines</option>
            {medicines.map((m) => (
              <option key={m._id} value={m._id}>
                {m.name}
              </option>
            ))}
          </select>
        </div>
      </div>

      {error && <div className="mt-alert mt-alert--danger mb-4">{error}</div>}

      {loading ? (
        <div className="animate-pulse space-y-2">
          <div className="h-6 w-32 rounded bg-gray-200" />
          <div className="h-20 rounded bg-gray-200" />
        </div>
      ) : summary && summary.totalSpent > 0 ? (
        <div className="space-y-5">
          <div className="text-2xl font-bold text-gray-900">
            {summary.currency ? `${summary.currency} ` : ''}
            {summary.totalSpent.toFixed(2)}
            <span className="text-sm font-normal text-gray-500 ml-2">total spent</span>
          </div>

          {summary.byMedicine.length > 0 && (
            <div>
              <h3 className="text-sm font-semibold text-gray-700 mb-2">By medicine</h3>
              <div className="space-y-2">
                {summary.byMedicine.map((item) => (
                  <div
                    key={item.medicineId}
                    className="flex items-center justify-between rounded-lg border p-3"
                  >
                    <div>
                      <span className="text-sm font-medium text-gray-900">{item.medicineName}</span>
                      <span className="ml-2 text-xs text-gray-500">
                        {item.purchaseCount} purchase{item.purchaseCount !== 1 ? 's' : ''} &bull;{' '}
                        avg {summary.currency ? `${summary.currency} ` : ''}
                        {item.avgUnitPrice.toFixed(2)}/unit
                      </span>
                    </div>
                    <span className="text-sm font-semibold text-gray-800">
                      {summary.currency ? `${summary.currency} ` : ''}
                      {item.totalSpent.toFixed(2)}
                    </span>
                  </div>
                ))}
              </div>
            </div>
          )}

          {summary.byPeriod.length > 0 && (
            <div>
              <h3 className="text-sm font-semibold text-gray-700 mb-2">By period</h3>
              <div className="space-y-2">
                {summary.byPeriod.map((item) => (
                  <div
                    key={item.period}
                    className="flex items-center justify-between rounded-lg border p-3"
                  >
                    <span className="text-sm text-gray-700">{item.period}</span>
                    <span className="text-sm font-semibold text-gray-800">
                      {summary.currency ? `${summary.currency} ` : ''}
                      {item.totalSpent.toFixed(2)}
                    </span>
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      ) : (
        <p className="text-sm text-gray-500 py-4 text-center">
          No purchase data found for this period.
        </p>
      )}
    </div>
  );
}

// --- Event timeline ---

function EventTimeline({
  householdId,
  medicines,
}: {
  householdId: string;
  medicines: MedicineOption[];
}) {
  const [events, setEvents] = useState<CabinetEvent[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [filterEventType, setFilterEventType] = useState('');
  const [filterMedicineId, setFilterMedicineId] = useState('');
  const [startDate, setStartDate] = useState('');
  const [endDate, setEndDate] = useState('');
  const [cursor, setCursor] = useState<string | null>(null);
  const [hasMore, setHasMore] = useState(false);

  const fetchEvents = useCallback(
    async (append = false) => {
      if (!append) setLoading(true);
      setError('');
      try {
        const result = await listCabinetEvents(householdId, {
          eventType: filterEventType || undefined,
          medicineId: filterMedicineId || undefined,
          startDate: startDate ? new Date(startDate).toISOString() : undefined,
          endDate: endDate ? new Date(endDate).toISOString() : undefined,
          cursor: append ? (cursor ?? undefined) : undefined,
          limit: 20,
        });
        setEvents((prev) => (append ? [...prev, ...result.data] : result.data));
        setCursor(result.pagination.cursor);
        setHasMore(result.pagination.hasMore);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load events');
      } finally {
        setLoading(false);
      }
    },
    [householdId, filterEventType, filterMedicineId, startDate, endDate, cursor],
  );

  // Refetch from scratch when filters change
  useEffect(() => {
    setCursor(null);
    setEvents([]);
    fetchEvents(false);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [householdId, filterEventType, filterMedicineId, startDate, endDate]);

  return (
    <div className="mt-card">
      <h2 className="text-lg font-semibold mb-4">Cabinet Activity</h2>

      <div className="mb-4 flex flex-wrap items-center gap-3">
        <select
          value={filterEventType}
          onChange={(e) => setFilterEventType(e.target.value)}
          className="mt-field"
          style={{ width: 'auto' }}
        >
          <option value="">All event types</option>
          {Object.values(CabinetEventType).map((t) => (
            <option key={t} value={t}>
              {/* v8 ignore next */ EVENT_TYPE_LABELS[t] ?? t}
            </option>
          ))}
        </select>
        <select
          value={filterMedicineId}
          onChange={(e) => setFilterMedicineId(e.target.value)}
          className="mt-field"
          style={{ width: 'auto' }}
        >
          <option value="">All medicines</option>
          {medicines.map((m) => (
            <option key={m._id} value={m._id}>
              {m.name}
            </option>
          ))}
        </select>
        <input
          type="date"
          value={startDate}
          onChange={(e) => setStartDate(e.target.value)}
          className="mt-field"
          style={{ width: 'auto' }}
          title="Start date"
        />
        <input
          type="date"
          value={endDate}
          onChange={(e) => setEndDate(e.target.value)}
          className="mt-field"
          style={{ width: 'auto' }}
          title="End date"
        />
        {(filterEventType || filterMedicineId || startDate || endDate) && (
          <button
            onClick={() => {
              setFilterEventType('');
              setFilterMedicineId('');
              setStartDate('');
              setEndDate('');
            }}
            className="mt-link text-sm"
          >
            Clear filters
          </button>
        )}
      </div>

      {error && (
        <div className="mt-alert mt-alert--danger mb-4">
          {error}
          <button onClick={() => setError('')} className="ml-2 underline">
            Dismiss
          </button>
        </div>
      )}

      {loading ? (
        <div className="space-y-3">
          {Array.from({ length: 5 }).map((_, i) => (
            <div key={i} className="animate-pulse h-14 rounded-lg bg-gray-200" />
          ))}
        </div>
      ) : events.length === 0 ? (
        <p className="text-sm text-center text-gray-500 py-6">
          No events found for the selected filters.
        </p>
      ) : (
        <div className="relative">
          {/* Timeline line */}
          <div className="absolute left-4 top-0 bottom-0 w-px bg-gray-200" />
          <div className="space-y-4 pl-10">
            {events.map((event) => (
              <div key={event._id} className="relative">
                {/* Dot */}
                <div
                  className={`absolute -left-6 top-2 h-3 w-3 rounded-full border-2 border-white ${
                    event.quantity > 0 ? 'bg-green-400' : 'bg-red-400'
                  }`}
                />
                <div className="rounded-lg border bg-gray-50 p-3">
                  <div className="flex items-start justify-between gap-3 flex-wrap">
                    <div className="flex items-center gap-2 flex-wrap">
                      <span
                        className={`mt-pill ${/* v8 ignore next */ EVENT_TYPE_PILL[event.eventType] ?? 'mt-pill--ghost'}`}
                      >
                        {/* v8 ignore next */ EVENT_TYPE_LABELS[event.eventType] ?? event.eventType}
                      </span>
                      <span className="text-sm font-medium text-gray-900">
                        {event.medicineName}
                      </span>
                      <QuantityBadge quantity={event.quantity} />
                      <span className="text-xs text-gray-500">
                        {event.quantityBefore} &rarr; {event.quantityAfter}
                      </span>
                    </div>
                    <span className="text-xs text-gray-400 shrink-0">
                      {formatDateTime(event.createdAt)}
                    </span>
                  </div>
                  {(event.reason || event.notes || event.storeName || event.totalPrice) && (
                    <div className="mt-1 flex flex-wrap gap-3 text-xs text-gray-500">
                      {event.reason && <span>Reason: {event.reason}</span>}
                      {event.storeName && <span>Store: {event.storeName}</span>}
                      {event.totalPrice && (
                        <span>
                          {event.currency ? `${event.currency} ` : ''}
                          {event.totalPrice.toFixed(2)}
                        </span>
                      )}
                      {event.notes && <span>{event.notes}</span>}
                    </div>
                  )}
                </div>
              </div>
            ))}
          </div>

          {hasMore && (
            <div className="mt-4 text-center">
              <button onClick={() => fetchEvents(true)} className="mt-btn mt-btn--ghost">
                Load more
              </button>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// --- Main component ---

export function ActivityTab({ householdId }: { householdId: string }) {
  const [medicines, setMedicines] = useState<MedicineOption[]>([]);

  useEffect(() => {
    listMedicines(householdId, { limit: 100 })
      .then((r) =>
        setMedicines(
          r.data.map((m: { _id: string; name: string }) => ({ _id: m._id, name: m.name })),
        ),
      )
      .catch(() => {});
  }, [householdId]);

  return (
    <div className="space-y-6">
      <SpendingSummaryView householdId={householdId} medicines={medicines} />
      <EventTimeline householdId={householdId} medicines={medicines} />
    </div>
  );
}
