# Passerelle - uniform access to data and services
# Copyright (C) 2015  Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import datetime


def build_message(data):
    message = {}
    fields = data['fields']
    wf = data['workflow']['data']

    date_completude = datetime.date.today().strftime('%Y-%m-%d')

    if 'numero' in fields:
        statut_demande = 2
    else:
        statut_demande = 1

    try:
        aide_ccas = (fields.get('aide_ccas') or '').strip().upper().startswith('OUI')
    except Exception:
        aide_ccas = True

    protection = get_protection(fields, wf)
    if protection:
        message['MesureProtection'] = protection

    demandeur = get_demandeur(fields, wf)
    if demandeur:
        message['Demandeur'] = demandeur

    message['Beneficiaire'] = get_beneficiaire(fields, wf)

    beneficiaire_situation = message['Beneficiaire']['situationFamiliale']

    conjoint = get_conjoint(fields, wf, beneficiaire_situation)
    if conjoint:
        message['Conjoint'] = conjoint

    revenus = get_revenu(fields, wf)
    if revenus:
        message['RevenusImposition'] = revenus

    message['InformationsBancaires'] = get_info_bancaire(fields, wf)
    message['Patrimoine'] = get_patrimoine(fields, wf)

    etablissement, dummy = get_etablissement(fields, wf)

    demande_apa = {
        'statutDemande': statut_demande,
        'dateDepot': data['receipt_time'][0:10],
        'dateArrivee': data['receipt_time'][0:10],
        'dateCompletude': date_completude,
    }

    demande_apa_nomenclature = (
        {'codeNature': 1, 'codeType': 68} if etablissement else {'codeNature': 2, 'codeType': 70}
    )

    demande_apa['Nomenclature'] = demande_apa_nomenclature

    demande_apa['codeLieuDepot'] = 8 if aide_ccas else 7

    message['DemandeApa'] = demande_apa

    return message


def get_protection(fields, wf):
    protection_type = (
        wf.get('supp2_var_typeprotectionorga')
        or fields.get('typeprotectionorga')
        or fields.get('typeprotectionpers')
    )
    if protection_type:
        protection_type = protection_type.strip().upper()
        if 'TUTELLE' in protection_type:
            protection_type = 4
        elif 'CURATELLE' in protection_type:
            protection_type = 3
        elif 'SAUVEGARDE' in protection_type:
            protection_type = 5
        else:
            protection_type = None
    else:
        protection_type = None

    protection_organisme = (
        wf.get('tutelle_var_organisme_raw')
        or wf.get('supp2_var_organisme_raw')
        or fields.get('papier_organisme_raw')
    )
    if protection_organisme:
        protection_organisme = protection_organisme.split('-')[1]
    else:
        protection_organisme = None

    message = {}

    if protection_organisme:
        message['indexOrganismeTutelle'] = protection_organisme
        message['codeTypeProtection'] = protection_type

    return message


