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 {
  fetchPositions as fetchPositionsApi,
  fetchPositionById as fetchPositionByIdApi,
  createPosition as createPositionApi,
  updatePosition as updatePositionApi,
  deletePosition as deletePositionApi,
  type TrusteePosition,
  type PaginationParams
} from '../api/trusteeApi';

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;
}

// Re-export types
export type { TrusteePosition, PaginationParams };

// Positions list hook
export function useTrusteePositions() {
  const instanceId = useInstanceId();

  const [positions, setPositions] = useState<TrusteePosition[]>([]);
  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, TrusteePosition[]>();
  const { checkPermission } = usePermissions();

  // Fetch attributes from backend
  const fetchAttributes = useCallback(async () => {
    if (!instanceId) return [];

    try {
      const response = await api.get(`/api/trustee/${instanceId}/attributes/TrusteePosition`);
      
      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;
      } else if (response.data && typeof response.data === 'object') {
        const keys = Object.keys(response.data);
        for (const key of keys) {
          if (Array.isArray(response.data[key])) {
            attrs = response.data[key];
            break;
          }
        }
      }
      
      setAttributes(attrs);
      return attrs;
    } catch (error: any) {
      console.error('Error fetching attributes:', error);
      setAttributes([]);
      return [];
    }
  }, [instanceId]);

  // Fetch permissions from backend
  const fetchPermissions = useCallback(async () => {
    try {
      const objectKey = 'data.feature.trustee.TrusteePosition';
      const perms = await checkPermission('DATA', objectKey);
      setPermissions(perms);
      return perms;
    } catch (error: any) {
      console.error('Error fetching permissions:', error);
      const defaultPerms: UserPermissions = {
        view: false,
        read: 'n',
        create: 'n',
        update: 'n',
        delete: 'n',
      };
      setPermissions(defaultPerms);
      return defaultPerms;
    }
  }, [checkPermission]);

  const fetchPositions = useCallback(async (params?: PaginationParams) => {
    if (!instanceId) {
      setPositions([]);
      return;
    }

    try {
      const data = await fetchPositionsApi(request, instanceId, params);
      
      if (data && typeof data === 'object' && 'items' in data) {
        const items = Array.isArray(data.items) ? data.items : [];
        setPositions(items);
        if (data.pagination) {
          setPagination(data.pagination);
        }
      } else {
        const items = Array.isArray(data) ? data : [];
        setPositions(items);
        setPagination(null);
      }
    } catch (error: any) {
      setPositions([]);
      setPagination(null);
    }
  }, [request, instanceId]);

  // Optimistically remove a position
  const removeOptimistically = (positionId: string) => {
    setPositions(prevPositions => prevPositions.filter(pos => pos.id !== positionId));
  };

  // Optimistically update a position
  const updateOptimistically = (positionId: string, updateData: Partial<TrusteePosition>) => {
    setPositions(prevPositions => 
      prevPositions.map(pos => 
        pos.id === positionId 
          ? { ...pos, ...updateData }
          : pos
      )
    );
  };

  // Fetch a single position by ID
  const fetchPositionById = useCallback(async (positionId: string): Promise<TrusteePosition | null> => {
    if (!instanceId) return null;
    return await fetchPositionByIdApi(request, instanceId, positionId);
  }, [request, instanceId]);

  // Generate edit fields from attributes dynamically with MwSt calculation logic
  const generateEditFieldsFromAttributes = useCallback((): Array<{
    key: string;
    label: string;
    type: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'multiselect' | 'readonly' | 'number';
    editable?: boolean;
    required?: boolean;
    validator?: (value: any, formData?: any) => string | null;
    onChange?: (value: any, formData: any) => Partial<any>;
    options?: Array<{ value: string | number; label: string }>;
    optionsReference?: string;
    dependsOn?: string;
    minRows?: number;
    maxRows?: number;
  }> => {
    if (!attributes || attributes.length === 0) {
      return [];
    }

    const editableFields = attributes
      .filter(attr => {
        if (attr.readonly === true || attr.editable === false) {
          return false;
        }
        const nonEditableFields = ['id', 'mandate', '_createdBy', '_modifiedBy', '_createdAt', '_modifiedAt'];
        return !nonEditableFields.includes(attr.name);
      })
      .map(attr => {
        const isDescField = attr.name === 'desc' || attr.name.toLowerCase().includes('description');
        
        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;
        let dependsOn: string | undefined = undefined;
        let minRows: number | undefined = undefined;
        let maxRows: number | undefined = undefined;
        let onChange: ((value: any, formData: any) => Partial<any>) | undefined = undefined;
        
        if (isDescField) {
          fieldType = 'textarea';
          minRows = 3;
          maxRows = 8;
        } else 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 === 'textarea') {
          fieldType = 'textarea';
          minRows = minRows || 3;
          maxRows = maxRows || 8;
        }

        // contractId depends on organisationId
        if (attr.name === 'contractId') {
          dependsOn = 'organisationId';
        }

        // CUSTOM LOGIC: MwSt-Berechnung
        // When bookingAmount or vatPercentage changes, auto-calculate vatAmount
        if (attr.name === 'bookingAmount') {
          onChange = (value: number, formData: any) => {
            const amount = parseFloat(String(value)) || 0;
            const percentage = parseFloat(String(formData.vatPercentage)) || 0;
            const calculatedVat = amount * (percentage / 100);
            return { vatAmount: calculatedVat };
          };
        } else if (attr.name === 'vatPercentage') {
          onChange = (value: number, formData: any) => {
            const percentage = parseFloat(String(value)) || 0;
            const amount = parseFloat(String(formData.bookingAmount)) || 0;
            const calculatedVat = amount * (percentage / 100);
            return { vatAmount: calculatedVat };
          };
        }

        let required = attr.required === true;
        let validator: ((value: any, formData?: any) => string | null) | undefined = undefined;

        // CUSTOM LOGIC: vatAmount validator - warn if manually overridden
        if (attr.name === 'vatAmount') {
          validator = (value: any, formData?: any) => {
            if (!formData) return null;
            
            const vatAmount = parseFloat(String(value)) || 0;
            const bookingAmount = parseFloat(String(formData.bookingAmount)) || 0;
            const vatPercentage = parseFloat(String(formData.vatPercentage)) || 0;
            const calculatedVat = bookingAmount * (vatPercentage / 100);
            
            if (Math.abs(vatAmount - calculatedVat) > 0.01) {
              return 'MwSt-Betrag weicht von Berechnung ab (manuell überschrieben)';
            }
            return null;
          };
        }

        // Standard validators
        if (attr.name === 'organisationId' || attr.name === 'contractId') {
          required = true;
          validator = (value: any) => {
            if (!value || (typeof value === 'string' && value.trim() === '')) {
              return `${attr.label || attr.name} is required`;
            }
            return null;
          };
        } else if (attr.name === 'valuta' || attr.name === 'transactionDateTime') {
          required = true;
        } else if (attr.name === 'bookingCurrency' || attr.name === 'originalCurrency') {
          required = true;
        } else if (attr.name === 'bookingAmount' || attr.name === 'originalAmount') {
          required = true;
          validator = (value: any) => {
            const num = parseFloat(String(value));
            if (isNaN(num)) {
              return 'Must be a valid number';
            }
            return null;
          };
        }

        return {
          key: attr.name,
          label: attr.label || attr.name,
          type: fieldType,
          editable: attr.editable !== false && attr.readonly !== true,
          required,
          validator,
          onChange,
          options,
          optionsReference,
          dependsOn,
          minRows,
          maxRows
        };
      });

    return editableFields;
  }, [attributes]);

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

  // Fetch data when instanceId is available
  useEffect(() => {
    if (instanceId) {
      fetchAttributes();
      fetchPermissions();
      fetchPositions();
    }
  }, [instanceId, fetchAttributes, fetchPermissions, fetchPositions]);

  return { 
    positions, 
    loading, 
    error, 
    refetch: fetchPositions,
    removeOptimistically,
    updateOptimistically,
    attributes,
    permissions,
    pagination,
    fetchPositionById,
    generateEditFieldsFromAttributes,
    ensureAttributesLoaded,
    instanceId
  };
}

