import { describe, it, expect } from 'vitest'
import {
    buildSupplierFormTabKeys,
    hasAtLeastOneValidContact,
    isAddressValid,
    isBankRequiredForPaymentType,
    isBlankRow,
    isContactBlank,
    isContactNamed,
    isRibBlank,
    isRibComplete,
    isRibRequiredForPaymentType,
    lastFillableTabKey,
    omitEmptyRequired,
    type AddressValidityDraft,
    type ContactDraft,
    type ContactFillableDraft,
} from '../supplierFormRules'

/** Bloc contact totalement vide (amorce par defaut). */
function blankContact(): ContactFillableDraft {
    return {
        firstName: null,
        lastName: null,
        jobTitle: null,
        phonePrimary: null,
        phoneSecondary: null,
        email: null,
    }
}

describe('buildSupplierFormTabKeys (gating onglet Comptabilite + onglets edit-only)', () => {
    it('inclut l onglet accounting si l utilisateur a accounting.view', () => {
        expect(buildSupplierFormTabKeys(true)).toContain('accounting')
    })

    it('exclut l onglet accounting sinon (Bureau / Commerciale)', () => {
        expect(buildSupplierFormTabKeys(false)).not.toContain('accounting')
    })

    it('a la creation, ordre = information / contacts / addresses / transport (+ accounting si vu)', () => {
        expect(buildSupplierFormTabKeys(true)).toEqual(['information', 'contacts', 'addresses', 'transport', 'accounting'])
        expect(buildSupplierFormTabKeys(false)).toEqual(['information', 'contacts', 'addresses', 'transport'])
    })

    it('a la creation, exclut Statistiques / Rapports / Echanges', () => {
        const keys = buildSupplierFormTabKeys(true)
        expect(keys).not.toContain('statistics')
        expect(keys).not.toContain('reports')
        expect(keys).not.toContain('exchanges')
    })

    it('en modification (includeEditOnlyTabs), ajoute les onglets edit-only en fin', () => {
        expect(buildSupplierFormTabKeys(true, { includeEditOnlyTabs: true })).toEqual([
            'information', 'contacts', 'addresses', 'transport', 'accounting', 'statistics', 'reports', 'exchanges',
        ])
    })
})

describe('lastFillableTabKey (redirection fin d\'ajout, role-aware)', () => {
    it('addresses pour un role sans Comptabilite (Bureau / Commerciale)', () => {
        expect(lastFillableTabKey(buildSupplierFormTabKeys(false))).toBe('addresses')
    })

    it('accounting pour un role avec accounting.view (Admin)', () => {
        expect(lastFillableTabKey(buildSupplierFormTabKeys(true))).toBe('accounting')
    })

    it('ignore les onglets placeholder (Transport en dernier ne compte pas)', () => {
        expect(lastFillableTabKey(['information', 'contacts', 'addresses', 'transport'])).toBe('addresses')
    })

    it('undefined si aucun onglet remplissable (que des placeholders)', () => {
        expect(lastFillableTabKey(['transport', 'statistics'])).toBeUndefined()
    })
})

describe('isContactNamed (RG-2.04)', () => {
    it('vrai si le prenom ou le nom est renseigne', () => {
        expect(isContactNamed({ firstName: 'Alice', lastName: null })).toBe(true)
        expect(isContactNamed({ firstName: null, lastName: 'Martin' })).toBe(true)
    })

    it('faux si les deux sont vides ou espaces uniquement', () => {
        expect(isContactNamed({ firstName: null, lastName: null })).toBe(false)
        expect(isContactNamed({ firstName: '  ', lastName: '' })).toBe(false)
    })
})

describe('hasAtLeastOneValidContact (RG-2.13)', () => {
    it('faux sur une liste vide ou sans contact nomme', () => {
        expect(hasAtLeastOneValidContact([])).toBe(false)
        const contacts: ContactDraft[] = [{ firstName: null, lastName: null }, { firstName: '', lastName: '  ' }]
        expect(hasAtLeastOneValidContact(contacts)).toBe(false)
    })

    it('vrai des qu un contact a un nom ou un prenom', () => {
        expect(hasAtLeastOneValidContact([{ firstName: null, lastName: null }, { firstName: 'Bob', lastName: null }])).toBe(true)
    })
})

