/**
 * Trustee Hooks
 * 
 * Hooks für das Trustee-Feature mit Instanz-Kontext.
 * Die instanceId wird automatisch aus der URL gelesen.
 */

import { useState, useEffect, useCallback } from 'react';
import { useApiRequest } from './useApi';
import api from '../api';
import { usePermissions, type UserPermissions } from './usePermissions';
import { useInstanceId } from './useCurrentInstance';
import {
  // Types
  type TrusteeOrganisation,
  type TrusteeRole,
  type TrusteeAccess,
  type TrusteeContract,
  type TrusteeDocument,
  type TrusteePosition,
  type TrusteePositionDocument,
  type PaginationParams,
  // Organisation API
  fetchOrganisations as fetchOrganisationsApi,
  fetchOrganisationById as fetchOrganisationByIdApi,
  createOrganisation as createOrganisationApi,
  updateOrganisation as updateOrganisationApi,
  deleteOrganisation as deleteOrganisationApi,
  // Role API
  fetchRoles as fetchRolesApi,
  fetchRoleById as fetchRoleByIdApi,
  createRole as createRoleApi,
  updateRole as updateRoleApi,
  deleteRole as deleteRoleApi,
  // Access API
  fetchAccess as fetchAccessApi,
  fetchAccessById as fetchAccessByIdApi,
  createAccess as createAccessApi,
  updateAccess as updateAccessApi,
  deleteAccess as deleteAccessApi,
  // Contract API
  fetchContracts as fetchContractsApi,
  fetchContractById as fetchContractByIdApi,
  createContract as createContractApi,
  updateContract as updateContractApi,
  deleteContract as deleteContractApi,
  // Document API
  fetchDocuments as fetchDocumentsApi,
  fetchDocumentById as fetchDocumentByIdApi,
  createDocument as createDocumentApi,
  updateDocument as updateDocumentApi,
  deleteDocument as deleteDocumentApi,
  // Position API
  fetchPositions as fetchPositionsApi,
  fetchPositionById as fetchPositionByIdApi,
  createPosition as createPositionApi,
  updatePosition as updatePositionApi,
  deletePosition as deletePositionApi,
  // Position-Document API
  fetchPositionDocuments as fetchPositionDocumentsApi,
  createPositionDocument as createPositionDocumentApi,
  updatePositionDocument as updatePositionDocumentApi,
  deletePositionDocument as deletePositionDocumentApi,
} from '../api/trusteeApi';

// Re-export types
export type {
  TrusteeOrganisation,
  TrusteeRole,
  TrusteeAccess,
  TrusteeContract,
  TrusteeDocument,
  TrusteePosition,
  TrusteePositionDocument,
  PaginationParams
};

export interface AttributeDefinition {
  name: string;
  type: 'text' | 'email' | 'date' | 'checkbox' | 'select' | 'multiselect' | 'number' | 'textarea' | 'timestamp' | 'file';
  label: string;
  description?: string;
  required?: boolean;
  default?: any;
  options?: any[] | string;
  readonly?: boolean;
  editable?: boolean;
  visible?: boolean;
  order?: number;
  sortable?: boolean;
  filterable?: boolean;
  searchable?: boolean;
  width?: number;
  minWidth?: number;
  maxWidth?: number;
  filterOptions?: string[];
  dependsOn?: string;
}

// ============================================================================
// GENERIC TRUSTEE ENTITY HOOK FACTORY
// ============================================================================

interface TrusteeEntityConfig<T> {
  entityName: string;
  fetchAll: (request: any, instanceId: string, params?: PaginationParams) => Promise<any>;
  fetchById: (request: any, instanceId: string, id: string) => Promise<T | null>;
  create: (request: any, instanceId: string, data: Partial<T>) => Promise<T>;
  update: (request: any, instanceId: string, id: string, data: Partial<T>) => Promise<T>;
  deleteItem: (request: any, instanceId: string, id: string) => Promise<void>;
}

