import { useMutation, useQueryClient } from '@tanstack/react-query';
import { gql } from 'graphql-request';
import { fetchGraphQL, createQueryKey } from '../client';
import type { Order } from '@/types/order';
import type { Invoice } from '../queries/invoiceQueries';

// GraphQL Mutations
const CREATE_ORDER_MUTATION = gql`
  mutation CreateOrder($input: CreateOrderInput!) {
    createOrder(input: $input) {
      id
      companyId
      fiscalYearId
      customerId
      customerName
      customerNumber
      orderNumber
      orderDate
      expectedDeliveryDate
      status
      amountExVat
      amountVat
      amountTotal
      uninvoicedAmount
      currency
      notes
      reference
      createdBy
      createdAt
      updatedAt
      lines {
        lineNumber
        productId
        description
        quantity
        unit
        unitPrice
        discountPercent
        vatCode
        accountId
        amountExVat
        amountVat
        amountTotal
        isInvoiced
      }
    }
  }
`;

const ADD_ORDER_LINE_MUTATION = gql`
  mutation AddOrderLine($input: AddOrderLineInput!) {
    addOrderLine(input: $input) {
      id
      companyId
      customerId
      amountExVat
      amountVat
      amountTotal
      updatedAt
      lines {
        lineNumber
        productId
        description
        quantity
        unit
        unitPrice
        discountPercent
        vatCode
        accountId
        amountExVat
        amountVat
        amountTotal
        isInvoiced
      }
    }
  }
`;

const UPDATE_ORDER_LINE_MUTATION = gql`
  mutation UpdateOrderLine($input: UpdateOrderLineInput!) {
    updateOrderLine(input: $input) {
      id
      companyId
      customerId
      amountExVat
      amountVat
      amountTotal
      updatedAt
      lines {
        lineNumber
        productId
        description
        quantity
        unit
        unitPrice
        discountPercent
        vatCode
        accountId
        amountExVat
        amountVat
        amountTotal
        isInvoiced
      }
    }
  }
`;

const REMOVE_ORDER_LINE_MUTATION = gql`
  mutation RemoveOrderLine($input: RemoveOrderLineInput!) {
    removeOrderLine(input: $input) {
      id
      companyId
      customerId
      amountExVat
      amountVat
      amountTotal
      updatedAt
      lines {
        lineNumber
        productId
        description
        quantity
        unit
        unitPrice
        discountPercent
        vatCode
        accountId
        amountExVat
        amountVat
        amountTotal
        isInvoiced
      }
    }
  }
`;

const CONFIRM_ORDER_MUTATION = gql`
  mutation ConfirmOrder($orderId: ID!) {
    confirmOrder(orderId: $orderId) {
      id
      companyId
      customerId
      status
      confirmedAt
      confirmedBy
      updatedAt
    }
  }
`;

const INVOICE_ORDER_LINES_MUTATION = gql`
  mutation InvoiceOrderLines($input: InvoiceOrderLinesInput!) {
    invoiceOrderLines(input: $input) {
      id
      companyId
      invoiceNumber
      status
      amountTotal
    }
  }
`;

const CANCEL_ORDER_MUTATION = gql`
  mutation CancelOrder($input: CancelOrderInput!) {
    cancelOrder(input: $input) {
      id
      companyId
      customerId
      status
      cancelledAt
      cancelledReason
      cancelledBy
      updatedAt
    }
  }
`;

// Input types
export interface CreateOrderInput {
  companyId: string;
  fiscalYearId?: string;
  customerId: string;
  orderDate?: string;
  expectedDeliveryDate?: string;
  notes?: string;
  reference?: string;
}

export interface AddOrderLineInput {
  orderId: string;
  productId?: string;
  description: string;
  quantity: number;
  unitPrice: number;
  unit?: string;
  discountPercent?: number;
  vatCode: string;
  accountId?: string;
}

export interface UpdateOrderLineInput {
  orderId: string;
  lineNumber: number;
  description?: string;
  quantity?: number;
  unitPrice?: number;
  unit?: string;
  discountPercent?: number;
  vatCode?: string;
  accountId?: string;
}

export interface RemoveOrderLineInput {
  orderId: string;
  lineNumber: number;
}


export interface InvoiceOrderLinesInput {
  orderId: string;
  lineNumbers: number[];
  invoiceDate?: string;
  dueDate?: string;
}

export interface CancelOrderInput {
  orderId: string;
  reason: string;
}

// Response types
interface CreateOrderResponse {
  createOrder: Order;
}

interface AddOrderLineResponse {
  addOrderLine: Order;
}