describe('isBlankRow / isContactBlank / isRibBlank (blocs vides vs partiels)', () => {
    it('isBlankRow vrai si toutes les valeurs sont vides', () => {
        expect(isBlankRow([null, undefined, '', '  '])).toBe(true)
        expect(isBlankRow([null, 'x', ''])).toBe(false)
    })

    it('isContactBlank faux si un email seul est saisi (bloc a soumettre -> 422 RG-2.04 inline)', () => {
        expect(isContactBlank(blankContact())).toBe(true)
        expect(isContactBlank({ ...blankContact(), email: 'jean@acme.fr' })).toBe(false)
    })

    it('isRibBlank faux si un IBAN seul est saisi (bloc a soumettre -> 422 NotBlank inline)', () => {
        expect(isRibBlank({ label: null, bic: null, iban: null })).toBe(true)
        expect(isRibBlank({ label: null, bic: null, iban: 'FR1420041010050500013M02606' })).toBe(false)
    })
})

describe('isRibComplete (gating « + RIB » + RG-2.08)', () => {
    it('vrai quand label + BIC + IBAN sont remplis', () => {
        expect(isRibComplete({ label: 'Compte courant', bic: 'BNPAFRPP', iban: 'FR1420041010050500013M02606' })).toBe(true)
    })

    it('faux si un champ manque', () => {
        expect(isRibComplete({ label: null, bic: 'BNPAFRPP', iban: 'FR14...' })).toBe(false)
        expect(isRibComplete({ label: 'Compte', bic: '  ', iban: 'FR14...' })).toBe(false)
    })
})

describe('regles type de reglement (RG-2.07 / RG-2.08)', () => {
    it('banque obligatoire si VIREMENT', () => {
        expect(isBankRequiredForPaymentType('VIREMENT')).toBe(true)
        expect(isBankRequiredForPaymentType('LCR')).toBe(false)
        expect(isBankRequiredForPaymentType(null)).toBe(false)
    })

    it('RIB obligatoire si LCR', () => {
        expect(isRibRequiredForPaymentType('LCR')).toBe(true)
        expect(isRibRequiredForPaymentType('VIREMENT')).toBe(false)
        expect(isRibRequiredForPaymentType(null)).toBe(false)
    })
})

describe('isAddressValid (enum addressType, RG-2.06/2.09/2.10 ; pas d\'email facturation)', () => {
    function validAddress(): AddressValidityDraft {
        return {
            addressType: 'DEPART',
            categoryIris: ['/api/categories/1'],
            siteIris: ['/api/sites/1'],
        }
    }

    it('vrai quand type + >= 1 site + >= 1 categorie', () => {
        expect(isAddressValid(validAddress())).toBe(true)
    })

    it('faux si le type d\'adresse n\'est pas renseigne (amorce vierge)', () => {
        expect(isAddressValid({ ...validAddress(), addressType: null })).toBe(false)
    })

    it('faux si aucun site (RG-2.06)', () => {
        expect(isAddressValid({ ...validAddress(), siteIris: [] })).toBe(false)
    })

    it('faux si aucune categorie (RG-2.10)', () => {
        expect(isAddressValid({ ...validAddress(), categoryIris: [] })).toBe(false)
    })

    it('accepte les trois valeurs d\'enum PROSPECT / DEPART / RENDU', () => {
        for (const type of ['PROSPECT', 'DEPART', 'RENDU'] as const) {
            expect(isAddressValid({ ...validAddress(), addressType: type })).toBe(true)
        }
    })
})

describe('omitEmptyRequired (ERP-119 : 422 NotBlank au lieu de 400 de type)', () => {
    it('retire les cles requises vides et conserve le reste', () => {
        const payload = omitEmptyRequired(
            { companyName: null, sites: ['/api/sites/1'] },
            ['companyName'],
        )
        expect('companyName' in payload).toBe(false)
        expect(payload.sites).toEqual(['/api/sites/1'])
    })

    it('false / 0 ne sont pas consideres vides (booleens / nombres preserves)', () => {
        const payload = omitEmptyRequired({ triageProvider: false, bennes: 0 }, ['triageProvider', 'bennes'])
        expect(payload).toEqual({ triageProvider: false, bennes: 0 })
    })
})
