// VAT Code Configuration for Danish SKAT Compliance

import type {
  VATCode,
  VATCodeConfig,
  VATPeriodicitetConfig,
  SKATVATBox,
  VATBoxId,
  BasisBoxId,
} from '@/types/vat';
import type { VATPeriodicitet } from '@/types/periods';

/**
 * Complete VAT code configuration for Danish bookkeeping
 */
export const VAT_CODE_CONFIG: Record<VATCode, VATCodeConfig> = {
  S25: {
    code: 'S25',
    nameDanish: 'Udgaaende moms 25%',
    nameEnglish: 'Output VAT 25%',
    rate: 0.25,
    type: 'output',
    affectsBoxes: {
      vatBox: 'A',
      basisBox: '1',
    },
    reverseCharge: false,
    deductible: false,
    description: 'Moms paa salg af varer og ydelser i Danmark',
  },
  K25: {
    code: 'K25',
    nameDanish: 'Indgaaende moms 25%',
    nameEnglish: 'Input VAT 25%',
    rate: 0.25,
    type: 'input',
    affectsBoxes: {
      vatBox: 'B',
    },
    reverseCharge: false,
    deductible: true,
    description: 'Fradragsberettiget moms paa koeb',
  },
  EU_VARE: {
    code: 'EU_VARE',
    nameDanish: 'EU-varekoeb (erhvervelsesmoms)',
    nameEnglish: 'EU goods purchase (acquisition VAT)',
    rate: 0.25,
    type: 'reverse_charge',
    affectsBoxes: {
      vatBox: 'C',
      basisBox: '3',
    },
    reverseCharge: true,
    deductible: true, // Both output and input VAT
    description: 'Koeb af varer fra andre EU-lande med omvendt betalingspligt',
  },
  EU_YDELSE: {
    code: 'EU_YDELSE',
    nameDanish: 'EU-ydelseskoeb (omvendt betalingspligt)',
    nameEnglish: 'EU services purchase (reverse charge)',
    rate: 0.25,
    type: 'reverse_charge',
    affectsBoxes: {
      vatBox: 'D',
      basisBox: '4',
    },
    reverseCharge: true,
    deductible: true,
    description: 'Koeb af ydelser fra udlandet med omvendt betalingspligt',
  },
  MOMSFRI: {
    code: 'MOMSFRI',
    nameDanish: 'Momsfritaget',
    nameEnglish: 'VAT exempt',
    rate: 0,
    type: 'exempt',
    affectsBoxes: {
      basisBox: '2',
    },
    reverseCharge: false,
    deductible: false,
    description: 'Momsfritaget salg (sundhed, undervisning, mv.)',
  },
  EKSPORT: {
    code: 'EKSPORT',
    nameDanish: 'Eksport (0%)',
    nameEnglish: 'Export (0%)',
    rate: 0,
    type: 'exempt',
    affectsBoxes: {
      basisBox: '2',
    },
    reverseCharge: false,
    deductible: false,
    description: 'Eksport til lande uden for EU',
  },
  NONE: {
    code: 'NONE',
    nameDanish: 'Ingen moms',
    nameEnglish: 'No VAT',
    rate: 0,
    type: 'none',
    affectsBoxes: {},
    reverseCharge: false,
    deductible: false,
    description: 'Transaktioner uden momsrelevans',
  },
};

/**
 * VAT period configuration based on SKAT requirements
 */
export const VAT_PERIODICITET_CONFIG: Record<VATPeriodicitet, VATPeriodicitetConfig> = {
  monthly: {
    type: 'monthly',
    nameDanish: 'Maanedlig',
    nameEnglish: 'Monthly',
    deadlineDaysAfterPeriod: 25, // 25th of following month
    periodsPerYear: 12,
    threshold: { min: 50000000 }, // >50M DKK/year
  },
  quarterly: {
    type: 'quarterly',
    nameDanish: 'Kvartalsvis',
    nameEnglish: 'Quarterly',
    deadlineDaysAfterPeriod: 40, // ~40 days after quarter end (1st of 2nd month)
    periodsPerYear: 4,
    threshold: { min: 1000000, max: 50000000 }, // 1M-50M DKK/year
  },
  'half-yearly': {
    type: 'half-yearly',
    nameDanish: 'Halvaarslig',
    nameEnglish: 'Half-yearly',
    deadlineDaysAfterPeriod: 60, // ~2 months after period
    periodsPerYear: 2,
    threshold: { min: 300000, max: 1000000 }, // 300K-1M DKK/year
  },
  yearly: {
    type: 'yearly',
    nameDanish: 'Aarslig',
    nameEnglish: 'Yearly',
    deadlineDaysAfterPeriod: 90, // March 1st for calendar year
    periodsPerYear: 1,
    threshold: { max: 300000 }, // <300K DKK/year
  },
};