def get_demandeur(fields, wf):

    protection = get_protection(fields, wf)
    protection_type = protection.get('codeTypeProtection', None)
    protection_organisme = protection.get('indexOrganismeTutelle', None)

    demandeur_profil = fields.get('profildemandeur') or ''
    demandeur_profil = demandeur_profil.strip().upper()

    if 'PERSONNE' in demandeur_profil:
        demandeur_profil = 'PERSONNE'
    elif 'PROCHE' in demandeur_profil:
        demandeur_profil = 'PROCHE'
    elif 'ORGANISME' in demandeur_profil:
        demandeur_profil = 'ORGANISME'
    else:
        demandeur_profil = 'BENEFICIAIRE'

    if demandeur_profil in ('PERSONNE', 'PROCHE'):
        demandeur_id = None

        demandeur_nom = wf.get('supp1_var_nomdemandeur') or fields.get('nomdemandeur') or ''
        demandeur_nom = demandeur_nom.strip().upper()

        demandeur_prenom = wf.get('supp1_var_prenomdemandeur') or fields.get('prenomdemandeur') or ''
        demandeur_prenom = demandeur_prenom.strip().upper()

        demandeur_civilite = wf.get('supp1_var_civilitedemandeur') or fields.get('civilitedemandeur') or ''
        demandeur_civilite = demandeur_civilite.strip().upper()
        if 'MONSIEUR' in demandeur_civilite:
            demandeur_sexe = 'H'
        else:
            demandeur_sexe = 'F'

        demandeur_tel = wf.get('supp1_var_teldemandeur') or fields.get('teldemandeur') or ''
        demandeur_email = wf.get('supp1_var_courrieldemandeur') or fields.get('courrieldemandeur') or ''

        message = {}

        if demandeur_id:
            message['indexParticulier'] = demandeur_id

        if protection_type is not None and protection_organisme is None:
            message['typeProtection'] = protection_type

        message.update(
            {
                'nom': demandeur_nom,
                'prenom': demandeur_prenom,
                'sexe': demandeur_sexe,
                'Adresse': {'codeDepartement': 14, 'codeCommune': 990, 'codeLieu': '9999'},
            }
        )

        contact = {'email': demandeur_email}

        if demandeur_tel:
            contact['telephone'] = demandeur_tel

        message['Contact'] = contact

        return message

    return None


def get_etablissement(fields, wf):
    etablissement = wf.get('etablissement_var_nometablissement_raw') or fields.get(
        'papier_nometablissement_raw'
    )
    if etablissement:
        etablissement = etablissement.split('-')[1]
        etablissement_date_entree = fields.get('date_etablissement') or ''
        etablissement_date_entree = etablissement_date_entree[0:10]
    else:
        etablissement = None
        etablissement_date_entree = None

    return (etablissement, etablissement_date_entree)


