import { useMutation, useQueryClient } from '@tanstack/react-query';
import { gql } from 'graphql-request';
import { fetchGraphQL, createQueryKey } from '../client';
import type { Company, CompanyRole, UserCompanyAccess } from '@/types/accounting';

// GraphQL Mutations - using gql tag for proper parsing with graphql-request v7
const CREATE_COMPANY_MUTATION = gql`
  mutation CreateCompany($input: CreateCompanyInput!) {
    createCompany(input: $input) {
      id
      name
      cvr
      country
      currency
      fiscalYearStartMonth
    }
  }
`;

const UPDATE_COMPANY_MUTATION = gql`
  mutation UpdateCompany($id: ID!, $input: UpdateCompanyInput!) {
    updateCompany(id: $id, input: $input) {
      id
      name
      cvr
      address
      city
      postalCode
      country
      currency
    }
  }
`;

const GRANT_USER_ACCESS_MUTATION = gql`
  mutation GrantUserAccess($input: GrantUserAccessInput!) {
    grantUserAccess(input: $input) {
      id
      userId
      companyId
      role
      grantedBy
      grantedAt
      isActive
    }
  }
`;

const CHANGE_USER_ROLE_MUTATION = gql`
  mutation ChangeUserRole($input: ChangeUserRoleInput!) {
    changeUserRole(input: $input) {
      id
      userId
      companyId
      role
    }
  }
`;

const REVOKE_USER_ACCESS_MUTATION = gql`
  mutation RevokeUserAccess($input: RevokeUserAccessInput!) {
    revokeUserAccess(input: $input) {
      id
      userId
      companyId
      isActive
    }
  }
`;

const UPDATE_COMPANY_BANK_DETAILS_MUTATION = gql`
  mutation UpdateCompanyBankDetails($id: ID!, $input: UpdateCompanyBankDetailsInput!) {
    updateCompanyBankDetails(id: $id, input: $input) {
      id
      name
      bankName
      bankRegNo
      bankAccountNo
      bankIban
      bankBic
    }
  }
`;

// Input types
interface CreateCompanyInput {
  name: string;
  cvr?: string;
  country?: string;
  currency?: string;
  fiscalYearStartMonth?: number;
  vatRegistered?: boolean;
  vatPeriodFrequency?: 'MONTHLY' | 'QUARTERLY' | 'HALFYEARLY';
}

interface UpdateCompanyInput {
  name?: string;
  cvr?: string;
  address?: string;
  city?: string;
  postalCode?: string;
}

interface GrantUserAccessInput {
  userId: string;
  companyId: string;
  role: CompanyRole;
}

interface ChangeUserRoleInput {
  userId: string;
  companyId: string;
  newRole: CompanyRole;
}

interface RevokeUserAccessInput {
  userId: string;
  companyId: string;
}

interface UpdateCompanyBankDetailsInput {
  bankName?: string;
  bankRegNo?: string;
  bankAccountNo?: string;
  bankIban?: string;
  bankBic?: string;
}

// Response types
interface CreateCompanyResponse {
  createCompany: Company;
}

interface UpdateCompanyResponse {
  updateCompany: Company;
}

interface GrantUserAccessResponse {
  grantUserAccess: UserCompanyAccess;
}

interface ChangeUserRoleResponse {
  changeUserRole: UserCompanyAccess;
}

interface RevokeUserAccessResponse {
  revokeUserAccess: UserCompanyAccess;
}

interface UpdateCompanyBankDetailsResponse {
  updateCompanyBankDetails: Company;
}

/**
 * Hook to create a new company
 */
export function useCreateCompany() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: CreateCompanyInput) => {
      const data = await fetchGraphQL<CreateCompanyResponse>(CREATE_COMPANY_MUTATION, { input });
      return data.createCompany;
    },
    onSuccess: () => {
      // Invalidate myCompanies to refetch the list
      queryClient.invalidateQueries({ queryKey: createQueryKey('myCompanies') });
    },
  });
}

/**
 * Hook to update a company
 */
export function useUpdateCompany() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({ id, input }: { id: string; input: UpdateCompanyInput }) => {
      const data = await fetchGraphQL<UpdateCompanyResponse>(UPDATE_COMPANY_MUTATION, { id, input });
      return data.updateCompany;
    },
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: createQueryKey('company', { id: variables.id }) });
      queryClient.invalidateQueries({ queryKey: createQueryKey('myCompanies') });
    },
  });
}

/**
 * Hook to grant a user access to a company
 */
export function useGrantUserAccess() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: GrantUserAccessInput) => {
      const data = await fetchGraphQL<GrantUserAccessResponse>(GRANT_USER_ACCESS_MUTATION, { input });
      return data.grantUserAccess;
    },
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: createQueryKey('companyUsers', { companyId: variables.companyId }) });
    },
  });
}

/**
 * Hook to change a user's role
 */
export function useChangeUserRole() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: ChangeUserRoleInput) => {
      const data = await fetchGraphQL<ChangeUserRoleResponse>(CHANGE_USER_ROLE_MUTATION, { input });
      return data.changeUserRole;
    },
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: createQueryKey('companyUsers', { companyId: variables.companyId }) });
    },
  });
}

/**
 * Hook to revoke a user's access
 */
export function useRevokeUserAccess() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: RevokeUserAccessInput) => {
      const data = await fetchGraphQL<RevokeUserAccessResponse>(REVOKE_USER_ACCESS_MUTATION, { input });
      return data.revokeUserAccess;
    },
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: createQueryKey('companyUsers', { companyId: variables.companyId }) });
    },
  });
}

/**
 * Hook to update company bank details for invoices
 */
export function useUpdateCompanyBankDetails() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({ id, input }: { id: string; input: UpdateCompanyBankDetailsInput }) => {
      const data = await fetchGraphQL<UpdateCompanyBankDetailsResponse>(UPDATE_COMPANY_BANK_DETAILS_MUTATION, { id, input });
      return data.updateCompanyBankDetails;
    },
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: createQueryKey('company', { id: variables.id }) });
      queryClient.invalidateQueries({ queryKey: createQueryKey('myCompanies') });
    },
  });
}
