'use client';

import { create } from 'zustand';
import { Product } from '@ftb/shared';
import { api } from '@/lib/api';
import { shouldPersistRemoteOverview } from '@/lib/product-overview-persistence';
import { loadServerData, saveServerData, SERVER_DATA_CACHE_MS } from '@/lib/server-data';
import type { Stage, Role } from '@/lib/stage';
import type { Priority, VersionLinks } from '@/lib/derive';

interface VersionMember {
  role: Role;
  name: string;
}

interface RoleProgress {
  role: Role;
  percent: number;
  daysSpent: number;
}

interface VersionItem {
  id: string;
  name: string;
  status?: string;
  releaseDate: string | null;
  createdAt: string;
  currentStage?: Stage;
  startDate?: string | null;
  expectedReleaseDate?: string | null;
  members?: VersionMember[];
  progress?: RoleProgress[];
  priority?: Priority;
  links?: VersionLinks;
}

const MOCK_OVERVIEW: ProductOverview[] = [];
let lastOverviewFetchAt = 0;

interface ProductWithCount {
  id: string;
  name: string;
  description: string;
  createdAt: string;
  updatedAt: string;
  _count?: { requirements: number; projects: number; versions?: number };
}

interface ProductOverview extends ProductWithCount {
  projects: { id: string; name: string; description: string; createdAt: string }[];
  versions: VersionItem[];
}

interface ProductState {
  products: ProductWithCount[];
  overview: ProductOverview[];
  currentProduct: (Product & { requirements?: any[]; versions?: any[] }) | null;
  loading: boolean;
  overviewLoaded: boolean;
  error: string | null;
  fetchProducts: () => Promise<void>;
  fetchOverview: () => Promise<void>;
  fetchProduct: (id: string) => Promise<void>;
  createProduct: (data: { name: string; description?: string }) => Promise<void>;
  updateProduct: (id: string, data: { name?: string; description?: string }) => Promise<void>;
  deleteProduct: (id: string) => Promise<void>;
  reorderProducts: (ids: string[]) => Promise<void>;
  migrateAndDeleteProduct: (sourceId: string, targetId: string) => Promise<void>;
  createProject: (productId: string, data: { name: string; description?: string }) => Promise<void>;
  updateProject: (productId: string, projectId: string, data: { name?: string; description?: string }) => Promise<void>;
  createVersion: (productId: string, data: { name: string; status: string }) => Promise<void>;
  updateVersion: (productId: string, versionId: string, data: Partial<VersionItem>) => Promise<void>;
  deleteVersion: (productId: string, versionId: string) => Promise<void>;
  deleteProject: (productId: string, projectId: string) => Promise<void>;
}