function _createTrusteeEntityHook<T extends { id: string }>(config: TrusteeEntityConfig<T>) {
  return function useTrusteeEntity() {
    // Hole instanceId aus URL-Kontext
    const instanceId = useInstanceId();
    
    const [items, setItems] = useState<T[]>([]);
    const [attributes, setAttributes] = useState<AttributeDefinition[]>([]);
    const [permissions, setPermissions] = useState<UserPermissions | null>(null);
    const [pagination, setPagination] = useState<{
      currentPage: number;
      pageSize: number;
      totalItems: number;
      totalPages: number;
    } | null>(null);
    const { request, isLoading: loading, error } = useApiRequest<null, T[]>();
    const { checkPermission } = usePermissions();

    const fetchAttributes = useCallback(async () => {
      if (!instanceId) return [];
      
      try {
        const response = await api.get(`/api/trustee/${instanceId}/attributes/${config.entityName}`);
        let attrs: AttributeDefinition[] = [];
        if (response.data?.attributes && Array.isArray(response.data.attributes)) {
          attrs = response.data.attributes;
        } else if (Array.isArray(response.data)) {
          attrs = response.data;
        }
        setAttributes(attrs);
        return attrs;
      } catch (error: any) {
        console.error(`Error fetching ${config.entityName} attributes:`, error);
        setAttributes([]);
        return [];
      }
    }, [instanceId]);

    const fetchPermissions = useCallback(async () => {
      try {
        // Use fully qualified objectKey for RBAC: data.feature.trustee.EntityName
        const objectKey = `data.feature.trustee.${config.entityName}`;
        const perms = await checkPermission('DATA', objectKey);
        setPermissions(perms);
        return perms;
      } catch (error: any) {
        console.error(`Error fetching ${config.entityName} permissions:`, error);
        const defaultPerms: UserPermissions = {
          view: false,
          read: 'n',
          create: 'n',
          update: 'n',
          delete: 'n',
        };
        setPermissions(defaultPerms);
        return defaultPerms;
      }
    }, [checkPermission]);

    const fetchItems = useCallback(async (params?: PaginationParams) => {
      if (!instanceId) {
        setItems([]);
        return;
      }
      
      try {
        const data = await config.fetchAll(request, instanceId, params);
        
        if (data && typeof data === 'object' && 'items' in data) {
          const fetchedItems = Array.isArray(data.items) ? data.items : [];
          setItems(fetchedItems);
          if (data.pagination) {
            setPagination(data.pagination);
          }
        } else {
          const fetchedItems = Array.isArray(data) ? data : [];
          setItems(fetchedItems);
          setPagination(null);
        }
      } catch (error: any) {
        setItems([]);
        setPagination(null);
      }
    }, [request, instanceId]);

    const removeOptimistically = (itemId: string) => {
      setItems(prev => prev.filter(item => item.id !== itemId));
    };

    const updateOptimistically = (itemId: string, updateData: Partial<T>) => {
      setItems(prev =>
        prev.map(item =>
          item.id === itemId
            ? { ...item, ...updateData }
            : item
        )
      );
    };

    const fetchById = useCallback(async (itemId: string): Promise<T | null> => {
      if (!instanceId) return null;
      return await config.fetchById(request, instanceId, itemId);
    }, [request, instanceId]);

    const generateEditFieldsFromAttributes = useCallback(() => {
      if (!attributes || attributes.length === 0) {
        return [];
      }

      return attributes
        .filter(attr => {
          if (attr.readonly === true || attr.editable === false) {
            return false;
          }
          if (attr.name === 'id') {
            return false;
          }
          const nonEditableFields = ['_createdBy', '_createdAt', '_modifiedBy', '_modifiedAt'];
          return !nonEditableFields.includes(attr.name);
        })
        .map(attr => {
          let fieldType: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'multiselect' | 'readonly' | 'number' = 'string';
          let options: Array<{ value: string | number; label: string }> | undefined = undefined;
          let optionsReference: string | undefined = undefined;

          if (attr.type === 'checkbox') {
            fieldType = 'boolean';
          } else if (attr.type === 'email') {
            fieldType = 'email';
          } else if (attr.type === 'date') {
            fieldType = 'date';
          } else if (attr.type === 'number') {
            fieldType = 'number';
          } else if (attr.type === 'select') {
            fieldType = 'enum';
            if (Array.isArray(attr.options)) {
              options = attr.options.map((opt: any) => {
                const labelValue = typeof opt.label === 'string'
                  ? opt.label
                  : opt.label?.en || opt.label?.[Object.keys(opt.label)[0]] || String(opt.value);
                return { value: opt.value, label: labelValue };
              });
            } else if (typeof attr.options === 'string') {
              optionsReference = attr.options;
            }
          } else if (attr.type === 'multiselect') {
            fieldType = 'multiselect';
            if (Array.isArray(attr.options)) {
              options = attr.options.map((opt: any) => {
                const labelValue = typeof opt.label === 'string'
                  ? opt.label
                  : opt.label?.en || opt.label?.[Object.keys(opt.label)[0]] || String(opt.value);
                return { value: opt.value, label: labelValue };
              });
            } else if (typeof attr.options === 'string') {
              optionsReference = attr.options;
            }
          } else if (attr.type === 'textarea') {
            fieldType = 'textarea';
          } else if (attr.type === 'timestamp') {
            fieldType = 'readonly';
          }

          return {
            key: attr.name,
            label: attr.label || attr.name,
            type: fieldType,
            editable: attr.editable !== false && attr.readonly !== true,
            required: attr.required === true,
            options,
            optionsReference,
            dependsOn: attr.dependsOn
          };
        });
    }, [attributes]);

    const generateCreateFieldsFromAttributes = useCallback(() => {
      if (!attributes || attributes.length === 0) {
        return [];
      }

      return attributes
        .filter(attr => {
          const systemFields = ['_createdBy', '_createdAt', '_modifiedBy', '_modifiedAt', 'mandateId'];
          return !systemFields.includes(attr.name);
        })
        .map(attr => {
          let fieldType: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'multiselect' | 'readonly' | 'number' = 'string';
          let options: Array<{ value: string | number; label: string }> | undefined = undefined;
          let optionsReference: string | undefined = undefined;

          if (attr.type === 'checkbox') {
            fieldType = 'boolean';
          } else if (attr.type === 'email') {
            fieldType = 'email';
          } else if (attr.type === 'date') {
            fieldType = 'date';
          } else if (attr.type === 'number') {
            fieldType = 'number';
          } else if (attr.type === 'select') {
            fieldType = 'enum';
            if (Array.isArray(attr.options)) {
              options = attr.options.map((opt: any) => {
                const labelValue = typeof opt.label === 'string'
                  ? opt.label
                  : opt.label?.en || opt.label?.[Object.keys(opt.label)[0]] || String(opt.value);
                return { value: opt.value, label: labelValue };
              });
            } else if (typeof attr.options === 'string') {
              optionsReference = attr.options;
            }
          } else if (attr.type === 'multiselect') {
            fieldType = 'multiselect';
            if (Array.isArray(attr.options)) {
              options = attr.options.map((opt: any) => {
                const labelValue = typeof opt.label === 'string'
                  ? opt.label
                  : opt.label?.en || opt.label?.[Object.keys(opt.label)[0]] || String(opt.value);
                return { value: opt.value, label: labelValue };
              });
            } else if (typeof attr.options === 'string') {
              optionsReference = attr.options;
            }
          } else if (attr.type === 'textarea') {
            fieldType = 'textarea';
          } else if (attr.type === 'timestamp') {
            fieldType = 'readonly';
          }

          return {
            key: attr.name,
            label: attr.label || attr.name,
            type: fieldType,
            editable: true,
            required: attr.required === true,
            options,
            optionsReference,
            dependsOn: attr.dependsOn
          };
        });
    }, [attributes]);

    const ensureAttributesLoaded = useCallback(async () => {
      if (attributes && attributes.length > 0) {
        return attributes;
      }
      return await fetchAttributes();
    }, [attributes, fetchAttributes]);

    // Lade Daten wenn instanceId verfügbar
    useEffect(() => {
      if (instanceId) {
        fetchAttributes();
        fetchPermissions();
        fetchItems();
      }
    }, [instanceId, fetchAttributes, fetchPermissions, fetchItems]);

    return {
      items,
      loading,
      error,
      refetch: fetchItems,
      removeOptimistically,
      updateOptimistically,
      attributes,
      permissions,
      pagination,
      fetchById,
      generateEditFieldsFromAttributes,
      generateCreateFieldsFromAttributes,
      ensureAttributesLoaded,
      instanceId // Auch instanceId zurückgeben für Operations-Hook
    };
  };
}