/**
 * SKAT VAT box definitions
 */
export const SKAT_VAT_BOXES: Record<VATBoxId | BasisBoxId, SKATVATBox> = {
  // VAT amounts (Momsbeloeb)
  A: {
    id: 'A',
    type: 'vat',
    nameDanish: 'Salgsmoms',
    nameEnglish: 'Output VAT (sales)',
    description: 'Moms af varer og ydelser solgt i Danmark (25%)',
    skippable: false,
    isDeductible: false,
  },
  B: {
    id: 'B',
    type: 'vat',
    nameDanish: 'Koebsmoms',
    nameEnglish: 'Input VAT (purchases)',
    description: 'Fradragsberettiget moms af koeb',
    skippable: false,
    isDeductible: true,
  },
  C: {
    id: 'C',
    type: 'vat',
    nameDanish: 'Moms af EU-varekoeb',
    nameEnglish: 'VAT on EU goods purchases',
    description: 'Erhvervelsesmoms ved koeb af varer fra andre EU-lande',
    skippable: true,
    isDeductible: false, // Listed as output, but can be deducted via B
  },
  D: {
    id: 'D',
    type: 'vat',
    nameDanish: 'Moms af ydelseskoeb fra udland',
    nameEnglish: 'VAT on foreign services',
    description: 'Moms ved koeb af ydelser fra udlandet med omvendt betalingspligt',
    skippable: true,
    isDeductible: false,
  },
  // Basis/turnover amounts (Omsaetning)
  '1': {
    id: '1',
    type: 'basis',
    nameDanish: 'Salg med moms',
    nameEnglish: 'Sales with VAT',
    description: 'Vaerdi af varer og ydelser solgt med dansk moms (momsgrundlag)',
    skippable: false,
    isDeductible: false,
  },
  '2': {
    id: '2',
    type: 'basis',
    nameDanish: 'Salg uden moms',
    nameEnglish: 'Sales without VAT',
    description: 'Momsfrit salg og eksport',
    skippable: true,
    isDeductible: false,
  },
  '3': {
    id: '3',
    type: 'basis',
    nameDanish: 'EU-varekoeb',
    nameEnglish: 'EU goods purchases',
    description: 'Vaerdi af varer koebt fra andre EU-lande',
    skippable: true,
    isDeductible: false,
  },
  '4': {
    id: '4',
    type: 'basis',
    nameDanish: 'Ydelseskoeb fra udland',
    nameEnglish: 'Foreign services purchases',
    description: 'Vaerdi af ydelser koebt fra udlandet',
    skippable: true,
    isDeductible: false,
  },
};

/**
 * Default VAT accounts for automatic double-entry
 */
export const VAT_ACCOUNTS = {
  inputVAT: '5610',    // Indgaaende moms (fradrag)
  outputVAT: '5710',   // Udgaaende moms (skyld)
  euVAT: '5620',       // EU-moms (erhvervelsesmoms)
} as const;

// =====================================================
// HELPER FUNCTIONS
// =====================================================

/**
 * Valid VAT code values for validation
 */
export const VALID_VAT_CODES: readonly VATCode[] = [
  'S25', 'K25', 'EU_VARE', 'EU_YDELSE', 'MOMSFRI', 'EKSPORT', 'NONE'
] as const;

/**
 * Check if a value is a valid VAT code
 */
export function isValidVATCode(code: unknown): code is VATCode {
  return typeof code === 'string' && VALID_VAT_CODES.includes(code as VATCode);
}

