package com.alexanderlogistics.migration;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.imixs.workflow.exceptions.PluginException;
import org.junit.Before;
import org.junit.Test;

import junit.framework.Assert;

public class MigrationMahnerDatev {

    List<String> doppelteBuchungen = new ArrayList<String>();
    List<String> rechnungsnummern = new ArrayList<String>();
    String WJ = "2022";

    @Before
    public void setup() throws PluginException {
        doppelteBuchungen = new ArrayList<String>();
        rechnungsnummern = new ArrayList<String>();
    }

    /**
     * Diese Test Method wandelt die Datei OPD_migration_230126.csv in eine EXTV
     * Datev Datei um, welche wir dann für einen einmaligen Import der
     * Rechnugnsdaten verwenden können.
     * 
     */
    @Test
    public void migriere() {

        System.out.println("***********************");
        System.out.println("* OP Listen Migration *");
        System.out.println("* Wirtschaftsjahr " + WJ + " *");
        System.out.println("***********************");

        String filename_input = "datev/OPD_migration_230126.csv";
        String filename_output = "src/test/resources/datev/EXTF_OPD_migration_" + WJ + ".csv";
        FileInputStream fis;
        BufferedReader br = null;
        try {
            ClassLoader classLoader = this.getClass().getClassLoader();
            File inputFile = new File(classLoader.getResource(filename_input).getFile());
            Assert.assertTrue(inputFile.exists());
            fis = new FileInputStream(inputFile);
            DataInputStream in = new DataInputStream(fis);
            br = new BufferedReader(new InputStreamReader(in, "ISO-8859-1"));

            // read the first line containing the field names
            String fieldnames = br.readLine();

            Assert.assertTrue(fieldnames.contains("Kontonummer"));

            // write output file...
            BufferedWriter writer = new BufferedWriter(new FileWriter(filename_output));
            writeEXTFHeader(writer,WJ);

            // Jetzt iterieren wir über die Input Datei und schreiben jeweilse eine Zeile
            // in die Output Datei...
            String line;
            int count = 0;
            int count2021 = 0;
            int count2022 = 0;
            int count2023 = 0;

            while ((line = br.readLine()) != null) {

                String[] data = line.split(";(?=([^\"]*\"[^\"]*\")*[^\"]*$)", 999);

                if (data.length != 90) {
                    System.out.println("Fehlerhafte Daten in Zeile " + count);
                    System.out.println(line);
                    Assert.fail();
                }

                String wj = data[3];
                wj = wj.substring(wj.length() - 4);
                if (wj.equals("2021")) {
                    count2021++;
                }
                if (wj.equals("2022")) {
                    count2022++;
                }
                if (wj.equals("2023")) {
                    count2023++;
                }

                // Nur einlesen falls das Wirtschfsjahr passt
                if (WJ.equals(wj)) {
                    writeOutputLine(writer, data, count);
                }
                count++;

//                if (count>25) {
//                    break;
//                }
            }

            writer.close();

            System.out.println("... fininshed - read " + count + " lines.");
            System.out.println("... wj 2021= " + count2021);
            System.out.println("... wj 2022= " + count2022);
            System.out.println("... wj 2023= " + count2023);

            System.out.println("... Besondere Buchungen :");
            for (String rgn : doppelteBuchungen) {
                System.out.println("      Rechnungs-Nr: " + rgn);
            }

        } catch (IOException e) {
            e.printStackTrace();
            Assert.fail();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    Assert.fail();
                }
            }
        }
    }

    /**
     * Hilfsmethode die einen DATEV Header schreibt
     * 
     * @param writer
     * @throws IOException
     */
    private void writeEXTFHeader(BufferedWriter writer,String wj) throws IOException {

        writer.write(
                "\"EXTF\";\"510\";21;\"Buchungsstapel\";7;\"20220721060421653\";\"\";\"CS\";\"cargoservice\";\"\";\"\";\"\";\"" + WJ  + "0101\";\"4\";\"" + WJ + "0101\";\"" + WJ + "1231\";\"202206ALL\";\"CS\";\"\";\"\";0;\"EUR\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\"");
        writer.newLine();
        writer.write(
                "Umsatz (ohne Soll-/Haben-Kennzeichen);Soll-Haben-Kennzeichen;WKZ Umsatz;Kurs;Basisumsatz;WKZ Basisumsatz;Konto;Gegenkonto;BU-Schlüssel;Belegdatum;Belegfeld 1;Belegfeld 2;Skonto;Buchungstext;Postensperre;Diverse Adressnummer;Geschäftspartnerbank;Sachverhalt;Zinssperre;Beleglink;Beleginfo-Art 1;Beleginfo-Inhalt 1;Beleginfo-Art 2;Beleginfo-Inhalt 2;Beleginfo-Art 3;Beleginfo-Inhalt 3;Beleginfo-Art 4;Beleginfo-Inhalt 4;Beleginfo-Art 5;Beleginfo-Inhalt 5;Beleginfo-Art 6;Beleginfo-Inhalt 6;Beleginfo-Art 7;Beleginfo-Inhalt 7;Beleginfo-Art 8;Beleginfo-Inhalt 8;KOST1-Kostenstelle;KOST2-Kostenstelle;KOST-Menge;EU-Mitgliedstaatu. USt-IdNr.;EU-Steuersatz;Abw. Versteuerungsart;Sachverhalt L+L;Funktionserg�nzung L+L;BU 49 Hauptfunktionstyp;BU 49 Hauptfunktionsnummer;BU 49 Funktionserg�nzung;Zusatzinformation-Art 1;Zusatzinformation-Inhalt 1;Zusatzinformation-Art 2;Zusatzinformation-Inhalt 2;Zusatzinformation-Art 3;Zusatzinformation-Inhalt 3;Zusatzinformation-Art 4;Zusatzinformation-Inhalt 4;Zusatzinformation-Art 5;Zusatzinformation-Inhalt 5;Zusatzinformation-Art 6;Zusatzinformation-Inhalt 6;Zusatzinformation-Art 7;Zusatzinformation-Inhalt 7;Zusatzinformation-Art 8;Zusatzinformation-Inhalt 8;Zusatzinformation-Art 9;Zusatzinformation-Inhalt 9;Zusatzinformation-Art 10;Zusatzinformation-Inhalt 10;Zusatzinformation-Art 11;Zusatzinformation-Inhalt 11;Zusatzinformation-Art 12;Zusatzinformation-Inhalt 12;Zusatzinformation-Art 13;Zusatzinformation-Inhalt 13;Zusatzinformation-Art 14;Zusatzinformation-Inhalt 14;Zusatzinformation-Art 15;Zusatzinformation-Inhalt 15;Zusatzinformation-Art 16;Zusatzinformation-Inhalt 16;Zusatzinformation-Art 17;Zusatzinformation-Inhalt 17;Zusatzinformation-Art 18;Zusatzinformation-Inhalt 18;Zusatzinformation-Art 19;Zusatzinformation-Inhalt 19;Zusatzinformation-Art 20;Zusatzinformation-Inhalt 20;St�ck;Gewicht;Zahlweise;Forderungsart;Veranlagungsjahr;Zugeordnete F�lligkeit;Skontotyp;Auftragsnummer;Buchungstyp;USt-Schl�ssel (Anzahlungen);EU-Mitgliedstaat (Anzahlungen);Sachverhalt L+L (Anzahlungen);EU-Steuersatz (Anzahlungen);Erlöskonto (Anzahlungen);Herkunft-Kz;Leerfeld;KOST-Datum;SEPAMandatsreferenz;Skontosperre;Gesellschaftername;Beteiligtennummer;Identifikationsnummer;Zeichnernummer;Postensperre bis;Bezeichnung SoBil-Sachverhalt;Kennzeichen SoBil-Buchung;Festschreibung;Leistungsdatum;Datum Zuord. Steuerperiode");
        writer.newLine();
    }

    /**
     * Schreibt eine einzelen Datenzeile
     * 
     * @param writer
     * @param data
     * @throws IOException
     */
    private void writeOutputLine(BufferedWriter writer, String[] data, int line) throws IOException {

        String rechnungsNummer = data[2];
        String rechnungsDatum=data[3];
        String faelligkeit=data[4];
        String saldo=data[7];
        String zahlung=data[6];
        // vertasuchen
        if (faelligkeit.length()==8) {
            faelligkeit=faelligkeit.substring(4,8)+faelligkeit.substring(2,4)+faelligkeit.substring(0,2);
        } else {
            faelligkeit="20230125";
        }
        String text=data[18];
        String basisumsatz = "0,00";
        String umsatz = data[5];
        if ("0,00".equals(umsatz)) {
            umsatz = data[6];
        }
        if ("0,00".equals(umsatz)) {
            System.out.println("ACHTUNG - Fehler in Spalte 5 bzw. 6 in zeile " + line);
        }
        String sh = data[8];

        String wkz = data[9];
        if (isEmpty(wkz)) {
            wkz = "\"EUR\"";
        } else {
            umsatz = data[10];
            basisumsatz = data[5];
            if ("0,00".equals(basisumsatz)) {
                basisumsatz = data[6];
            }

        }
        String kurs = data[11];

        String gegenkonto = data[0];
        String konto = data[12];

        boolean skip=false;
        if (rechnungsnummern.contains(rechnungsNummer)) {
            doppelteBuchungen.add(rechnungsNummer + "\tZahlung=" + zahlung + "\tSaldo="+saldo);
            skip=true;
        }
        rechnungsnummern.add(rechnungsNummer);
        if (skip) {
            return;
        }
        
        // umdrehen von sh
        if ("\"H\"".equals(sh)) {
            sh="\"S\"";
        } else {
            sh="\"H\"";
        }
        
        // umsätze
        writer.write(umsatz + ";" + sh + ";" + wkz + ";" + kurs + ";" + basisumsatz + ";");
        // wkz
        if (wkz.equals("\"EUR\"")) {
            writer.write(";");
        } else {
            writer.write("\"EUR\";");            
        }
        // konten
        writer.write(konto + ";" + gegenkonto + ";;");
        // datum und rechnungsnummer
        writer.write(rechnungsDatum.substring(0,4) + ";" + rechnungsNummer + ";;;"+text + ";0;;;0;;;;;Faelligkeit;"+faelligkeit+";");
        
        writer.write(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;");
        writer.newLine();
    }

    private boolean isEmpty(String data) {
        return (data.isEmpty() || "\"\"".equals(data));
    }

}
