import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { map } from 'rxjs/operators';
import { database, collections } from '../database';
import { runSync, watchForUpdates, stopWatchingForUpdates } from '../database/sync';
import { getAuthToken } from '../services/auth';
import { DEFAULT_CATEGORIES } from '../constants';
import Category from '../models/Category';
import RepeatProfile from '../models/RepeatProfile';

interface DatabaseContextType {
  database: typeof database;
  collections: typeof collections;
  isReady: boolean;
  initializeDatabase: () => Promise<void>;
}

const DatabaseContext = createContext<DatabaseContextType | null>(null);

export function DatabaseProvider({ children }: { children: ReactNode }) {
  const [isReady, setIsReady] = useState(false);

  const initializeDatabase = async () => {
    try {
      const existingCategories = await collections.categories.query().fetch();
      
      if (existingCategories.length === 0) {
        await database.write(async () => {
          for (const cat of DEFAULT_CATEGORIES) {
            await collections.categories.create((c) => {
              c.name = cat.name;
              c.color = cat.color;
              c.order = cat.order;
              c.createdAt = new Date();
              c.updatedAt = new Date();
            });
          }
        });
      }
      
      setIsReady(true);

      const token = await getAuthToken();
      if (token) {
        runSync()
          .catch(() => {})
          .finally(() => {
            watchForUpdates();
          });
      } else {
        stopWatchingForUpdates();
      }
    } catch (error) {
      console.error('Failed to initialize database:', error);
      setIsReady(true);
    }
  };

  useEffect(() => {
    initializeDatabase();
    return () => {
      stopWatchingForUpdates();
    };
  }, []);

  return (
    <DatabaseContext.Provider value={{ database, collections, isReady, initializeDatabase }}>
      {children}
    </DatabaseContext.Provider>
  );
}

export function useDatabase() {
  const context = useContext(DatabaseContext);
  if (!context) {
    throw new Error('useDatabase must be used within a DatabaseProvider');
  }
  return context;
}

export function useCategories(): Category[] {
  const { collections } = useDatabase();
  const [categories, setCategories] = useState<Category[]>([]);

  useEffect(() => {
    let mounted = true;
    const subscription = collections.categories
      .query()
      .observeWithColumns(['name', 'color', 'order'])
      .pipe(map((cats) => [...cats].sort((a, b) => a.order - b.order)))
      .subscribe({
        next: (cats) => {
          if (mounted) setCategories(cats);
        },
        error: () => {},
      });

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

  return categories;
}

export function useCategory(categoryId: string) {
  const { collections } = useDatabase();
  return collections.categories.find(categoryId);
}

export function useRepeatProfiles(): RepeatProfile[] {
  const { collections } = useDatabase();
  const [profiles, setProfiles] = useState<RepeatProfile[]>([]);

  useEffect(() => {
    let mounted = true;
    const subscription = collections.repeatProfiles
      .query()
      .observeWithColumns(['name', 'repeat', 'repeat_interval', 'repeat_days'])
      .pipe(map((rows) => [...rows].sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime())))
      .subscribe({
        next: (rows) => {
          if (mounted) setProfiles(rows);
        },
        error: () => {},
      });

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

  return profiles;
}