"use client";

// ============================================================================
// Workspace Provider
// ============================================================================

import React, {
  createContext,
  useContext,
  useState,
  useEffect,
  useCallback,
} from "react";
import { useParams, useRouter, usePathname } from "next/navigation";
import { workspacesApi, projectsApi, membersApi, authApi } from "@/lib/api";
import type {
  Workspace,
  Project,
  Permission,
  PermissionKey,
} from "@/lib/types/api";
import { STORAGE_KEYS } from "@/lib/utils/constants";
import { isDemoWorkspace, demoApi, demoWorkspace, demoProjects, DEMO_WORKSPACE_ID } from "@/lib/demo";
import { useAuth } from "@/components/auth/auth-provider";

// ============================================================================
// Types
// ============================================================================

interface WorkspaceContextType {
  // Workspaces
  workspaces: Workspace[];
  currentWorkspace: Workspace | null;
  setCurrentWorkspace: (workspace: Workspace) => void;

  // Projects (Target Channels)
  projects: Project[];
  selectedProjects: Project[];
  currentProject: Project | null; // First selected or null (for backward compatibility)
  setSelectedProjects: (projects: Project[]) => void;
  toggleProject: (project: Project) => void;
  selectAllProjects: () => void;
  clearProjectSelection: () => void;
  
  // Helper for API filtering
  // Returns project_id only if single project selected, undefined otherwise
  getProjectFilterId: () => string | undefined;
  // Returns true if all projects are selected
  allProjectsSelected: boolean;

  // Demo mode
  isDemoMode: boolean;

  // Permissions
  permissions: Permission[];
  hasPermission: (key: PermissionKey, projectId?: string) => boolean;
  isAdmin: boolean;

  // Loading states
  isLoading: boolean;
  isLoadingProjects: boolean;
  error: string | null;

  // Actions
  refreshWorkspaces: () => Promise<Workspace[]>;
  refreshProjects: () => Promise<void>;
  createWorkspace: (name: string) => Promise<Workspace>;
}

const WorkspaceContext = createContext<WorkspaceContextType | undefined>(
  undefined
);

// ============================================================================
// Hook
// ============================================================================

export const useWorkspace = () => {
  const context = useContext(WorkspaceContext);
  if (!context) {
    throw new Error("useWorkspace must be used within WorkspaceProvider");
  }
  return context;
};

// ============================================================================
// Provider
// ============================================================================

interface WorkspaceProviderProps {
  children: React.ReactNode;
}