def get_beneficiaire(fields, wf):
    beneficiaire_id = None
    if not wf.get('homonymie_var_homonyme_new_user_raw'):
        beneficiaire_id = wf.get('homonymie_var_homonyme_force_id')
        if not beneficiaire_id:
            beneficiaire_id = wf.get('homonymie_var_homonyme_id_raw')

    beneficiaire_civilite = (
        wf.get('supp3_var_civilitebeneficiaire') or fields.get('civilitebeneficiaire') or ''
    )
    beneficiaire_civilite = beneficiaire_civilite.strip().upper()
    if 'MONSIEUR' in beneficiaire_civilite:
        beneficiaire_sexe = 'H'
    else:
        beneficiaire_sexe = 'F'

    beneficiaire_nom = wf.get('supp3_var_nombeneficiaire') or fields.get('nombeneficiaire') or ''
    beneficiaire_nom = beneficiaire_nom.strip().upper()

    beneficiaire_nomnaissance = wf.get('supp3_var_nomdenaissance') or fields.get('nomdenaissance') or ''
    beneficiaire_nomnaissance = beneficiaire_nomnaissance.strip().upper()
    if beneficiaire_nomnaissance == '':
        beneficiaire_nomnaissance = None

    beneficiaire_prenom = wf.get('supp3_var_prenombeneficiaire') or fields.get('prenombeneficiaire') or ''
    beneficiaire_prenom = beneficiaire_prenom.strip().upper()

    beneficiaire_dn = wf.get('supp3_var_dnnbeneficiaire_raw') or fields.get('dnnbeneficiaire') or ''
    beneficiaire_dn = beneficiaire_dn[0:10]

    beneficiaire_ln = wf.get('supp3_var_lieunbeneficiaire') or fields.get('lieunbeneficiaire') or ''
    beneficiaire_ln = beneficiaire_ln.strip().upper()

    beneficiaire_nationalite = (
        wf.get('supp3_var_nationalitebeneficiaire') or fields.get('nationalitebeneficiaire') or 'NATIONAL'
    )
    beneficiaire_nationalite = beneficiaire_nationalite.strip().upper()
    if 'NATIONAL' in beneficiaire_nationalite:
        beneficiaire_nationalite = 1
    elif 'RESSORTISSANT' in beneficiaire_nationalite:
        beneficiaire_nationalite = 2
    else:
        beneficiaire_nationalite = 3

    beneficiaire_situation = (
        wf.get('supp3_var_situationfamillebeneficiaire') or fields.get('situationfamillebeneficiaire') or ''
    )
    beneficiaire_situation = beneficiaire_situation.strip().upper()
    if 'MARI' in beneficiaire_situation:
        beneficiaire_situation = 2
    elif 'DIVOR' in beneficiaire_situation:
        beneficiaire_situation = 5
    elif 'VEUF' in beneficiaire_situation:
        beneficiaire_situation = 3
    elif 'CONCUB' in beneficiaire_situation:
        beneficiaire_situation = 7
    elif 'PACS' in beneficiaire_situation:
        beneficiaire_situation = 8
    else:
        beneficiaire_situation = 1  # celibataire

    beneficiaire_tel = wf.get('supp3_var_telbeneficiaire') or fields.get('telbeneficiaire') or ''
    beneficiaire_email = wf.get('supp3_var_courrielbeneficiaire') or fields.get('courrielbeneficiaire') or ''

    beneficiaire_code_commune_raw = (
        wf.get('adresse_var_code_commune_raw')
        or fields.get('papier_excode_commune_raw')
        or fields.get('papier_code_commune_raw')
        or 'commune-0-0'
    )
    beneficiaire_code_commune = beneficiaire_code_commune_raw.split('-')[2]
    beneficiaire_code_departement = beneficiaire_code_commune_raw.split('-')[1]
    beneficiaire_numero_lieu = (
        wf.get('adresse_var_num_lieu') or fields.get('papier_exnum_lieu') or fields.get('papier_num_lieu')
    )
    beneficiaire_code_lieu = (
        wf.get('adresse_var_code_lieu_raw')
        or fields.get('papier_excode_lieu_raw')
        or fields.get('papier_code_lieu_raw')
    )

    beneficiaire_retraite = (
        wf.get('supp3_var_retraitebeneficiaire') or fields.get('retraitebeneficiaire') or ''
    )
    beneficiaire_retraite = beneficiaire_retraite.strip().upper()
    beneficiaire_retraite = 'OUI' in beneficiaire_retraite

    if beneficiaire_retraite:
        info = (
            wf.get('supp3_var_regretraitebeneficiaire_raw')
            or wf.get('retraite_var_listeretraite_raw')
            or fields.get('papier_listeretraite_raw')
            or 'organisme_retraite-0'
        )
        beneficiaire_retraite_code = info.split('-')[1]

    message = {}

    if beneficiaire_id:
        message['indexIndividu'] = beneficiaire_id

    message.update({'nom': beneficiaire_nom, 'prenom': beneficiaire_prenom})

    if beneficiaire_nomnaissance:
        message['nomJeuneFille'] = beneficiaire_nomnaissance

    message.update({'sexe': beneficiaire_sexe, 'dateNaissance': beneficiaire_dn})

    if beneficiaire_ln:
        message['lieuNaissance'] = beneficiaire_ln

    message.update({'nationalite': beneficiaire_nationalite, 'situationFamiliale': beneficiaire_situation})

    if beneficiaire_tel or beneficiaire_email:
        contact = {}

        if beneficiaire_tel:
            contact['telephone'] = beneficiaire_tel

        if beneficiaire_email:
            contact['email'] = beneficiaire_email

        message['Contact'] = contact

    etablissement, etablissement_date_entree = get_etablissement(fields, wf)

    if etablissement:
        message.update(
            {
                'indexEtablissementAccueil': int(etablissement),
                'dateInstallBeneficiaire': etablissement_date_entree,
            }
        )

    if beneficiaire_retraite:
        message.update(
            {
                'Retraite': {
                    'codeOrganismeRetraite': int(beneficiaire_retraite_code),
                    'periodicite': 4,
                    'Nomenclature': {'indexFamille': 7, 'indexNature': 2},
                }
            }
        )

    adresse = {
        'codeCommune': int(beneficiaire_code_commune),
        'codeDepartement': int(beneficiaire_code_departement),
    }

    if beneficiaire_numero_lieu:
        adresse['numeroLieu'] = beneficiaire_numero_lieu

    adresse['codeLieu'] = beneficiaire_code_lieu

    message['Adresse'] = adresse

    return message