function _createTrusteeOperationsHook<T extends { id: string }>(config: TrusteeEntityConfig<T>) {
  return function useTrusteeEntityOperations() {
    // Hole instanceId aus URL-Kontext
    const instanceId = useInstanceId();
    
    const [deletingItems, setDeletingItems] = useState<Set<string>>(new Set());
    const [creatingItem, setCreatingItem] = useState(false);
    const { request, isLoading } = useApiRequest();
    const [deleteError, setDeleteError] = useState<string | null>(null);
    const [createError, setCreateError] = useState<string | null>(null);
    const [updateError, setUpdateError] = useState<string | null>(null);

    const handleDelete = useCallback(async (itemId: string) => {
      if (!instanceId) {
        setDeleteError('No instance context');
        return false;
      }
      
      setDeleteError(null);
      setDeletingItems(prev => new Set(prev).add(itemId));

      try {
        await config.deleteItem(request, instanceId, itemId);
        await new Promise(resolve => setTimeout(resolve, 300));
        return true;
      } catch (error: any) {
        setDeleteError(error.message);
        return false;
      } finally {
        setDeletingItems(prev => {
          const newSet = new Set(prev);
          newSet.delete(itemId);
          return newSet;
        });
      }
    }, [request, instanceId]);

    const handleCreate = useCallback(async (itemData: Partial<T>) => {
      if (!instanceId) {
        setCreateError('No instance context');
        return { success: false, error: 'No instance context' };
      }
      
      setCreateError(null);
      setCreatingItem(true);

      console.warn('🔧 handleCreate called with itemData:', itemData);

      try {
        const newItem = await config.create(request, instanceId, itemData);
        return { success: true, data: newItem };
      } catch (error: any) {
        console.error('🔧 handleCreate error:', {
          message: error.message,
          response: error.response?.data,
          status: error.response?.status
        });
        const errorMessage = error.response?.data?.detail || error.message;
        setCreateError(errorMessage);
        return { success: false, error: errorMessage };
      } finally {
        setCreatingItem(false);
      }
    }, [request, instanceId]);

    const handleUpdate = useCallback(async (itemId: string, updateData: Partial<T>) => {
      if (!instanceId) {
        setUpdateError('No instance context');
        return { success: false, error: 'No instance context' };
      }
      
      setUpdateError(null);

      try {
        const updatedItem = await config.update(request, instanceId, itemId, updateData);
        return { success: true, data: updatedItem };
      } catch (error: any) {
        const errorMessage = error.response?.data?.message || error.message || 'Failed to update';
        setUpdateError(errorMessage);
        return {
          success: false,
          error: errorMessage,
          statusCode: error.response?.status,
          isPermissionError: error.response?.status === 403,
          isValidationError: error.response?.status === 400
        };
      }
    }, [request, instanceId]);

    return {
      deletingItems,
      creatingItem,
      deleteError,
      createError,
      updateError,
      handleDelete,
      handleCreate,
      handleUpdate,
      isLoading,
      instanceId
    };
  };
}

