import { useState, useEffect, useCallback } from "react";
import {
  type ProjectParty,
  type AssignPartyData,
  type PartyType,
  getProjectParties,
  assignPartyToProject,
  deletePartyAssignment,
  getVendorsForDropdown,
  getContractorsForDropdown,
  getConsultantsForDropdown,
} from "../../services/projectPartyService";
import { type Vendor } from "../../services/vendorService";
import { type Contractor } from "../../services/contractorService";
import { type Consultant } from "../../services/consultantService";

interface UseProjectPartyState {
  projectParties: ProjectParty[];
  loading: boolean;
  error: string | null;
  availableVendors: Vendor[];
  availableContractors: Contractor[];
  availableConsultants: Consultant[];
  partiesLoading: boolean;
}

interface UseProjectPartyActions {
  refreshParties: (partyType?: PartyType) => Promise<void>;
  refreshPartiesByType: (partyType: PartyType) => Promise<void>;
  assignParty: (data: AssignPartyData) => Promise<boolean>;
  removeParty: (partyId: string, partyType: PartyType) => Promise<boolean>;
  loadAvailableParties: () => Promise<void>;
  getPartiesByType: (partyType: PartyType) => ProjectParty[];
}

const INITIAL_STATE: UseProjectPartyState = {
  projectParties: [],
  loading: false,
  error: null,
  availableVendors: [],
  availableContractors: [],
  availableConsultants: [],
  partiesLoading: false,
};

function useProjectParty(projectId: string) {
  const [state, setState] = useState<UseProjectPartyState>(INITIAL_STATE);

  // Fetch project parties
  const refreshParties = useCallback(
    async (partyType?: PartyType) => {
      if (!projectId) return;

      setState((prev) => ({ ...prev, loading: true, error: null }));

      try {
        const result = await getProjectParties(projectId, partyType);

        if (result?.data?.success && result.data.data) {
          setState((prev) => ({
            ...prev,
            projectParties: result.data.data ?? [],
            loading: false,
            error: null,
          }));
        } else {
          setState((prev) => ({
            ...prev,
            projectParties: [],
            loading: false,
            error: result?.data?.message || "Failed to fetch project parties",
          }));
        }
      } catch (error) {
        setState((prev) => ({
          ...prev,
          projectParties: [],
          loading: false,
          error: "Failed to fetch project parties",
        }));
      }
    },
    [projectId]
  );

  // Load available parties for dropdown
  const loadAvailableParties = useCallback(async () => {
    setState((prev) => ({ ...prev, partiesLoading: true }));

    try {
      const [vendorsResult, contractorsResult, consultantsResult] =
        await Promise.all([
          getVendorsForDropdown(),
          getContractorsForDropdown(),
          getConsultantsForDropdown(),
        ]);

      setState((prev) => ({
        ...prev,
        availableVendors: vendorsResult?.data?.success
          ? vendorsResult.data.data.data ?? []
          : [],
        availableContractors: contractorsResult?.data?.success
          ? contractorsResult.data.data.data ?? []
          : [],
        availableConsultants: consultantsResult?.data?.success
          ? consultantsResult.data.data.data ?? []
          : [],
        partiesLoading: false,
      }));
    } catch (error) {
      setState((prev) => ({
        ...prev,
        availableVendors: [],
        availableContractors: [],
        availableConsultants: [],
        partiesLoading: false,
      }));
    }
  }, []);

  // Refresh parties by specific type
  const refreshPartiesByType = useCallback(
    async (partyType: PartyType) => {
      if (!projectId) return;

      setState((prev) => ({ ...prev, loading: true, error: null }));

      try {
        const result = await getProjectParties(projectId, partyType);

        if (result?.data?.success && result.data.data) {
          const newParties = result.data.data ?? [];

          setState((prev) => {
            // Filter out existing parties of this type and add new ones
            const filteredExisting = prev.projectParties.filter(
              (p) => p.party_type !== partyType
            );
            return {
              ...prev,
              projectParties: [...filteredExisting, ...newParties],
              loading: false,
              error: null,
            };
          });
        } else {
          setState((prev) => ({
            ...prev,
            loading: false,
            error:
              result?.data?.message ||
              `Failed to fetch ${partyType.toLowerCase()}s`,
          }));
        }
      } catch (error) {
        setState((prev) => ({
          ...prev,
          loading: false,
          error: `Failed to fetch ${partyType.toLowerCase()}s`,
        }));
      }
    },
    [projectId]
  );

  // Auto-fetch when projectId changes - load available parties only
  useEffect(() => {
    if (projectId) {
      loadAvailableParties();
    }
  }, [projectId, loadAvailableParties]);

  // Assign party to project
  const assignParty = useCallback(
    async (data: AssignPartyData): Promise<boolean> => {
      if (!projectId) return false;

      try {
        const result = await assignPartyToProject(data);
        if (result?.data?.success) {
          await refreshParties();
          return true;
        }
        return false;
      } catch (error) {
        return false;
      }
    },
    [projectId, refreshParties]
  );

  // Remove party from project
  const removeParty = useCallback(
    async (partyId: string, partyType: PartyType): Promise<boolean> => {
      if (!projectId) return false;

      try {
        const result = await deletePartyAssignment(
          projectId,
          partyId,
          partyType
        );
        if (result?.data?.success) {
          await refreshParties();
          return true;
        }
        return false;
      } catch (error) {
        return false;
      }
    },
    [projectId, refreshParties]
  );

  // Get parties by type
  const getPartiesByType = useCallback(
    (partyType: PartyType): ProjectParty[] => {
      return state.projectParties.filter(
        (party) => party.party_type === partyType
      );
    },
    [state.projectParties]
  );

  const actions: UseProjectPartyActions = {
    refreshParties,
    refreshPartiesByType,
    assignParty,
    removeParty,
    loadAvailableParties,
    getPartiesByType,
  };

  return {
    ...state,
    ...actions,
  };
}

export default useProjectParty;