export const WorkspaceProvider: React.FC<WorkspaceProviderProps> = ({
  children,
}) => {
  const params = useParams();
  const router = useRouter();
  const pathname = usePathname();
  const { user } = useAuth();

  // State
  const [workspaces, setWorkspaces] = useState<Workspace[]>([]);
  const [currentWorkspace, setCurrentWorkspaceState] = useState<Workspace | null>(null);
  const [projects, setProjects] = useState<Project[]>([]);
  const [selectedProjects, setSelectedProjectsState] = useState<Project[]>([]);
  const [permissions, setPermissions] = useState<Permission[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [isLoadingProjects, setIsLoadingProjects] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Get workspaceId from URL params
  const workspaceIdFromUrl = params?.workspaceId as string | undefined;

  // Check if demo mode
  const isDemoMode = isDemoWorkspace(workspaceIdFromUrl);

  // Current project (first selected for backward compatibility)
  const currentProject = selectedProjects.length > 0 ? selectedProjects[0] : null;

  // Check if all projects are selected
  const allProjectsSelected = 
    projects.length > 0 && selectedProjects.length === projects.length;

  // Get project_id for API filtering
  // Returns undefined if multiple projects selected (to get workspace-wide data)
  const getProjectFilterId = useCallback(() => {
    if (selectedProjects.length === 1) {
      return selectedProjects[0].id;
    }
    // Multiple projects selected - return undefined to get all data
    return undefined;
  }, [selectedProjects]);

  // ============================================================================
  // Permission Helpers
  // ============================================================================

  const isAdmin = permissions.some((p) => p.key === "admin_full");

  const hasPermission = useCallback(
    (key: PermissionKey, projectId?: string): boolean => {
      // Admin has all permissions
      if (isAdmin) return true;

      // Find permission by key
      const permission = permissions.find((p) => p.key === key);
      if (!permission) return false;

      // If no scopes defined, permission applies globally
      if (!permission.scopes || permission.scopes.length === 0) return true;

      // If projectId provided, check if it's in scopes
      if (projectId) {
        return permission.scopes.some(
          (s) => s.type === "project" && s.id === projectId
        );
      }

      // Permission exists but is scoped - need projectId to verify
      return true;
    },
    [permissions, isAdmin]
  );

  // ============================================================================
  // Load Workspaces
  // ============================================================================

  const loadWorkspaces = useCallback(async () => {
    try {
      setIsLoading(true);
      setError(null);

      // Demo mode - use mock data, but also load real workspaces if user is logged in
      if (isDemoMode) {
        const allWorkspaces: Workspace[] = [demoWorkspace];
        
        // If user is logged in, also load their real workspaces
        if (user) {
          try {
            const response = await workspacesApi.list({ size: 100 });
            allWorkspaces.push(...response.items);
          } catch (err) {
            // If loading real workspaces fails, just use demo workspace
            console.warn("Failed to load real workspaces in demo mode:", err);
          }
        }
        
        setWorkspaces(allWorkspaces);
        setCurrentWorkspaceState(demoWorkspace);
        setIsLoading(false);
        return allWorkspaces;
      }

      const response = await workspacesApi.list({ size: 100 });
      setWorkspaces(response.items);

      // If we have workspaceId in URL, select that workspace
      if (workspaceIdFromUrl && response.items.length > 0) {
        const workspace = response.items.find((w) => w.id === workspaceIdFromUrl);
        if (workspace) {
          setCurrentWorkspaceState(workspace);
          localStorage.setItem(STORAGE_KEYS.SELECTED_WORKSPACE, workspace.id);
        } else {
          // Workspace from URL not found, redirect to first available
          const firstWorkspace = response.items[0];
          setCurrentWorkspaceState(firstWorkspace);
          localStorage.setItem(STORAGE_KEYS.SELECTED_WORKSPACE, firstWorkspace.id);
          // Redirect to correct workspace
          const newPath = pathname.replace(
            `/dashboard/${workspaceIdFromUrl}`,
            `/dashboard/${firstWorkspace.id}`
          );
          router.replace(newPath);
        }
      } else if (response.items.length > 0) {
        // Try to restore from localStorage or use first
        const savedId = localStorage.getItem(STORAGE_KEYS.SELECTED_WORKSPACE);
        const saved = savedId
          ? response.items.find((w) => w.id === savedId)
          : null;
        const workspace = saved || response.items[0];
        setCurrentWorkspaceState(workspace);
        localStorage.setItem(STORAGE_KEYS.SELECTED_WORKSPACE, workspace.id);
      }

      return response.items;
    } catch (err: any) {
      console.error("Failed to load workspaces:", err);
      setError(err?.error?.message || "Ошибка загрузки воркспейсов");
      return [];
    } finally {
      setIsLoading(false);
    }
  }, [workspaceIdFromUrl, pathname, router, isDemoMode, user]);

  // ============================================================================
  // Load Projects & Permissions
  // ============================================================================

  const loadProjectsAndPermissions = useCallback(async (workspaceId: string) => {
    try {
      setIsLoadingProjects(true);

      // Demo mode - use mock data
      if (isDemoMode) {
        const activeProjects = demoProjects.filter((p) => p.status === "active");
        setProjects(activeProjects);
        setPermissions([{ key: "admin_full" }]);
        setSelectedProjectsState(activeProjects.length > 0 ? [activeProjects[0]] : []);
        setIsLoadingProjects(false);
        return;
      }

      // Load projects
      const projectsResponse = await projectsApi.list(workspaceId, { size: 100 });
      const activeProjects = projectsResponse.items.filter(
        (p) => p.status === "active"
      );
      setProjects(activeProjects);

      // Load current user's permissions
      const me = await authApi.me();
      const membersResponse = await membersApi.list(workspaceId, { size: 100 });
      // Find member by user.id (not by member record id)
      const currentMember = membersResponse.items.find((m) => m.user.id === me.id);

      if (currentMember) {
        // If member found but no permissions, they're likely the creator - grant admin
        if (currentMember.permissions.length === 0) {
          setPermissions([{ key: "admin_full" }]);
        } else {
          setPermissions(currentMember.permissions);
        }
      } else {
        // User not in members list - might be creator, check if only workspace
        // Grant admin access by default for workspace creators
        if (membersResponse.items.length === 0) {
          setPermissions([{ key: "admin_full" }]);
        } else {
          setPermissions([]);
        }
      }

      // Restore selected projects from localStorage
      const savedProjectIds = localStorage.getItem(
        `${STORAGE_KEYS.SELECTED_PROJECT}_${workspaceId}`
      );
      if (savedProjectIds && activeProjects.length > 0) {
        try {
          const ids = JSON.parse(savedProjectIds) as string[];
          const savedProjects = activeProjects.filter((p) => ids.includes(p.id));
          if (savedProjects.length > 0) {
            setSelectedProjectsState(savedProjects);
          } else if (activeProjects.length > 0) {
            setSelectedProjectsState([activeProjects[0]]);
          }
        } catch {
          // Old format (single id), migrate to array
          const savedProject = activeProjects.find((p) => p.id === savedProjectIds);
          if (savedProject) {
            setSelectedProjectsState([savedProject]);
          } else if (activeProjects.length > 0) {
            setSelectedProjectsState([activeProjects[0]]);
          }
        }
      } else if (activeProjects.length > 0) {
        setSelectedProjectsState([activeProjects[0]]);
      } else {
        setSelectedProjectsState([]);
      }
    } catch (err: any) {
      console.error("Failed to load projects/permissions:", err);
    } finally {
      setIsLoadingProjects(false);
    }
  }, [isDemoMode]);

  // ============================================================================
  // Set Current Workspace
  // ============================================================================

  const setCurrentWorkspace = useCallback(
    (workspace: Workspace) => {
      setCurrentWorkspaceState(workspace);
      localStorage.setItem(STORAGE_KEYS.SELECTED_WORKSPACE, workspace.id);

      // Update URL if we're in dashboard
      if (pathname.startsWith("/dashboard/")) {
        const currentWorkspaceId = workspaceIdFromUrl;
        if (currentWorkspaceId && currentWorkspaceId !== workspace.id) {
          const newPath = pathname.replace(
            `/dashboard/${currentWorkspaceId}`,
            `/dashboard/${workspace.id}`
          );
          router.push(newPath);
        }
      } else if (pathname === "/dashboard" || pathname === "/") {
        router.push(`/dashboard/${workspace.id}`);
      }

      // Load projects for new workspace
      loadProjectsAndPermissions(workspace.id);
    },
    [pathname, router, workspaceIdFromUrl, loadProjectsAndPermissions]
  );

  // ============================================================================
  // Project Selection Methods
  // ============================================================================

  const saveSelectedProjects = useCallback(
    (selected: Project[]) => {
      if (currentWorkspace) {
        localStorage.setItem(
          `${STORAGE_KEYS.SELECTED_PROJECT}_${currentWorkspace.id}`,
          JSON.stringify(selected.map((p) => p.id))
        );
      }
    },
    [currentWorkspace]
  );

  const setSelectedProjects = useCallback(
    (selected: Project[]) => {
      setSelectedProjectsState(selected);
      saveSelectedProjects(selected);
    },
    [saveSelectedProjects]
  );

  const toggleProject = useCallback(
    (project: Project) => {
      setSelectedProjectsState((prev) => {
        const isSelected = prev.some((p) => p.id === project.id);
        let newSelection: Project[];
        
        if (isSelected) {
          // Don't allow deselecting if it's the only one
          if (prev.length <= 1) {
            return prev;
          }
          newSelection = prev.filter((p) => p.id !== project.id);
        } else {
          newSelection = [...prev, project];
        }
        
        saveSelectedProjects(newSelection);
        return newSelection;
      });
    },
    [saveSelectedProjects]
  );

  const selectAllProjects = useCallback(() => {
    setSelectedProjectsState(projects);
    saveSelectedProjects(projects);
  }, [projects, saveSelectedProjects]);

  const clearProjectSelection = useCallback(() => {
    if (projects.length > 0) {
      const firstProject = [projects[0]];
      setSelectedProjectsState(firstProject);
      saveSelectedProjects(firstProject);
    }
  }, [projects, saveSelectedProjects]);

  // ============================================================================
  // Create Workspace
  // ============================================================================

  const createWorkspace = useCallback(async (name: string): Promise<Workspace> => {
    const workspace = await workspacesApi.create({ name });
    setWorkspaces((prev) => [...prev, workspace]);
    return workspace;
  }, []);

  // ============================================================================
  // Effects
  // ============================================================================

  // Initial load
  useEffect(() => {
    loadWorkspaces();
  }, [loadWorkspaces]);

  // Load projects when workspace changes
  useEffect(() => {
    if (currentWorkspace) {
      loadProjectsAndPermissions(currentWorkspace.id);
    }
  }, [currentWorkspace?.id, loadProjectsAndPermissions]);

  // ============================================================================
  // Render
  // ============================================================================

  return (
    <WorkspaceContext.Provider
      value={{
        // Workspaces
        workspaces,
        currentWorkspace,
        setCurrentWorkspace,

        // Projects
        projects,
        selectedProjects,
        currentProject,
        setSelectedProjects,
        toggleProject,
        selectAllProjects,
        clearProjectSelection,
        getProjectFilterId,
        allProjectsSelected,

        // Demo mode
        isDemoMode,

        // Permissions
        permissions,
        hasPermission,
        isAdmin,

        // Loading states
        isLoading,
        isLoadingProjects,
        error,

        // Actions
        refreshWorkspaces: loadWorkspaces,
        refreshProjects: () =>
          currentWorkspace
            ? loadProjectsAndPermissions(currentWorkspace.id)
            : Promise.resolve(),
        createWorkspace,
      }}
    >
      {children}
    </WorkspaceContext.Provider>
  );
};