def get_conjoint(fields, wf, beneficiaire_situation):
    conjoint_id = None
    if not wf.get('homonymie_conjoint_var_homonyme_new_user_raw'):
        conjoint_id = wf.get('homonymie_conjoint_var_homonyme_force_id')
        if not conjoint_id:
            conjoint_id = wf.get('homonymie_conjoint_var_homonyme_id_raw')

    conjoint_civilite = wf.get('supp5_var_civiliteconjoint') or fields.get('civiliteconjoint') or ''
    conjoint_civilite = conjoint_civilite.strip().upper()
    if 'MONSIEUR' in conjoint_civilite:
        conjoint_sexe = 'H'
    else:
        conjoint_sexe = 'F'

    conjoint_nom = wf.get('supp5_var_nomconjoint') or fields.get('nomconjoint') or ''
    conjoint_nom = conjoint_nom.strip().upper()
    if conjoint_nom == '':
        conjoint_nom = None

    conjoint_nomnaissance = (
        wf.get('supp5_var_nomnaissanceconjoint') or fields.get('nomnaissanceconjoint') or ''
    )
    conjoint_nomnaissance = conjoint_nomnaissance.strip().upper()
    if conjoint_nomnaissance == '':
        conjoint_nomnaissance = None

    conjoint_prenom = wf.get('supp5_var_prenomconjoint') or fields.get('prenomconjoint') or ''
    conjoint_prenom = conjoint_prenom.strip().upper()

    conjoint_dn = wf.get('supp5_var_dnnconjoint_raw') or fields.get('dnnconjoint') or ''
    conjoint_dn = conjoint_dn[0:10]

    conjoint_participation = (
        wf.get('supp5_var_participationconjoint') or fields.get('participationconjoint') or 'NON'
    )
    conjoint_participation = 'OUI' in conjoint_participation.strip().upper()

    if not conjoint_nom:
        return None

    message = {}

    if conjoint_id:
        message['indexIndividu'] = conjoint_id

    message.update(
        {
            'nom': conjoint_nom,
            'prenom': conjoint_prenom,
        }
    )

    if conjoint_nomnaissance:
        message['nomJeuneFille'] = conjoint_nomnaissance

    message.update(
        {
            'dateNaissance': conjoint_dn,
            'sexe': conjoint_sexe,
            'bParticipeRevenus': conjoint_participation,
            'situationFamiliale': beneficiaire_situation,
        }
    )

    return message


def get_revenu(fields, wf):
    salaire = wf.get('supp6_var_revenuSalaire') or fields.get('revenuSalaire')
    try:
        salaire = float(salaire)
    except Exception:
        salaire = 0.0
    retraite = wf.get('supp6_var_revenuRetraite') or fields.get('revenuRetraite')
    try:
        retraite = float(retraite)
    except Exception:
        retraite = 0.0
    revenus = salaire + retraite
    revenus_annee = wf.get('supp6_var_anneerefrevenu') or fields.get('anneerefrevenu')

    conjoint_participation = (
        wf.get('supp5_var_participationconjoint') or fields.get('participationconjoint') or 'NON'
    )
    conjoint_participation = 'OUI' in conjoint_participation.strip().upper()

    if conjoint_participation:
        salaire = wf.get('supp6_var_revenuSalaireConjoint') or fields.get('revenuSalaireConjoint')
        try:
            salaire = float(salaire)
        except Exception:
            salaire = 0.0
        retraite = wf.get('supp6_var_revenuRetraiteConjoint') or fields.get('revenuRetraiteConjoint')
        try:
            retraite = float(retraite)
        except Exception:
            retraite = 0.0
        revenus = revenus + salaire + retraite

    if not revenus_annee:
        return None

    message = {'anneeReference': int(revenus_annee), 'revenuReference': revenus}

    return message