export const useProductStore = create<ProductState>((set, get) => ({
  products: [],
  overview: [],
  currentProduct: null,
  loading: false,
  overviewLoaded: false,
  error: null,

  fetchProducts: async () => {
    set({ loading: true, error: null });
    try {
      const overview = await loadStoredOverview();
      const products = overview
        ? overview.map(({ projects: _projects, versions: _versions, ...product }) => product)
        : await api.get<ProductWithCount[]>('/products');
      set({ products, loading: false });
    } catch {
      set({ products: [], error: null, loading: false });
    }
  },

  fetchOverview: async () => {
    if (get().overviewLoaded && Date.now() - lastOverviewFetchAt < SERVER_DATA_CACHE_MS) return;
    const cached = await loadStoredOverview();
    if (get().overviewLoaded && Date.now() - lastOverviewFetchAt < SERVER_DATA_CACHE_MS) return;
    lastOverviewFetchAt = Date.now();
    if (cached) {
      // 有本地缓存，直接用，不再调远端覆盖（mock 模式核心数据在本地）
      set({ overview: cached, loading: false, overviewLoaded: true });
      return;
    }
    set({ loading: true, error: null });
    try {
      const overview = await api.get<ProductOverview[]>('/products/overview');
      set({ overview, loading: false, overviewLoaded: true });
      if (shouldPersistRemoteOverview(overview)) {
        void saveStoredOverview(overview).catch(() => {});
      }
    } catch {
      set({ overview: MOCK_OVERVIEW, error: null, loading: false, overviewLoaded: true });
    }
  },

  fetchProduct: async (id) => {
    set({ loading: true, error: null });
    try {
      const overview = await loadStoredOverview();
      const found = overview?.find((p) => p.id === id);
      if (found) {
        set({ currentProduct: found as any, loading: false });
        return;
      }
      const product = await api.get<Product>(`/products/${id}`);
      set({ currentProduct: product, loading: false });
    } catch {
      const found = get().overview.find((p) => p.id === id);
      if (found) {
        set({ currentProduct: found as any, loading: false });
      } else {
        set({ error: '产品不存在', loading: false });
      }
    }
  },

  createProduct: async (data) => {
    const newProduct: ProductOverview = {
      id: `local-${Date.now()}`,
      name: data.name || '',
      description: data.description || '',
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
      projects: [],
      versions: [],
      _count: { requirements: 0, projects: 0, versions: 0 },
    };
    const updated = [newProduct, ...get().overview];
    set({ overview: updated, overviewLoaded: true });
    await saveStoredOverview(updated);
  },

  updateProduct: async (id, data) => {
    const updated = get().overview.map((p) =>
      p.id === id ? { ...p, ...data, updatedAt: new Date().toISOString() } : p,
    );
    const currentProduct = get().currentProduct;
    set({
      overview: updated,
      overviewLoaded: true,
      currentProduct:
        currentProduct?.id === id ? ({ ...currentProduct, ...data } as any) : currentProduct,
    });
    await saveStoredOverview(updated);
  },

  deleteProduct: async (id) => {
    const updated = get().overview.filter((p) => p.id !== id);
    set({
      products: get().products.filter((p) => p.id !== id),
      overview: updated,
      overviewLoaded: true,
      currentProduct: get().currentProduct?.id === id ? null : get().currentProduct,
    });
    await saveStoredOverview(updated);
  },

  reorderProducts: async (ids) => {
    const map = new Map(get().overview.map((p) => [p.id, p]));
    const reordered = ids.map((id) => map.get(id)).filter(Boolean) as ProductOverview[];
    set({ overview: reordered, overviewLoaded: true });
    await saveStoredOverview(reordered);
  },

  migrateAndDeleteProduct: async (sourceId, targetId) => {
    const source = get().overview.find((p) => p.id === sourceId);
    const target = get().overview.find((p) => p.id === targetId);
    if (!source || !target) return;

    const migratedTarget: ProductOverview = {
      ...target,
      projects: [...target.projects, ...source.projects],
      versions: [...target.versions, ...source.versions],
      _count: {
        requirements: (target._count?.requirements ?? 0) + (source._count?.requirements ?? 0),
        projects: (target._count?.projects ?? 0) + (source._count?.projects ?? 0),
        versions: (target._count?.versions ?? 0) + (source._count?.versions ?? 0),
      },
    };

    const updated = get().overview
      .filter((p) => p.id !== sourceId)
      .map((p) => (p.id === targetId ? migratedTarget : p));
    set({ overview: updated, overviewLoaded: true });
    await saveStoredOverview(updated);
  },

  createProject: async (productId, data) => {
    const newProject = {
      id: `proj-${Date.now()}`,
      name: data.name || '',
      description: data.description || '',
      createdAt: new Date().toISOString(),
    };
    const updated = get().overview.map((p) => {
      if (p.id !== productId) return p;
      return {
        ...p,
        projects: [...p.projects, newProject],
        _count: { ...p._count, projects: (p._count?.projects ?? 0) + 1 } as any,
      };
    });
    set({ overview: updated, overviewLoaded: true });
    await saveStoredOverview(updated);
  },

  updateProject: async (productId, projectId, data) => {
    const updated = get().overview.map((p) => {
      if (p.id !== productId) return p;
      const currentProject = p.projects.find((proj) => proj.id === projectId);
      if (!currentProject) return p;

      const nextName = data.name?.trim();
      const shouldRename = !!nextName && nextName !== currentProject.name;
      const nextProjects = p.projects.map((proj) =>
        proj.id === projectId
          ? {
              ...proj,
              ...data,
              name: nextName || proj.name,
            }
          : proj,
      );
      const nextVersions = shouldRename
        ? p.versions.map((version) => {
            if (!version.name.toLowerCase().startsWith(currentProject.name.toLowerCase())) return version;
            return {
              ...version,
              name: `${nextName}${version.name.slice(currentProject.name.length)}`,
            };
          })
        : p.versions;

      return {
        ...p,
        projects: nextProjects,
        versions: nextVersions,
      };
    });
    set({ overview: updated, overviewLoaded: true });
    await saveStoredOverview(updated);
  },

  createVersion: async (productId, data) => {
    const newVersion: VersionItem = {
      id: `ver-${Date.now()}`,
      name: data.name,
      status: data.status,
      releaseDate: null,
      createdAt: new Date().toISOString(),
      ...(data as any),
    };
    const updated = get().overview.map((p) => {
      if (p.id !== productId) return p;
      return {
        ...p,
        versions: [...p.versions, newVersion],
        _count: { ...p._count, versions: (p._count?.versions ?? 0) + 1 } as any,
      };
    });
    set({ overview: updated, overviewLoaded: true });
    await saveStoredOverview(updated);
  },

  updateVersion: async (productId, versionId, data) => {
    const updated = get().overview.map((p) => {
      if (p.id !== productId) return p;
      return {
        ...p,
        versions: p.versions.map((v) =>
          v.id === versionId ? { ...v, ...data } : v,
        ),
      };
    });
    set({ overview: updated, overviewLoaded: true });
    await saveStoredOverview(updated);
  },

  deleteVersion: async (productId, versionId) => {
    const updated = get().overview.map((p) => {
      if (p.id !== productId) return p;
      return {
        ...p,
        versions: p.versions.filter((v) => v.id !== versionId),
        _count: { ...p._count, versions: Math.max(0, (p._count?.versions ?? 0) - 1) } as any,
      };
    });
    set({ overview: updated, overviewLoaded: true });
    await saveStoredOverview(updated);
  },

  deleteProject: async (productId, projectId) => {
    const updated = get().overview.map((p) => {
      if (p.id !== productId) return p;
      return {
        ...p,
        projects: p.projects.filter((proj) => proj.id !== projectId),
        _count: { ...p._count, projects: Math.max(0, (p._count?.projects ?? 0) - 1) } as any,
      };
    });
    set({ overview: updated, overviewLoaded: true });
    await saveStoredOverview(updated);
  },
}));

async function saveStoredOverview(data: ProductOverview[]) {
  await saveServerData('products-overview', data);
}

async function loadStoredOverview(): Promise<ProductOverview[] | null> {
  try {
    return await loadServerData<ProductOverview[]>('products-overview');
  } catch {}
  return null;
}
