import { create } from 'zustand';
import { v4 as uuidv4 } from 'uuid';
import { db } from '@/db/schema.ts';
import { useSitesStore } from '@/store/sites.ts';
import { useCoverageStore } from '@/store/coverage.ts';
import type { Site, CoverageSettings } from '@/types/index.ts';

export interface Project {
  id: string;
  name: string;
  description?: string;
  sites: Site[];
  coverageSettings: CoverageSettings;
  createdAt: number;
  updatedAt: number;
}

interface ProjectsState {
  projects: Project[];
  currentProjectId: string | null;

  loadProjects: () => Promise<void>;
  saveProject: (name: string, description?: string) => Promise<void>;
  loadProject: (id: string) => Promise<Project | null>;
  deleteProject: (id: string) => Promise<void>;
}

export const useProjectsStore = create<ProjectsState>((set, get) => ({
  projects: [],
  currentProjectId: null,

  loadProjects: async () => {
    const dbProjects = await db.projects.orderBy('updatedAt').reverse().toArray();
    const projects: Project[] = dbProjects.map((p) => JSON.parse(p.data));
    set({ projects });
  },

  saveProject: async (name: string, description?: string) => {
    const sites = useSitesStore.getState().sites;
    const coverageSettings = useCoverageStore.getState().settings;
    const now = Date.now();

    // Check if updating existing project with same name
    const existing = get().projects.find((p) => p.name === name);
    const id = existing?.id ?? uuidv4();

    const project: Project = {
      id,
      name,
      description,
      sites,
      coverageSettings,
      createdAt: existing?.createdAt ?? now,
      updatedAt: now,
    };

    await db.projects.put({
      id,
      name,
      data: JSON.stringify(project),
      createdAt: project.createdAt,
      updatedAt: now,
    });

    set({ currentProjectId: id });
    await get().loadProjects();
  },

  loadProject: async (id: string) => {
    const dbProject = await db.projects.get(id);
    if (!dbProject) return null;

    const project: Project = JSON.parse(dbProject.data);

    // Restore sites: clear existing and add project sites
    const sitesStore = useSitesStore.getState();
    // Clear all existing sites from DB
    const currentSites = sitesStore.sites;
    for (const site of currentSites) {
      await sitesStore.deleteSite(site.id);
    }

    // Re-add project sites
    for (const site of project.sites) {
      await db.sites.put({
        id: site.id,
        data: JSON.stringify(site),
        createdAt: new Date(site.createdAt).getTime(),
        updatedAt: new Date(site.updatedAt).getTime(),
      });
    }
    await sitesStore.loadSites();

    // Restore coverage settings
    useCoverageStore.getState().updateSettings(project.coverageSettings);

    // Clear any existing coverage result (outdated for loaded project)
    useCoverageStore.getState().setResult(null);

    set({ currentProjectId: id });
    return project;
  },

  deleteProject: async (id: string) => {
    await db.projects.delete(id);
    const { currentProjectId } = get();
    if (currentProjectId === id) {
      set({ currentProjectId: null });
    }
    await get().loadProjects();
  },
}));
