import { useDatabase } from './useDatabase';
import { Q } from '@nozbe/watermelondb';
import { useEffect, useState, useMemo, useCallback } from 'react';
import Task from '../models/Task';
import { startOfMonth, endOfMonth } from 'date-fns';

export function useTasksInMonth(monthDate: Date) {
  const { collections } = useDatabase();
  const [tasks, setTasks] = useState<Task[]>([]);
  const [loading, setLoading] = useState(true);
  const [refreshKey, setRefreshKey] = useState(0);
  const refresh = useCallback(() => setRefreshKey((k) => k + 1), []);

  const range = useMemo(() => {
    const s = startOfMonth(monthDate);
    s.setHours(0, 0, 0, 0);
    const e = endOfMonth(monthDate);
    e.setHours(23, 59, 59, 999);
    return { start: s.getTime(), end: e.getTime() };
  }, [monthDate]);

  useEffect(() => {
    let mounted = true;
    setLoading(true);
    const subscription = collections.tasks
      .query(
        Q.where('due_date', Q.between(range.start, range.end)),
        Q.sortBy('due_date', 'asc')
      )
      .observe()
      .subscribe({
        next: (result) => {
          if (mounted) {
            setTasks(result);
            setLoading(false);
          }
        },
        error: () => {
          if (mounted) setLoading(false);
        },
      });

    return () => {
      mounted = false;
      subscription.unsubscribe();
    };
  }, [collections, range.start, range.end, refreshKey]);

  const byDay = useMemo(() => {
    const map: Record<number, Task[]> = {};
    for (const t of tasks) {
      const key = new Date(t.dueDate).getDate();
      const bucket = map[key] ?? [];
      bucket.push(t);
      map[key] = bucket;
    }
    return map;
  }, [tasks]);

  return { tasks, byDay, loading, refresh };
}

export function useTasks(categoryIds: string[] = [], showCompleted: boolean | 'all' = false, maxAheadDays?: number) {
  const { collections } = useDatabase();
  const [tasks, setTasks] = useState<Task[]>([]);
  const [loading, setLoading] = useState(true);
  const [refreshKey, setRefreshKey] = useState(0);
  const refresh = useCallback(() => setRefreshKey((k) => k + 1), []);

  const cutoff = useMemo(() => {
    if (maxAheadDays === undefined) return null;
    const d = new Date();
    d.setHours(23, 59, 59, 999);
    d.setDate(d.getDate() + maxAheadDays);
    return d.getTime();
  }, [maxAheadDays]);

  useEffect(() => {
    let mounted = true;
    const conditions: any[] = [];

    if (categoryIds.length > 0) {
      const tagConditions = categoryIds.map((id) =>
        Q.or(
          Q.where('tags', Q.like(`%,${id},%`)),
          Q.where('category_id', id)
        )
      );
      conditions.push(tagConditions.length === 1 ? tagConditions[0] : Q.or(...tagConditions));
    }

    if (showCompleted === true) {
      conditions.push(Q.where('completed', true));
    } else if (showCompleted === false) {
      conditions.push(Q.where('completed', false));
    }

    if (cutoff !== null) {
      conditions.push(Q.where('due_date', Q.lte(cutoff)));
    }

    const query = conditions.length > 0
      ? collections.tasks.query(Q.and(...conditions))
      : collections.tasks.query();

    const subscription = query
      .observe()
      .subscribe({
        next: (result) => {
          if (mounted) {
            setTasks(result);
            setLoading(false);
          }
        },
        error: () => {
          if (mounted) setLoading(false);
        },
      });

    return () => {
      mounted = false;
      subscription.unsubscribe();
    };
  }, [collections, categoryIds, showCompleted, cutoff, refreshKey]);

  return { tasks, loading, refresh };
}

export function useTasksByDate(date: Date) {
  const { collections } = useDatabase();
  const [tasks, setTasks] = useState<Task[]>([]);
  const [loading, setLoading] = useState(true);
  const [refreshKey, setRefreshKey] = useState(0);
  const refresh = useCallback(() => setRefreshKey((k) => k + 1), []);

  const startOfDay = useMemo(() => {
    const d = new Date(date);
    d.setHours(0, 0, 0, 0);
    return d;
  }, [date]);
  const endOfDay = useMemo(() => {
    const d = new Date(date);
    d.setHours(23, 59, 59, 999);
    return d;
  }, [date]);

  useEffect(() => {
    let mounted = true;
    const subscription = collections.tasks
      .query(
        Q.where('due_date', Q.between(startOfDay.getTime(), endOfDay.getTime())),
        Q.sortBy('due_date', 'asc')
      )
      .observe()
      .subscribe({
        next: (result) => {
          if (mounted) {
            setTasks(result);
            setLoading(false);
          }
        },
        error: () => {
          if (mounted) setLoading(false);
        },
      });

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

  return { tasks, loading, refresh };
}