def get_info_bancaire(fields, wf):
    banque_titulaire = wf.get('supp8_var_titulairecompte') or fields.get('titulairecompte')
    banque_domiciliation = wf.get('supp8_var_domicilebanque') or fields.get('domicilebanque')
    banque_codebanque = wf.get('supp8_var_codebanque') or fields.get('codebanque')
    banque_codeguichet = wf.get('supp8_var_codeguichet') or fields.get('codeguichet')
    banque_numero = wf.get('supp8_var_numcompte') or fields.get('numcompte')
    banque_cle = wf.get('supp8_var_clerib') or fields.get('clerib')

    return {
        "titulaireCompte": banque_titulaire,
        "domiciliation": banque_domiciliation,
        "codeBanque": banque_codebanque,
        "codeGuichet": banque_codeguichet,
        "numeroCompte": banque_numero,
        "cleRib": banque_cle,
        "modeReglement": 1,
    }


def get_patrimoine(fields, wf):
    try:
        immobilier_bati = float(wf.get('supp7_var_bienbatis') or fields.get('bienbatis'))
    except Exception:
        immobilier_bati = 0.0

    try:
        immobilier_non_bati = float(wf.get('supp7_var_biennonbatis') or fields.get('biennonbatis'))
    except Exception:
        immobilier_non_bati = 0.0

    try:
        prelevements = float(wf.get('supp6_var_revenuPrelevement') or fields.get('revenuPrelevement'))
    except Exception:
        prelevements = 0.0
    try:
        prelevements = prelevements + float(
            wf.get('supp6_var_revenuPrelevementConjoint') or fields.get('revenuPrelevementConjoint')
        )
    except Exception:
        pass

    try:
        fonciers = float(wf.get('supp6_var_revenuFoncier') or fields.get('revenuFoncier'))
    except Exception:
        fonciers = 0.0
    try:
        fonciers = fonciers + float(
            wf.get('supp6_var_revenuFoncierConjoint') or fields.get('revenuFoncierConjoint', 0.0)
        )
    except Exception:
        pass
    fonciers_annee = wf.get('supp7_var_anneefoncier') or fields.get('anneefoncier')

    revenus_annee = wf.get('supp6_var_anneerefrevenu') or fields.get('anneerefrevenu')

    message = []

    if immobilier_bati > 0 and revenus_annee:
        message.append(
            {
                "Nomenclature": {"indexFamille": 2, "indexNature": 1},
                "anneeReference": int(revenus_annee),
                "valeurPrelevement": immobilier_bati,
            }
        )

    if immobilier_non_bati > 0 and revenus_annee:
        message.append(
            {
                "Nomenclature": {"indexFamille": 2, "indexNature": 2},
                "anneeReference": int(revenus_annee),
                "valeurPrelevement": immobilier_non_bati,
            }
        )

    if prelevements > 0 and revenus_annee:
        message.append(
            {
                "Nomenclature": {"indexFamille": 3, "indexNature": 1},
                "anneeReference": int(revenus_annee),
                "valeurPrelevement": prelevements,
            }
        )

    if fonciers > 0 and fonciers_annee:
        message.append(
            {
                "Nomenclature": {"indexFamille": 4, "indexNature": 1},
                "anneeReference": int(fonciers_annee),
                "valeurPrelevement": fonciers,
            }
        )

    return message
