import { useEffect, useState } from 'react';
import { useDatabase } from './useDatabase';

const DAY_MS = 24 * 60 * 60 * 1000;
const WEEK_MS = 7 * DAY_MS;
const MONTH_MS = 30 * DAY_MS;

export interface DailyCompletion {
  label: string;
  count: number;
}

export interface CategoryStat {
  id: string;
  name: string;
  color: string;
  count: number;
}

export interface PriorityStat {
  priority: string;
  label: string;
  count: number;
}

export interface TaskStats {
  loading: boolean;
  totalCompleted: number;
  completedLast7: number;
  completedLast30: number;
  activeCount: number;
  overdueCount: number;
  completionRate: number;
  daily: DailyCompletion[];
  byCategory: CategoryStat[];
  byPriority: PriorityStat[];
  currentStreak: number;
}

export const PRIORITY_LABELS: Record<string, string> = {
  high: 'High',
  medium: 'Medium',
  low: 'Low',
  none: 'No priority',
};

function startOfDay(ts: number): number {
  const d = new Date(ts);
  d.setHours(0, 0, 0, 0);
  return d.getTime();
}

function dayLabel(dayStart: number): string {
  const d = new Date(dayStart);
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const diff = Math.round((today.getTime() - d.getTime()) / DAY_MS);
  if (diff === 0) return 'Today';
  if (diff === 1) return 'Yest';
  return d.toLocaleDateString(undefined, { weekday: 'short' });
}

const EMPTY_STATS: TaskStats = {
  loading: true,
  totalCompleted: 0,
  completedLast7: 0,
  completedLast30: 0,
  activeCount: 0,
  overdueCount: 0,
  completionRate: 0,
  daily: [],
  byCategory: [],
  byPriority: [],
  currentStreak: 0,
};

export function useStats(): TaskStats {
  const { collections, isReady } = useDatabase();
  const [stats, setStats] = useState<TaskStats>(EMPTY_STATS);

  useEffect(() => {
    if (!isReady) return;
    let mounted = true;

    const compute = () => {
      Promise.all([
        collections.tasks.query().fetch(),
        collections.categories.query().fetch(),
      ])
        .then(([allTasks, categories]) => {
          const now = Date.now();
          const todayStart = startOfDay(now);
          const weekStart = todayStart - WEEK_MS;
          const monthStart = todayStart - MONTH_MS;

          const categoryCounts = new Map<string, number>();
          const priorityCounts = new Map<string, number>();
          const dayBucket = new Map<number, number>();

          let totalCompleted = 0;
          let completedLast7 = 0;
          let completedLast30 = 0;
          let activeCount = 0;
          let overdueCount = 0;

          for (const t of allTasks) {
            if (t.completed) {
              if (t.completedAt == null) continue;
              const ts = t.completedAt as number;
              totalCompleted++;
              categoryCounts.set(t.categoryId, (categoryCounts.get(t.categoryId) ?? 0) + 1);
              priorityCounts.set(t.priority, (priorityCounts.get(t.priority) ?? 0) + 1);
              if (ts >= weekStart) completedLast7++;
              if (ts >= monthStart) completedLast30++;
              const day = startOfDay(ts);
              dayBucket.set(day, (dayBucket.get(day) ?? 0) + 1);
            } else {
              activeCount++;
              if (t.dueDate > 0 && t.dueDate < now) overdueCount++;
            }
          }

          const daily: DailyCompletion[] = [];
          for (let i = 6; i >= 0; i--) {
            const dayStart = todayStart - i * DAY_MS;
            daily.push({
              label: dayLabel(dayStart),
              count: dayBucket.get(dayStart) ?? 0,
            });
          }

          const categoryMap = new Map(categories.map((c) => [c.id, c]));
          const byCategory: CategoryStat[] = Array.from(categoryMap.values())
            .map((c) => ({
              id: c.id,
              name: c.name,
              color: c.color,
              count: categoryCounts.get(c.id) ?? 0,
            }))
            .filter((c) => c.count > 0)
            .sort((a, b) => b.count - a.count);

          const priorityOrder = ['high', 'medium', 'low', 'none'];
          const byPriority: PriorityStat[] = priorityOrder
            .map((p) => ({
              priority: p,
              label: PRIORITY_LABELS[p],
              count: priorityCounts.get(p) ?? 0,
            }))
            .filter((p) => p.count > 0);

          let streak = 0;
          const todayCount = dayBucket.get(todayStart) ?? 0;
          let cursor = todayCount > 0 ? todayStart : todayStart - DAY_MS;
          while ((dayBucket.get(cursor) ?? 0) > 0 && streak < 365) {
            streak++;
            cursor -= DAY_MS;
          }

          if (mounted) {
            setStats({
              loading: false,
              totalCompleted,
              completedLast7,
              completedLast30,
              activeCount,
              overdueCount,
              completionRate: totalCompleted > 0
                ? Math.round((totalCompleted / (totalCompleted + activeCount)) * 100)
                : 0,
              daily,
              byCategory,
              byPriority,
              currentStreak: streak,
            });
          }
        })
        .catch(() => {
          if (mounted) setStats((s) => ({ ...s, loading: false }));
        });
    };

    compute();

    const subscription = collections.tasks.query().observe().subscribe({
      next: () => {
        compute();
      },
      error: () => {},
    });

    return () => {
      mounted = false;
      subscription.unsubscribe();
    };
  }, [collections, isReady]);

  return stats;
}