import React, { createContext, useContext, useEffect, useState } from "react";
import { supabase } from "@/integrations/supabase/client";
import { useAuth } from "@/contexts/AuthContext";

interface BoardAssociation {
  id: string;
  name: string;
}

interface BoardAssociationContextType {
  associations: BoardAssociation[];
  selectedAssociationId: string | null;
  setSelectedAssociationId: (id: string) => void;
  /** For backward compat: returns array with just the selected ID, or all if none selected */
  associationIds: string[];
  loading: boolean;
  /** Whether this board member may upload docs / bids for the selected association. */
  canUpload: boolean;
  /** Per-association upload permission map. */
  canUploadByAssociation: Record<string, boolean>;
}

const BoardAssociationContext = createContext<BoardAssociationContextType>({
  associations: [],
  selectedAssociationId: null,
  setSelectedAssociationId: () => {},
  associationIds: [],
  loading: true,
  canUpload: false,
  canUploadByAssociation: {},
});

export function BoardAssociationProvider({ children }: { children: React.ReactNode }) {
  const { user } = useAuth();
  const [associations, setAssociations] = useState<BoardAssociation[]>([]);
  const [selectedAssociationId, setSelectedAssociationId] = useState<string | null>(null);
  const [uploadByAssoc, setUploadByAssoc] = useState<Record<string, boolean>>({});
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!user) {
      setAssociations([]);
      setSelectedAssociationId(null);
      setUploadByAssoc({});
      setLoading(false);
      return;
    }

    const load = async () => {
      const email = user.email?.toLowerCase() ?? "";
      // Load board memberships by user_id OR matching email (rows whose user_id was never linked),
      // plus master-board assignments by user_id.
      const [bmByIdRes, bmByEmailRes, mbaRes] = await Promise.all([
        supabase
          .from("board_members")
          .select("association_id, associations(name), can_upload")
          .eq("user_id", user.id),
        email
          ? supabase
              .from("board_members")
              .select("association_id, associations(name), email, can_upload")
              .ilike("email", email)
          : Promise.resolve({ data: [] as any[] }),
        (supabase as any)
          .from("master_board_assignments")
          .select("association_id, associations(name)")
          .eq("user_id", user.id),
      ]);

      const merged = new Map<string, BoardAssociation>();
      [
        ...((bmByIdRes as any).data || []),
        ...((bmByEmailRes as any).data || []),
        ...((mbaRes as any).data || []),
      ].forEach((r: any) => {
        if (!r?.association_id) return;
        if (!merged.has(r.association_id)) {
          merged.set(r.association_id, {
            id: r.association_id,
            name: r.associations?.name ?? "Unknown",
          });
        }
      });
      const items = Array.from(merged.values()).sort((a, b) => a.name.localeCompare(b.name));
      setAssociations(items);

      // Per-association upload permission (board_members.can_upload). Master-board
      // assignments are elevated and always permitted.
      const uploadMap: Record<string, boolean> = {};
      for (const r of [...((bmByIdRes as any).data || []), ...((bmByEmailRes as any).data || [])]) {
        if (!r?.association_id) continue;
        uploadMap[r.association_id] = uploadMap[r.association_id] || !!r.can_upload;
      }
      for (const r of ((mbaRes as any).data || [])) {
        if (r?.association_id) uploadMap[r.association_id] = true;
      }
      setUploadByAssoc(uploadMap);

      const savedId = localStorage.getItem("board_selected_association");
      if (savedId && items.some((a) => a.id === savedId)) {
        setSelectedAssociationId(savedId);
      } else if (items.length > 0) {
        setSelectedAssociationId(items[0].id);
      }
      setLoading(false);
    };

    void load();
  }, [user]);

  const handleSelect = (id: string) => {
    setSelectedAssociationId(id);
    localStorage.setItem("board_selected_association", id);
  };

  // Filter to just the selected association
  const associationIds = selectedAssociationId ? [selectedAssociationId] : associations.map((a) => a.id);
  const canUpload = selectedAssociationId
    ? !!uploadByAssoc[selectedAssociationId]
    : Object.values(uploadByAssoc).some(Boolean);

  return (
    <BoardAssociationContext.Provider
      value={{ associations, selectedAssociationId, setSelectedAssociationId: handleSelect, associationIds, loading, canUpload, canUploadByAssociation: uploadByAssoc }}
    >
      {children}
    </BoardAssociationContext.Provider>
  );
}

export function useBoardAssociations() {
  return useContext(BoardAssociationContext);
}
