/**
 * useBilling Hook
 * 
 * Hook für die Verwaltung von Billing-Daten.
 * Bietet Zugriff auf Guthaben, Transaktionen, Statistiken und Admin-Funktionen.
 */

import { useState, useEffect, useCallback } from 'react';
import { useApiRequest } from './useApi';
import {
  fetchBalances,
  fetchBalanceForMandate,
  fetchTransactions,
  fetchStatistics,
  fetchAllowedProviders,
  fetchSettingsAdmin,
  updateSettingsAdmin,
  addCreditAdmin,
  createCheckoutSession as createCheckoutSessionApi,
  fetchAccountsAdmin,
  fetchTransactionsAdmin,
  fetchUsersForMandateAdmin,
  type BillingBalance,
  type BillingTransaction,
  type BillingSettings,
  type BillingSettingsUpdate,
  type UsageReport,
  type AccountSummary,
  type CreditAddRequest,
  type CheckoutCreateRequest,
  type MandateUserSummary,
} from '../api/billingApi';

// Re-export types
export type {
  BillingBalance,
  BillingTransaction,
  BillingSettings,
  BillingSettingsUpdate,
  UsageReport,
  AccountSummary,
  CreditAddRequest,
  MandateUserSummary,
};

export type { BillingModel, TransactionType, ReferenceType } from '../api/billingApi';

/**
 * Hook for user billing operations
 */
export function useBilling() {
  const [balances, setBalances] = useState<BillingBalance[]>([]);
  const [transactions, setTransactions] = useState<BillingTransaction[]>([]);
  const [statistics, setStatistics] = useState<UsageReport | null>(null);
  const [allowedProviders, setAllowedProviders] = useState<string[]>([]);
  const { request, isLoading: loading, error } = useApiRequest();

  // Fetch all balances for the user
  const loadBalances = useCallback(async () => {
    try {
      const data = await fetchBalances(request);
      setBalances(Array.isArray(data) ? data : []);
      return data;
    } catch (err) {
      console.error('Error loading balances:', err);
      setBalances([]);
      return [];
    }
  }, [request]);

  // Fetch balance for a specific mandate
  const loadBalanceForMandate = useCallback(async (mandateId: string) => {
    try {
      return await fetchBalanceForMandate(request, mandateId);
    } catch (err) {
      console.error('Error loading balance for mandate:', err);
      return null;
    }
  }, [request]);

  // Fetch transactions
  const loadTransactions = useCallback(async (limit: number = 50, offset: number = 0) => {
    try {
      const data = await fetchTransactions(request, limit, offset);
      setTransactions(Array.isArray(data) ? data : []);
      return data;
    } catch (err) {
      console.error('Error loading transactions:', err);
      setTransactions([]);
      return [];
    }
  }, [request]);

  // Fetch statistics
  const loadStatistics = useCallback(async (
    period: 'day' | 'month' | 'year',
    year: number,
    month?: number
  ) => {
    try {
      const data = await fetchStatistics(request, period, year, month);
      setStatistics(data);
      return data;
    } catch (err) {
      console.error('Error loading statistics:', err);
      setStatistics(null);
      return null;
    }
  }, [request]);

  // Fetch allowed providers
  const loadAllowedProviders = useCallback(async () => {
    try {
      const data = await fetchAllowedProviders(request);
      setAllowedProviders(Array.isArray(data) ? data : []);
      return data;
    } catch (err) {
      console.error('Error loading allowed providers:', err);
      setAllowedProviders([]);
      return [];
    }
  }, [request]);

  // Initial load
  useEffect(() => {
    loadBalances();
    loadAllowedProviders();
  }, []);

  return {
    balances,
    transactions,
    statistics,
    allowedProviders,
    loading,
    error,
    loadBalances,
    loadBalanceForMandate,
    loadTransactions,
    loadStatistics,
    loadAllowedProviders,
    refetch: loadBalances,
  };
}

/**
 * Hook for admin billing operations
 */
