#!/usr/bin/env python3

from pathlib import Path
from datetime import date, timedelta, datetime
from urllib.request import urlopen
from fints.client import FinTS3PinTanClient
import csv
import json
import sys
import logging
import platform
from pathlib import Path

if platform.system() == "Windows":
    log_dir = Path(__file__).parent / "logs"
else:
    log_dir = Path.home() / "logs"

log_dir.mkdir(exist_ok=True)

log_file = log_dir / "ing.log"

logging.basicConfig(
    filename=log_file,
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    force=True
)

logging.info("[transactions] === Scriptstart ===")

# --------------------------------------------------
# Konfiguration laden
# --------------------------------------------------

config = {}

config_file = Path.home() / ".ing.conf"

if not config_file.exists():
    config_file = Path(__file__).parent / ".ing.conf"

with open(config_file, encoding="utf-8") as f:
    for line in f:
        line = line.strip()

        if not line or line.startswith("#"):
            continue

        if "=" not in line:
            continue

        key, value = line.split("=", 1)
        config[key] = value

# --------------------------------------------------
# ING-Konfiguration
# --------------------------------------------------

USER = config["ING_USER"]
PIN = config["ING_PIN"]
TARGET_IBAN = config["ING_IBAN"]

# --------------------------------------------------
# ioBroker-Konfiguration
# --------------------------------------------------

IOBROKER_HOST = config["IOBROKER_HOST"]
IOBROKER_PORT = config["IOBROKER_PORT"]

IOBROKER_DP_TRANSACTIONS = config["IOBROKER_DP_TRANSACTIONS"]
IOBROKER_DP_WEEKSUM = config["IOBROKER_DP_WEEKSUM"]
IOBROKER_DP_WEEKEXPENSES = config["IOBROKER_DP_WEEKEXPENSES"]

# --------------------------------------------------
# Bank
# --------------------------------------------------

BLZ = "50010517"

# --------------------------------------------------
# Exportverzeichnis bestimmen
# --------------------------------------------------

# --------------------------------------------------
# Exportverzeichnis bestimmen
# --------------------------------------------------

base_dir = Path(__file__).parent / "Transaktionen"
# --------------------------------------------------
# Kalenderwoche bestimmen
# --------------------------------------------------

if len(sys.argv) == 3:

    year = int(sys.argv[1])
    week = int(sys.argv[2])

else:

    year, week, _ = datetime.now().isocalendar()

# Montag der Kalenderwoche

start_date = datetime.strptime(
    f"{year}-W{week:02d}-1",
    "%G-W%V-%u"
).date()

# Sonntag der Kalenderwoche

end_date = start_date + timedelta(days=6)
today = date.today()

if end_date > today:
    end_date = today

if start_date > today:
    logging.error(
        "[transactions] Die angeforderte "
        "Kalenderwoche liegt vollständig "
        "in der Zukunft."
    )

    sys.exit(1)

year_dir = base_dir / str(year)
csv_dir = year_dir / "csv"
json_dir = year_dir / "json"

csv_dir.mkdir(parents=True, exist_ok=True)
json_dir.mkdir(parents=True, exist_ok=True)

CSV_FILE = csv_dir / f"transactions_{year}_KW{week:02d}.csv"
JSON_FILE = json_dir / f"transactions_{year}_KW{week:02d}.json"

# --------------------------------------------------
# ING-Verbindung
# --------------------------------------------------

client = FinTS3PinTanClient(
    BLZ,
    USER,
    PIN,
    "https://fints.ing.de/fints/",
    product_id="PythonFinTS"
)

export_data = []
transactions = []

# --------------------------------------------------
# Transaktionen abrufen
# --------------------------------------------------

with client:
    account_found = False

    for account in client.get_sepa_accounts():

        if account.iban != TARGET_IBAN:
            continue

        account_found = True

        transactions = client.get_transactions(
            account,
            start_date=start_date,
            end_date=end_date
        )

        logging.info(
            f"[transactions] Lade Transaktionen für KW{week:02d}/{year}"
        )

        logging.info(
            f"[transactions] Zeitraum: {start_date} bis {end_date}"
        )

        for transaction in transactions:

            data = transaction.data
            amount = data.get("amount")

            row = {
                "date": str(data.get("date", "")),
                "amount": round(float(amount.amount), 2) if amount else 0.0,
                "posting_text": data.get("posting_text", ""),
                "applicant_name": data.get("applicant_name", ""),
                "purpose": data.get("purpose", "")
            }

            export_data.append(row)

        break

    if not account_found:
        raise RuntimeError(
            f"IBAN nicht gefunden: {TARGET_IBAN}"
        )

# --------------------------------------------------
# CSV schreiben
# --------------------------------------------------

with open(CSV_FILE, "w", newline="", encoding="utf-8") as csvfile:

    writer = csv.DictWriter(
        csvfile,
        fieldnames=[
            "date",
            "amount",
            "posting_text",
            "applicant_name",
            "purpose"
        ],
        delimiter=";"
    )

    writer.writeheader()
    writer.writerows(export_data)

# --------------------------------------------------
# JSON schreiben
# --------------------------------------------------

with open(JSON_FILE, "w", encoding="utf-8") as jsonfile:

    json.dump(
        export_data,
        jsonfile,
        ensure_ascii=False,
        indent=2
    )

# --------------------------------------------------
# Statistiken berechnen
# --------------------------------------------------

transaction_count = len(export_data)

week_sum = 0.0
week_expenses = 0.0

for transaction in transactions:

    amount = float(transaction.data["amount"].amount)

    week_sum += amount

    if amount < 0:
        week_expenses += abs(amount)

week_sum = round(week_sum, 2)
week_expenses = round(week_expenses, 2)

# --------------------------------------------------
# An ioBroker senden
# --------------------------------------------------

base_url = f"http://{IOBROKER_HOST}:{IOBROKER_PORT}/set"

urlopen(
    f"{base_url}/{IOBROKER_DP_TRANSACTIONS}"
    f"?value={transaction_count}"
).read()

urlopen(
    f"{base_url}/{IOBROKER_DP_WEEKSUM}"
    f"?value={week_sum}"
).read()

urlopen(
    f"{base_url}/{IOBROKER_DP_WEEKEXPENSES}"
    f"?value={week_expenses}"
).read()

# --------------------------------------------------
# Erfolgsmeldung
# --------------------------------------------------

logging.info(
    f"[transactions] Export abgeschlossen | "
    f"Transaktionen={transaction_count} | "
    f"Wochensumme={week_sum:.2f} EUR | "
    f"Ausgaben={week_expenses:.2f} EUR"
)

logging.info(
    f"[transactions] CSV={CSV_FILE}"
)

logging.info(
    f"[transactions] JSON={JSON_FILE}"
)