// Position operations hook
export function useTrusteePositionOperations() {
  const instanceId = useInstanceId();

  const [deletingPositions, setDeletingPositions] = useState<Set<string>>(new Set());
  const [creatingPosition, setCreatingPosition] = 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 handlePositionDelete = async (positionId: string) => {
    if (!instanceId) {
      setDeleteError('No instance context');
      return false;
    }

    setDeleteError(null);
    setDeletingPositions(prev => new Set(prev).add(positionId));
    
    try {
      await deletePositionApi(request, instanceId, positionId);
      await new Promise(resolve => setTimeout(resolve, 300));
      return true;
    } catch (error: any) {
      setDeleteError(error.message);
      return false;
    } finally {
      setDeletingPositions(prev => {
        const newSet = new Set(prev);
        newSet.delete(positionId);
        return newSet;
      });
    }
  };

  const handlePositionCreate = async (positionData: Partial<TrusteePosition>) => {
    if (!instanceId) {
      setCreateError('No instance context');
      return { success: false, error: 'No instance context' };
    }

    setCreateError(null);
    setCreatingPosition(true);
    
    try {
      const newPosition = await createPositionApi(request, instanceId, positionData);
      return { success: true, positionData: newPosition };
    } catch (error: any) {
      setCreateError(error.message);
      return { success: false, error: error.message };
    } finally {
      setCreatingPosition(false);
    }
  };

  const handlePositionUpdate = async (
    positionId: string, 
    updateData: Partial<TrusteePosition>, 
    _originalData?: any
  ) => {
    if (!instanceId) {
      setUpdateError('No instance context');
      return { success: false, error: 'No instance context' };
    }

    setUpdateError(null);
    
    try {
      const updatedPosition = await updatePositionApi(request, instanceId, positionId, updateData);
      return { success: true, positionData: updatedPosition };
    } catch (error: any) {
      const errorMessage = error.response?.data?.message || error.message || 'Failed to update position';
      const statusCode = error.response?.status;
      
      setUpdateError(errorMessage);
      
      return { 
        success: false, 
        error: errorMessage,
        statusCode,
        isPermissionError: statusCode === 403,
        isValidationError: statusCode === 400
      };
    }
  };

  return {
    deletingPositions,
    creatingPosition,
    deleteError,
    createError,
    updateError,
    handlePositionDelete,
    handlePositionCreate,
    handlePositionUpdate,
    isLoading,
    instanceId
  };
}