interface UpdateOrderLineResponse {
  updateOrderLine: Order;
}

interface RemoveOrderLineResponse {
  removeOrderLine: Order;
}

interface ConfirmOrderResponse {
  confirmOrder: Order;
}

interface InvoiceOrderLinesResponse {
  invoiceOrderLines: Invoice;
}

interface CancelOrderResponse {
  cancelOrder: Order;
}

/**
 * Hook to create a new order (draft).
 */
export function useCreateOrder() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: CreateOrderInput) => {
      const data = await fetchGraphQL<CreateOrderResponse>(CREATE_ORDER_MUTATION, { input });
      return data.createOrder;
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({
        queryKey: createQueryKey('orders', { companyId: data.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('ordersByCustomer', { customerId: data.customerId }),
      });
    },
  });
}

/**
 * Hook to add a line to an order.
 */
export function useAddOrderLine() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: AddOrderLineInput) => {
      const data = await fetchGraphQL<AddOrderLineResponse>(ADD_ORDER_LINE_MUTATION, { input });
      return data.addOrderLine;
    },
    onSuccess: (data) => {
      queryClient.setQueryData(createQueryKey('order', { id: data.id }), data);
      queryClient.invalidateQueries({
        queryKey: createQueryKey('orders', { companyId: data.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('ordersByCustomer', { customerId: data.customerId }),
      });
    },
  });
}

/**
 * Hook to update an order line.
 */
export function useUpdateOrderLine() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: UpdateOrderLineInput) => {
      const data = await fetchGraphQL<UpdateOrderLineResponse>(UPDATE_ORDER_LINE_MUTATION, { input });
      return data.updateOrderLine;
    },
    onSuccess: (data) => {
      queryClient.setQueryData(createQueryKey('order', { id: data.id }), data);
      queryClient.invalidateQueries({
        queryKey: createQueryKey('orders', { companyId: data.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('ordersByCustomer', { customerId: data.customerId }),
      });
    },
  });
}

/**
 * Hook to remove an order line.
 */
export function useRemoveOrderLine() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: RemoveOrderLineInput) => {
      const data = await fetchGraphQL<RemoveOrderLineResponse>(REMOVE_ORDER_LINE_MUTATION, { input });
      return data.removeOrderLine;
    },
    onSuccess: (data) => {
      queryClient.setQueryData(createQueryKey('order', { id: data.id }), data);
      queryClient.invalidateQueries({
        queryKey: createQueryKey('orders', { companyId: data.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('ordersByCustomer', { customerId: data.customerId }),
      });
    },
  });
}

/**
 * Hook to confirm an order (draft -> confirmed).
 */
export function useConfirmOrder() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (orderId: string) => {
      const data = await fetchGraphQL<ConfirmOrderResponse>(CONFIRM_ORDER_MUTATION, { orderId });
      return data.confirmOrder;
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({
        queryKey: createQueryKey('order', { id: data.id }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('orders', { companyId: data.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('confirmedOrders', { companyId: data.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('ordersByCustomer', { customerId: data.customerId }),
      });
    },
  });
}

/**
 * Hook to create an invoice from order lines.
 * Returns the created invoice. Order queries are invalidated to refresh order status.
 */
export function useConvertOrderToInvoice() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: InvoiceOrderLinesInput) => {
      const data = await fetchGraphQL<InvoiceOrderLinesResponse>(INVOICE_ORDER_LINES_MUTATION, { input });
      return data.invoiceOrderLines;
    },
    onSuccess: (invoice, variables) => {
      // Invalidate order queries
      queryClient.invalidateQueries({
        queryKey: createQueryKey('order', { id: variables.orderId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('orders', { companyId: invoice.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('confirmedOrders', { companyId: invoice.companyId }),
      });
      queryClient.invalidateQueries({
        predicate: (query) => query.queryKey[0] === 'ordersByCustomer',
      });

      // Invalidate invoice queries
      queryClient.invalidateQueries({
        queryKey: createQueryKey('invoices', { companyId: invoice.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('invoice', { id: invoice.id }),
      });
    },
  });
}

/**
 * Hook to cancel an order.
 */
export function useCancelOrder() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: CancelOrderInput) => {
      const data = await fetchGraphQL<CancelOrderResponse>(CANCEL_ORDER_MUTATION, { input });
      return data.cancelOrder;
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({
        queryKey: createQueryKey('order', { id: data.id }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('orders', { companyId: data.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('confirmedOrders', { companyId: data.companyId }),
      });
      queryClient.invalidateQueries({
        queryKey: createQueryKey('ordersByCustomer', { customerId: data.customerId }),
      });
    },
  });
}