// ============================================================================
// ORGANISATION HOOKS
// ============================================================================

const organisationConfig: TrusteeEntityConfig<TrusteeOrganisation> = {
  entityName: 'TrusteeOrganisation',
  fetchAll: fetchOrganisationsApi,
  fetchById: fetchOrganisationByIdApi,
  create: createOrganisationApi,
  update: updateOrganisationApi,
  deleteItem: deleteOrganisationApi
};

export const useTrusteeOrganisations = _createTrusteeEntityHook(organisationConfig);
export const useTrusteeOrganisationOperations = _createTrusteeOperationsHook(organisationConfig);

// ============================================================================
// ROLE HOOKS
// ============================================================================

const roleConfig: TrusteeEntityConfig<TrusteeRole> = {
  entityName: 'TrusteeRole',
  fetchAll: fetchRolesApi,
  fetchById: fetchRoleByIdApi,
  create: createRoleApi,
  update: updateRoleApi,
  deleteItem: deleteRoleApi
};

export const useTrusteeRoles = _createTrusteeEntityHook(roleConfig);
export const useTrusteeRoleOperations = _createTrusteeOperationsHook(roleConfig);

// ============================================================================
// ACCESS HOOKS
// ============================================================================

const accessConfig: TrusteeEntityConfig<TrusteeAccess> = {
  entityName: 'TrusteeAccess',
  fetchAll: fetchAccessApi,
  fetchById: fetchAccessByIdApi,
  create: createAccessApi,
  update: updateAccessApi,
  deleteItem: deleteAccessApi
};

