/**
 * Single source of truth for valid chart of accounts types and categories.
 * Enforces a strict hierarchy with specific categories and detail types.
 * 
 * IMPORTANT: Any future account_type additions or changes MUST be updated here 
 * AND in the Supabase 'chart_of_accounts' table constraint 'chk_coa_account_type'.
 */

export const VALID_ACCOUNT_TYPES = ['Asset', 'Liability', 'Equity', 'Income', 'Expense', 'Suspense'];

export const ASSET_TYPES = ['Current assets', 'Fixed assets'];
export const LIABILITY_TYPES = ['Current liabilities', 'Fixed liabilities'];
export const REVENUE_TYPES = ['Income', 'Non-operating income'];
export const EXPENSE_TYPES = ['Expenses', 'Non-operating expenses'];
export const EQUITY_CATEGORIES = [...REVENUE_TYPES, ...EXPENSE_TYPES, 'Equity']; 
export const SUSPENSE_CATEGORIES = ['Suspense', 'Uncategorized'];

// Detailed categorized structures for HOA/Property Management
export const DETAILED_INCOME_CATEGORIES = [
  {
    group: 'Assessments',
    items: [
      { value: 'Assessments', desc: 'Standard periodic HOA dues' },
      { value: 'Special Assessments', desc: 'One-time or special project dues' },
      { value: 'Reserve Assessments', desc: 'Dues allocated specifically to reserves' }
    ]
  },
  {
    group: 'Fees & Fines',
    items: [
      { value: 'Late Fees', desc: 'Penalties for overdue payments' },
      { value: 'Violation Fines', desc: 'Fines for rule violations' },
      { value: 'Application Fees', desc: 'ARC or other application fees' }
    ]
  },
  {
    group: 'Other Income',
    items: [
      { value: 'Interest Income', desc: 'Interest earned on bank accounts' },
      { value: 'Rental Income', desc: 'Income from renting clubhouse or amenities' },
      { value: 'Misc Income', desc: 'Other miscellaneous income' }
    ]
  }
];

export const DETAILED_EXPENSE_CATEGORIES = [
  {
    group: 'Administrative',
    items: [
      { value: 'Management Fees', desc: 'Fees paid to property management' },
      { value: 'Legal & Professional', desc: 'Attorney, CPA, and consulting fees' },
      { value: 'Office Expenses', desc: 'Postage, printing, software, supplies' },
      { value: 'Insurance', desc: 'Property, liability, and D&O insurance' }
    ]
  },
  {
    group: 'Utilities',
    items: [
      { value: 'Electricity', desc: 'Electric utility bills' },
      { value: 'Water & Sewer', desc: 'Water and sewer utility bills' },
      { value: 'Trash Removal', desc: 'Garbage and recycling services' },
      { value: 'Internet & Phone', desc: 'Telecommunications services' }
    ]
  },
  {
    group: 'Maintenance & Repairs',
    items: [
      { value: 'Landscaping', desc: 'Lawn care and landscaping services' },
      { value: 'Pool Maintenance', desc: 'Pool cleaning and chemicals' },
      { value: 'General Maintenance', desc: 'General property and building repairs' },
      { value: 'Janitorial', desc: 'Cleaning services for common areas' }
    ]
  },
  {
    group: 'Taxes & Other',
    items: [
      { value: 'Property Taxes', desc: 'Taxes on association-owned property' },
      { value: 'Income Taxes', desc: 'State and federal income taxes' },
      { value: 'Reserve Contributions', desc: 'Transfers to reserve accounts' }
    ]
  }
];

export const VALID_CATEGORIES = [
  ...ASSET_TYPES,
  ...LIABILITY_TYPES,
  ...EQUITY_CATEGORIES,
  ...SUSPENSE_CATEGORIES,
  ...DETAILED_INCOME_CATEGORIES.map(g => g.group),
  ...DETAILED_INCOME_CATEGORIES.flatMap(g => g.items.map(i => i.value)),
  ...DETAILED_EXPENSE_CATEGORIES.map(g => g.group),
  ...DETAILED_EXPENSE_CATEGORIES.flatMap(g => g.items.map(i => i.value)),
  'Income', 
  'Non-operating income', 
  'Expenses', 
  'Non-operating expenses',
];