/**
 * Safely convert a string to VATCode, returns 'NONE' if invalid
 */
export function toVATCode(code: unknown): VATCode {
  return isValidVATCode(code) ? code : 'NONE';
}

/**
 * Get VAT code configuration
 */
export function getVATCodeConfig(code: VATCode): VATCodeConfig {
  return VAT_CODE_CONFIG[code];
}

/**
 * Get all VAT codes for a dropdown
 */
export function getVATCodeOptions(): Array<{ value: VATCode; label: string; description: string }> {
  return Object.values(VAT_CODE_CONFIG).map((config) => ({
    value: config.code,
    label: `${config.code} - ${config.nameDanish}`,
    description: config.description,
  }));
}

/**
 * Get VAT codes for expense transactions (input VAT)
 */
export function getExpenseVATCodeOptions(): Array<{ value: VATCode; label: string }> {
  return Object.values(VAT_CODE_CONFIG)
    .filter((config) => config.type === 'input' || config.type === 'reverse_charge' || config.type === 'none')
    .map((config) => ({
      value: config.code,
      label: `${config.code} - ${config.nameDanish}`,
    }));
}

/**
 * Get VAT codes for income transactions (output VAT)
 */
export function getIncomeVATCodeOptions(): Array<{ value: VATCode; label: string }> {
  return Object.values(VAT_CODE_CONFIG)
    .filter((config) => config.type === 'output' || config.type === 'exempt' || config.type === 'none')
    .map((config) => ({
      value: config.code,
      label: `${config.code} - ${config.nameDanish}`,
    }));
}

/**
 * Get period options for a dropdown
 */
export function getPeriodicitetOptions(): Array<{ value: VATPeriodicitet; label: string; description: string }> {
  return Object.values(VAT_PERIODICITET_CONFIG).map((config) => ({
    value: config.type,
    label: config.nameDanish,
    description: config.threshold?.min
      ? `Omsaetning over ${(config.threshold.min / 1000000).toFixed(0)}M DKK`
      : config.threshold?.max
        ? `Omsaetning under ${(config.threshold.max / 1000000).toFixed(1)}M DKK`
        : 'Standard',
  }));
}

/**
 * Get SKAT box definition
 */
export function getSKATBox(boxId: VATBoxId | BasisBoxId): SKATVATBox {
  return SKAT_VAT_BOXES[boxId];
}

/**
 * Check if a VAT code is deductible (affects input VAT)
 */
export function isVATDeductible(code: VATCode): boolean {
  return VAT_CODE_CONFIG[code].deductible;
}

/**
 * Check if a VAT code is reverse charge
 */
export function isReverseCharge(code: VATCode): boolean {
  return VAT_CODE_CONFIG[code].reverseCharge;
}

/**
 * Get VAT rate for a code
 */
export function getVATRate(code: VATCode): number {
  return VAT_CODE_CONFIG[code].rate;
}

/**
 * Calculate VAT from gross amount
 * Note: Rounds net first, then calculates VAT as gross - net
 * This ensures net + vat = gross (no floating point drift)
 */
export function calculateVATFromGross(grossAmount: number, rate: number): { net: number; vat: number } {
  if (rate === 0) {
    return { net: grossAmount, vat: 0 };
  }
  const rawNet = grossAmount / (1 + rate);
  const net = Math.round(rawNet * 100) / 100;
  // Calculate VAT as difference to guarantee gross = net + vat
  const vat = Math.round((grossAmount - net) * 100) / 100;
  return { net, vat };
}

/**
 * Calculate VAT from net amount
 * Note: Rounds VAT first, then calculates gross as net + vat
 * This ensures net + vat = gross (no floating point drift)
 */
export function calculateVATFromNet(netAmount: number, rate: number): { gross: number; vat: number } {
  if (rate === 0) {
    return { gross: netAmount, vat: 0 };
  }
  const rawVat = netAmount * rate;
  const vat = Math.round(rawVat * 100) / 100;
  // Calculate gross as sum to guarantee net + vat = gross
  const gross = Math.round((netAmount + vat) * 100) / 100;
  return { gross, vat };
}
