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

// GraphQL Queries - using gql tag for proper parsing with graphql-request v7
const MY_COMPANIES_QUERY = gql`
  query MyCompanies {
    myCompanies {
      id
      userId
      companyId
      role
      grantedAt
      isActive
      company {
        id
        name
        cvr
        country
        currency
        fiscalYearStartMonth
      }
    }
  }
`;

const COMPANY_USERS_QUERY = gql`
  query CompanyUsers($companyId: ID!) {
    companyUsers(companyId: $companyId) {
      id
      userId
      companyId
      role
      grantedBy
      grantedAt
      isActive
    }
  }
`;

const COMPANY_QUERY = gql`
  query Company($id: ID!) {
    company(id: $id) {
      id
      name
      cvr
      address
      city
      postalCode
      country
      currency
      fiscalYearStartMonth
      vatRegistered
      vatPeriodFrequency
      bankName
      bankRegNo
      bankAccountNo
      bankIban
      bankBic
    }
  }
`;

// Response types
interface MyCompaniesResponse {
  myCompanies: UserCompanyAccess[];
}

interface CompanyUsersResponse {
  companyUsers: UserCompanyAccess[];
}

interface CompanyResponse {
  company: Company | null;
}

// Normalize role from GraphQL (uppercase) to frontend (lowercase)
function normalizeRole(role: string): CompanyRole {
  return role.toLowerCase() as CompanyRole;
}

// Transform function to merge company with role
function transformToCompanyWithRole(access: UserCompanyAccess): CompanyWithRole | null {
  if (!access.company) return null;
  return {
    ...access.company,
    role: normalizeRole(access.role),
  };
}

/**
 * Hook to fetch all companies the current user has access to
 */
export function useMyCompanies(
  options?: Omit<UseQueryOptions<CompanyWithRole[], Error>, 'queryKey' | 'queryFn'>
) {
  return useQuery({
    queryKey: createQueryKey('myCompanies'),
    queryFn: async () => {
      const data = await fetchGraphQL<MyCompaniesResponse>(MY_COMPANIES_QUERY);
      return data.myCompanies
        .filter((access) => access.isActive && access.company)
        .map(transformToCompanyWithRole)
        .filter((c): c is CompanyWithRole => c !== null);
    },
    ...options,
  });
}

/**
 * Hook to fetch all users with access to a company (requires Owner role)
 */
export function useCompanyUsers(
  companyId: string | undefined,
  options?: Omit<UseQueryOptions<UserCompanyAccess[], Error>, 'queryKey' | 'queryFn'>
) {
  return useQuery({
    queryKey: createQueryKey('companyUsers', { companyId }),
    queryFn: async () => {
      if (!companyId) return [];
      const data = await fetchGraphQL<CompanyUsersResponse>(COMPANY_USERS_QUERY, { companyId });
      return data.companyUsers
        .filter((access) => access.isActive)
        .map((access) => ({
          ...access,
          role: normalizeRole(access.role),
        }));
    },
    enabled: !!companyId,
    ...options,
  });
}

/**
 * Hook to fetch a single company by ID
 */
export function useCompany(
  id: string | undefined,
  options?: Omit<UseQueryOptions<Company | null, Error>, 'queryKey' | 'queryFn'>
) {
  return useQuery({
    queryKey: createQueryKey('company', { id }),
    queryFn: async () => {
      if (!id) return null;
      const data = await fetchGraphQL<CompanyResponse>(COMPANY_QUERY, { id });
      return data.company;
    },
    enabled: !!id,
    ...options,
  });
}