export const VALID_DETAIL_TYPES = [
  'bank_account',
  'cash',
  'accounts_receivable',
  'other_current_asset',
  'fixed_asset',
  'accounts_payable',
  'credit_card',
  'other_current_liability',
  'long_term_liability',
  'equity',
  'income',
  'expense',
  'none'
];

export const SUBCATEGORY_OPTIONS = ['Income', 'Expense', 'Deposit'];

export const SUBCATEGORY_BY_ACCOUNT_TYPE = {
  Asset: ['Deposit','Charge','Accounts Receivable','Income'],
  Liability: ['Expense'],
  Equity: ['Income', 'Expense', 'Deposit'],
  Income: ['Income', 'Deposit'],
  Expense: ['Expense'],
  Suspense: ['Expense', 'Deposit']
};

export function getValidSubcategoriesForAccountType(type) {
  return SUBCATEGORY_BY_ACCOUNT_TYPE[type] || [];
}

/**
 * Validates if an account type is strictly within the allowed set.
 */
export function validateAccountType(type) {
  if (!type) throw new Error("Account type is required.");
  
  const cleanType = type.trim();
  const match = VALID_ACCOUNT_TYPES.find(v => v === cleanType);
  if (!match) throw new Error(`Invalid account type: "${cleanType}". Allowed values are strictly: ${VALID_ACCOUNT_TYPES.join(', ')}.`);
  
  return true;
}

/**
 * Validates if a category is strictly within the allowed set.
 */
export function validateCategory(category) {
  if (!category) throw new Error("Category is required.");

  const cleanCategory = category.trim();
  const match = VALID_CATEGORIES.find(v => v === cleanCategory);
  if (!match) throw new Error(`Invalid category: "${cleanCategory}".`);

  return true;
}

export function validateSubcategory(subcat, accountType) {
  const validOptions = getValidSubcategoriesForAccountType(accountType);
  return validOptions.includes(subcat) || DETAILED_INCOME_CATEGORIES.some(g => g.items.some(i => i.value === subcat)) || DETAILED_EXPENSE_CATEGORIES.some(g => g.items.some(i => i.value === subcat));
}

export function isBankAccount(detailType) {
  return detailType === 'bank_account' || detailType === 'cash';
}

/**
 * Safely maps fuzzy or plural strings to standardized account types.
 */
export function safelyMapAccountType(accountTypeStr, accountName = '') {
  if (!accountTypeStr && !accountName) return null;
  const t = (accountTypeStr || accountName).toString().toLowerCase().trim();
  
  if (t.includes('asset') || t.includes('bank') || t.includes('cash') || t.includes('receivable')) return 'Asset';
  if (t.includes('liabilit') || t.includes('payable') || t.includes('escrow')) return 'Liability';
  if (t.includes('equit') || t.includes('capital') || t.includes('retained') || t.includes('fund balance')) return 'Equity';
  if (t.includes('income') || t.includes('revenue') || t.includes('sales') || t.includes('deposit')) return 'Income';
  if (t.includes('expens') || t.includes('cost') || t.includes('fee')) return 'Expense';
  if (t.includes('suspense') || t.includes('uncategorized')) return 'Suspense';
  
  return null;
}

/**
 * Safely maps fuzzy strings to standardized categories.
 */
export function safelyMapCategory(categoryStr, accountType = '') {
  const c = (categoryStr || '').toString().toLowerCase().trim();
  const t = (accountType || '').toString().toLowerCase().trim();

  if (c.includes('current asset')) return 'Current assets';
  if (c.includes('fixed asset')) return 'Fixed assets';
  if (c.includes('current liabilit')) return 'Current liabilities';
  if (c.includes('fixed liabilit') || c.includes('long term')) return 'Fixed liabilities';
  if (c.includes('non-operating income') || c.includes('other income')) return 'Non-operating income';
  if (c.includes('income') || c.includes('revenue')) return 'Income';
  if (c.includes('non-operating expense') || c.includes('other expense')) return 'Non-operating expenses';
  if (c.includes('expens') || c.includes('cost')) return 'Expenses';
  if (c.includes('equit')) return 'Equity';
  if (c.includes('suspense')) return 'Suspense';

  // Fallbacks based on mapped account type if category is blank or unrecognized
  if (t === 'asset') return 'Current assets';
  if (t === 'liability') return 'Current liabilities';
  if (t === 'equity') return 'Equity';
  if (t === 'income') return 'Income';
  if (t === 'expense') return 'Expenses';
  if (t === 'suspense') return 'Suspense';

  return null;
}