"""
    gestion.odfviews, un module pour SLM
    - rendu d'information sous forme de document pour LibreOffice

    Copyright (C) 2023 Georges Khaznadar <georgesk@debian.org>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

from odf.opendocument import OpenDocumentSpreadsheet, OpenDocumentText
from odf.style import Style, ParagraphProperties, TableColumnProperties
from odf import style
from odf.text import H, P
from odf.table import Table, TableColumn, TableRow, TableCell

from io import BytesIO
from datetime import datetime

from django.http import FileResponse
from django.db.models import Count, Q
from django.views.decorators.csrf import ensure_csrf_cookie

from .models import Prets, Eleves, Classes, DATE111, Eleves_de_siecle, Caution
from .version import this_version

@ensure_csrf_cookie
def tableauSortantsPasAjour(request):
    """
    produit un fichier ODS avec des informations sur les élèves sortants,
    qui ne sont pas à jour pour rendre leurs livres prêtés.
    le POST contient un paramètre ids avec une liste d'identifiants d'élèves
    séparés par des virgules
    """
    ids = request.POST.get("ids").split(",")
    liste_eleves = Eleves.objects.filter(id__in = ids)
    fields_eleve = {
        "Nom_de_famille": "Nom de famille",
        "Prenom" : "Prénom",
        "Lib_Structure" : "Classe",
        "Tel_Portable" : "Téléphone portable",
        "Adresse" : "Adresse",
        "Nom_de_famille_Repr_Leg" : "Nom du représentant légal",
        "Prenom_Repr_Leg" : "Prénom du représentant légal",
        "Tel_Portable_Repr_Leg" : "Téléphone portable du représentant légal",
    }
    doc = OpenDocumentSpreadsheet()

    tablecontents = Style(name="Table Contents", family="paragraph")
    tablecontents.addElement(ParagraphProperties(
        numberlines="false", linenumber="0"))
    doc.styles.addElement(tablecontents)

    widthshort = Style(name="Wshort", family="table-column")
    widthshort.addElement(TableColumnProperties(columnwidth="1.7cm"))
    doc.automaticstyles.addElement(widthshort)

    widthwide = Style(name="Wwide", family="table-column")
    widthwide.addElement(TableColumnProperties(columnwidth="3.8cm"))
    doc.automaticstyles.addElement(widthwide)

    table = Table(name="Eleves")
    table.addElement(TableColumn(
        numbercolumnsrepeated=2+len(fields_eleve),stylename=widthshort))

    tr = TableRow()
    table.addElement(tr)
    for f in fields_eleve: # champs relatifs à l'élève
        tc = TableCell()
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=fields_eleve[f])
        tc.addElement(p)
        
    tc = TableCell() # nmuéro de caution
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Numéro de caution")
    tc.addElement(p)
    
    tc = TableCell() # caution non remboursée
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Caution non rendue")
    tc.addElement(p)
    
    tc = TableCell() # nombre de livres dus
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Nombre de livres non rendus")
    tc.addElement(p)

    tc = TableCell() # livres dus
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Livres non rendus")
    tc.addElement(p)

    for e in liste_eleves:
        # considérons tous les prêts à l'élève
        livres_non_rendus = Prets.objects.filter(eleve=e)
        try:
            caution_en_cours = Caution.objects.get(
                numero = e.no_caution).somme_payee
        except Exception as err:
            caution_en_cours = -1 # signe qu'il y a un bug !
        # retenons ceux qui ne sont pas encore rendus ni déclarés persus
        livres_non_rendus = livres_non_rendus.filter(
            ~Q(date_retour__gt = DATE111) &
            ~Q(Date_Declaration_Perte__gt = DATE111)
        )
        tr = TableRow()
        table.addElement(tr)
        for f in fields_eleve:
            tc = TableCell()
            tr.addElement(tc)
            p = P(stylename=tablecontents,text=str(getattr(e, f)))
            tc.addElement(p)

        # numéro de caution
        tc = TableCell(valuetype="float", value = e.no_caution)
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=str(e.no_caution))
        tc.addElement(p)
        
        # caution non rendue
        tc = TableCell(valuetype="float", value = caution_en_cours)
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=str(caution_en_cours))
        tc.addElement(p)
        
        # nombre de livres non rendus
        tc = TableCell(valuetype="float", value = len(livres_non_rendus))
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=str(len(livres_non_rendus)))
        tc.addElement(p)

        # titres des livres non rendus
        tc = TableCell()
        tr.addElement(tc)
        p = P(stylename=tablecontents,
              text=", ". \
              join([liv.inventaire.materiel.titre for liv in livres_non_rendus]))
        tc.addElement(p)
        

    doc.spreadsheet.addElement(table)
    buffer = BytesIO()
    doc.write(buffer)
    buffer.seek(0)
    return FileResponse(
        buffer,
        as_attachment=True,
        filename="Eleves_pas_a_jour.ods")

    

def listes_eleves_ODT(request):
    """
    Crée une liste des élèves éditable (format ODT) et imprimable.
    une page par classe (triées 2nde > 1ere > Term) avec le nom de la classe,
    la date d'impression, le nom du PP, le nom du CPE, et dans chaque page un
    tableau avec des lignes d'élèves (ordonnés alphabétiquement ; chaque ligne
    comprend un N° de coop, une case à cocher (pris des livres : oui/non),
    nom et prénom, liste succinte des options/spécialités
    """
    doc = OpenDocumentText()
    # Create a style for the paragraph with page-break
    withbreak = Style(
        name="WithBreak", parentstylename="Standard", family="paragraph")
    withbreak.addElement(ParagraphProperties(breakbefore="page"))
    doc.automaticstyles.addElement(withbreak)

    # styles de largeur pour tableau
    w1 = Style(name="W1", family="table-column")
    w1.addElement(TableColumnProperties(columnwidth="1cm"))
    doc.automaticstyles.addElement(w1)
    w2 = Style(name="W2", family="table-column")
    w2.addElement(TableColumnProperties(columnwidth="0.5cm"))
    doc.automaticstyles.addElement(w2)
    w3 = Style(name="W3", family="table-column")
    w3.addElement(TableColumnProperties(columnwidth="10cm"))
    doc.automaticstyles.addElement(w3)
    
    h1style = style.Style(name="Heading 1", family="paragraph")
    h1style.addElement(
        style.TextProperties(attributes={
            'fontsize': "24pt",
            'fontweight': "bold"
        }))
    doc.styles.addElement(h1style)

    boldstyle = style.Style(name="Bold", family="text")
    boldstyle.addElement(
        style.TextProperties(attributes={'fontweight': "bold"}))
    doc.automaticstyles.addElement(boldstyle)


    firstpage = True
    for classe in Classes.classes_importantes():
        timbre_date = f"Date : {datetime.now().strftime('%d/%m/%Y')} ; " + \
            f"imprimé par SLM, version {this_version}"
        if firstpage:
            p = P(text=timbre_date)
        else:
            p = P(stylename=withbreak, text=timbre_date)
        doc.text.addElement(p)
        doc.text.addElement(P(text = "PP :"))
        doc.text.addElement(P(text = "CPE :"))
        firstpage = False
        h = H(outlinelevel=1, stylename=h1style,
              text=f"Élèves de la {classe.libelle}")
        doc.text.addElement(h)
        table = Table()
        table.addElement(TableColumn(stylename=w1))
        table.addElement(TableColumn(stylename=w2))
        table.addElement(TableColumn(stylename=w3))
        doc.text.addElement(table)
        for eleve in Eleves.objects.annotate(
                num_prets=Count("prets")).filter(
                Lib_Structure = classe.libelle).order_by('NomPrenomEleve'):
            tr = TableRow()
            table.addElement(tr)
            
            tc = TableCell()
            tr.addElement(tc)
            p = P(text=str(eleve.no_caution if eleve.no_caution else '...'))
            tc.addElement(p)
            
            tc = TableCell()
            tr.addElement(tc)
            p = P(text="☐")
            tc.addElement(p)
            
            tc = TableCell()
            tr.addElement(tc)
            p = P(text=eleve.NomPrenomEleve)
            tc.addElement(p)

    buffer = BytesIO()
    doc.write(buffer)
    buffer.seek(0)
    return FileResponse(
        buffer,
        as_attachment=True,
        filename="Listes_eleves.odt")
    
@ensure_csrf_cookie
def print_eleves_sans_livres(request):
    """
    produit un fichier ODS avec des informations sur les élèves
    sans livres prêtés. Le POST peut apporter un paramètre "classe"
    """
    classe = request.POST.get("classe","")
    liste_sans_prets = Eleves.sans_prets_en_cours(classe)
    fields_eleve = {
        "Lib_Structure" : "Classe",
        "NomPrenomEleve": "Nom et prénom",
        "classes_passees": "Classes passées",
     }
    doc = OpenDocumentSpreadsheet()

    tablecontents = Style(name="Table Contents", family="paragraph")
    tablecontents.addElement(ParagraphProperties(
        numberlines="false", linenumber="0"))
    doc.styles.addElement(tablecontents)

    widthshort = Style(name="Wshort", family="table-column")
    widthshort.addElement(TableColumnProperties(columnwidth="1.7cm"))
    doc.automaticstyles.addElement(widthshort)

    widthwide = Style(name="Wwide", family="table-column")
    widthwide.addElement(TableColumnProperties(columnwidth="3.8cm"))
    doc.automaticstyles.addElement(widthwide)

    table = Table(name="Eleves")
    table.addElement(TableColumn(
        numbercolumnsrepeated=len(fields_eleve),stylename=widthwide))

    tr = TableRow()
    table.addElement(tr)
    for f in fields_eleve: # champs relatifs à l'élève
        tc = TableCell()
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=fields_eleve[f])
        tc.addElement(p)
        
    for e in liste_sans_prets:
        tr = TableRow()
        table.addElement(tr)
        for f in fields_eleve:
            tc = TableCell()
            tr.addElement(tc)
            p = P(stylename=tablecontents,text=str(getattr(e, f)))
            tc.addElement(p)
        

    doc.spreadsheet.addElement(table)
    buffer = BytesIO()
    doc.write(buffer)
    buffer.seek(0)
    filename = "Eleves_sans_livres"
    if classe:
        filename += "_" + classe
    filename += ".ods"
    return FileResponse(buffer, as_attachment=True, filename=filename)

@ensure_csrf_cookie
def print_eleves_avec_livres(request):
    """
    produit un fichier ODS avec des informations sur les élèves
    avec des livres prêtés. Le POST peut apporter un paramètre "classe"
    """
    classe = request.POST.get("classe","")
    liste_sans_prets = Eleves.avec_prets_en_cours(classe)
    fields_eleve = {
        "Lib_Structure" : "Classe",
        "NomPrenomEleve": "Nom et prénom",
        "classes_passees": "Classes passées",
     }
    doc = OpenDocumentSpreadsheet()

    tablecontents = Style(name="Table Contents", family="paragraph")
    tablecontents.addElement(ParagraphProperties(
        numberlines="false", linenumber="0"))
    doc.styles.addElement(tablecontents)

    widthshort = Style(name="Wshort", family="table-column")
    widthshort.addElement(TableColumnProperties(columnwidth="1.7cm"))
    doc.automaticstyles.addElement(widthshort)

    widthwide = Style(name="Wwide", family="table-column")
    widthwide.addElement(TableColumnProperties(columnwidth="3.8cm"))
    doc.automaticstyles.addElement(widthwide)

    table = Table(name="Eleves")
    table.addElement(TableColumn(
        numbercolumnsrepeated=1+len(fields_eleve),stylename=widthwide))

    tr = TableRow()
    table.addElement(tr)
    for f in fields_eleve: # champs relatifs à l'élève
        tc = TableCell()
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=fields_eleve[f])
        tc.addElement(p)

    # nombre de livres prêtés
    tc = TableCell()
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Livres prêtés")
    tc.addElement(p)
    
        
    for e in liste_sans_prets:
        tr = TableRow()
        table.addElement(tr)
        for f in fields_eleve:
            tc = TableCell()
            tr.addElement(tc)
            p = P(stylename=tablecontents,text=str(getattr(e, f)))
            tc.addElement(p)
        # nombre de livres prêtés
        tc = TableCell(valuetype="float", value=len(Prets.faits_a(e)))
        tr.addElement(tc)

    doc.spreadsheet.addElement(table)
    buffer = BytesIO()
    doc.write(buffer)
    buffer.seek(0)
    filename = "Eleves_avec_livres"
    if classe:
        filename += "_" + classe
    filename += ".ods"
    return FileResponse(buffer, as_attachment=True, filename=filename)

    