export const useTrusteeAccess = _createTrusteeEntityHook(accessConfig);
export const useTrusteeAccessOperations = _createTrusteeOperationsHook(accessConfig);

// ============================================================================
// CONTRACT HOOKS
// ============================================================================

const contractConfig: TrusteeEntityConfig<TrusteeContract> = {
  entityName: 'TrusteeContract',
  fetchAll: fetchContractsApi,
  fetchById: fetchContractByIdApi,
  create: createContractApi,
  update: updateContractApi,
  deleteItem: deleteContractApi
};

export const useTrusteeContracts = _createTrusteeEntityHook(contractConfig);
export const useTrusteeContractOperations = _createTrusteeOperationsHook(contractConfig);

// ============================================================================
// DOCUMENT HOOKS
// ============================================================================

const documentConfig: TrusteeEntityConfig<TrusteeDocument> = {
  entityName: 'TrusteeDocument',
  fetchAll: fetchDocumentsApi,
  fetchById: fetchDocumentByIdApi,
  create: createDocumentApi,
  update: updateDocumentApi,
  deleteItem: deleteDocumentApi
};

export const useTrusteeDocuments = _createTrusteeEntityHook(documentConfig);
export const useTrusteeDocumentOperations = _createTrusteeOperationsHook(documentConfig);

// ============================================================================
// POSITION HOOKS
// ============================================================================

const positionConfig: TrusteeEntityConfig<TrusteePosition> = {
  entityName: 'TrusteePosition',
  fetchAll: fetchPositionsApi,
  fetchById: fetchPositionByIdApi,
  create: createPositionApi,
  update: updatePositionApi,
  deleteItem: deletePositionApi
};

export const useTrusteePositions = _createTrusteeEntityHook(positionConfig);
export const useTrusteePositionOperations = _createTrusteeOperationsHook(positionConfig);

// ============================================================================
// POSITION-DOCUMENT HOOKS
// ============================================================================

const positionDocumentConfig: TrusteeEntityConfig<TrusteePositionDocument> = {
  entityName: 'TrusteePositionDocument',
  fetchAll: fetchPositionDocumentsApi,
  fetchById: async () => null,
  create: createPositionDocumentApi,
  update: updatePositionDocumentApi,
  deleteItem: deletePositionDocumentApi
};

export const useTrusteePositionDocuments = _createTrusteeEntityHook(positionDocumentConfig);
export const useTrusteePositionDocumentOperations = _createTrusteeOperationsHook(positionDocumentConfig);