export function useBillingAdmin(mandateId?: string) {
  const [settings, setSettings] = useState<BillingSettings | null>(null);
  const [accounts, setAccounts] = useState<AccountSummary[]>([]);
  const [transactions, setTransactions] = useState<BillingTransaction[]>([]);
  const [users, setUsers] = useState<MandateUserSummary[]>([]);
  const { request, isLoading: loading, error } = useApiRequest();

  // Fetch settings for a mandate
  const loadSettings = useCallback(async (targetMandateId?: string) => {
    const mId = targetMandateId || mandateId;
    if (!mId) return null;
    
    try {
      const data = await fetchSettingsAdmin(request, mId);
      setSettings(data);
      return data;
    } catch (err) {
      console.error('Error loading billing settings:', err);
      setSettings(null);
      return null;
    }
  }, [request, mandateId]);

  // Fetch accounts for a mandate
  const loadAccounts = useCallback(async (targetMandateId?: string) => {
    const mId = targetMandateId || mandateId;
    if (!mId) return [];
    
    try {
      const data = await fetchAccountsAdmin(request, mId);
      setAccounts(Array.isArray(data) ? data : []);
      return data;
    } catch (err) {
      console.error('Error loading accounts:', err);
      setAccounts([]);
      return [];
    }
  }, [request, mandateId]);

  // Fetch transactions for a mandate
  const loadTransactions = useCallback(async (targetMandateId?: string, limit: number = 100) => {
    const mId = targetMandateId || mandateId;
    if (!mId) return [];
    
    try {
      const data = await fetchTransactionsAdmin(request, mId, limit);
      setTransactions(Array.isArray(data) ? data : []);
      return data;
    } catch (err) {
      console.error('Error loading transactions:', err);
      setTransactions([]);
      return [];
    }
  }, [request, mandateId]);

  // Fetch users for a mandate
  const loadUsers = useCallback(async (targetMandateId?: string) => {
    const mId = targetMandateId || mandateId;
    if (!mId) return [];
    
    try {
      const data = await fetchUsersForMandateAdmin(request, mId);
      setUsers(Array.isArray(data) ? data : []);
      return data;
    } catch (err) {
      console.error('Error loading users:', err);
      setUsers([]);
      return [];
    }
  }, [request, mandateId]);

  // Update settings — after billing model change, reload dependent data (accounts / users / tx)
  const saveSettings = useCallback(
    async (settingsUpdate: BillingSettingsUpdate, targetMandateId?: string) => {
      const mId = targetMandateId || mandateId;
      if (!mId) return null;

      const previousModel = settings?.billingModel;

      try {
        const data = await updateSettingsAdmin(request, mId, settingsUpdate);
        setSettings(data);
        const newModel = settingsUpdate.billingModel;
        const modelChanged =
          newModel !== undefined && newModel !== null && newModel !== previousModel;
        if (modelChanged) {
          await Promise.all([
            loadAccounts(mId),
            loadTransactions(mId, 100),
            loadUsers(mId),
          ]);
        }
        return data;
      } catch (err) {
        console.error('Error saving billing settings:', err);
        throw err;
      }
    },
    [request, mandateId, settings?.billingModel, loadAccounts, loadTransactions, loadUsers]
  );

  // Add credit (manual, admin)
  const addCredit = useCallback(
    async (creditRequest: CreditAddRequest, targetMandateId?: string) => {
      const mId = targetMandateId || mandateId;
      if (!mId) return null;

      try {
        const result = await addCreditAdmin(request, mId, creditRequest);
        await loadAccounts(mId);
        return result;
      } catch (err) {
        console.error('Error adding credit:', err);
        throw err;
      }
    },
    [request, mandateId, loadAccounts]
  );

  // Create Stripe Checkout Session (returns redirect URL)
  const createCheckout = useCallback(
    async (checkoutRequest: CheckoutCreateRequest, targetMandateId?: string) => {
      const mId = targetMandateId || mandateId;
      if (!mId) return null;

      try {
        return await createCheckoutSessionApi(request, mId, checkoutRequest);
      } catch (err) {
        console.error('Error creating checkout session:', err);
        throw err;
      }
    },
    [request, mandateId]
  );

  // Load data when mandateId changes
  useEffect(() => {
    if (mandateId) {
      loadSettings();
      loadAccounts();
      loadTransactions();
      loadUsers();
    }
  }, [mandateId]);

  return {
    settings,
    accounts,
    transactions,
    users,
    loading,
    error,
    loadSettings,
    saveSettings,
    addCredit,
    createCheckout,
    loadAccounts,
    loadTransactions,
    loadUsers,
    refetch: () => {
      if (mandateId) {
        loadSettings();
        loadAccounts();
        loadTransactions();
        loadUsers();
      }
    },
  };
}

export default useBilling;
