#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import io

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')

import os
import json
import time
from datetime import date, timedelta
from pathlib import Path

import requests
import pymysql

# =========================================
# CONFIGURATION
# =========================================

ACCOUNTS_FILE = r"../accounts.json"
JSON_BASE_DIR = r"u:\Dropbox\!!!Days\Downloads Z230\Fio"

DB = {
    "host": "192.168.1.76",
    "port": 3306,
    "user": "root",
    "password": "Vlado9674+",
    "database": "fio",
    "charset": "utf8mb4",
}

BATCH_SIZE = 500
DAYS_BACK = 90

# =========================================
# HELPERS
# =========================================

def load_accounts(path):
    with open(path, "r", encoding="utf-8") as f:
        accounts = json.load(f)

    for acc in accounts:
        for key in ("name", "account_number", "token"):
            if key not in acc:
                raise ValueError(f"Missing '{key}' in account config: {acc}")

    return accounts


def fio_url_for_period(token, d_from, d_to):
    return f"https://fioapi.fio.cz/v1/rest/periods/{token}/{d_from:%Y-%m-%d}/{d_to:%Y-%m-%d}/transactions.json"


def fetch_fio_json(token, d_from, d_to):
    url = fio_url_for_period(token, d_from, d_to)
    resp = requests.get(url, timeout=30)

    if resp.status_code != 200:
        print(f"❌ HTTP {resp.status_code} from Fio")
        return None

    return resp.json()


def safe_col(t, n):
    val = t.get(f"column{n}")
    return None if not val else val.get("value")


def clean_date(dt_str):
    return None if not dt_str else dt_str[:10]


def ensure_dir(path):
    Path(path).mkdir(parents=True, exist_ok=True)


def save_json_for_account(base_dir, account_cfg, data, d_from, d_to):
    acc_folder = account_cfg["account_number"].replace("/", "_")
    out_dir = Path(base_dir) / acc_folder
    ensure_dir(out_dir)

    filename = f"{d_from:%Y-%m-%d}_to_{d_to:%Y-%m-%d}.json"
    out_path = out_dir / filename

    with open(out_path, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

    return out_path


# =========================================
# MAIN
# =========================================

def main():

    today = date.today()
    d_from = today - timedelta(days=DAYS_BACK)
    d_to = today

    print(f"=== Fio import {d_from} → {d_to} ===")

    accounts = load_accounts(ACCOUNTS_FILE)

    conn = pymysql.connect(**DB)
    cur = conn.cursor()

    sql = """
    INSERT INTO transactions
    (
        id_operace,
        cislo_uctu,
        transaction_date,
        amount,
        currency,
        protiucet,
        kod_banky,
        nazev_protiuctu,
        nazev_banky,
        typ,
        vs,
        ks,
        ss,
        zprava_pro_prijemce,
        uziv_identifikace,
        provedl,
        id_pokynu,
        komentar,
        upr_objem_mena,
        api_bic,
        reference_platce
    )
    VALUES
    (
        %(id_operace)s,
        %(cislo_uctu)s,
        %(transaction_date)s,
        %(amount)s,
        %(currency)s,
        %(protiucet)s,
        %(kod_banky)s,
        %(nazev_protiuctu)s,
        %(nazev_banky)s,
        %(typ)s,
        %(vs)s,
        %(ks)s,
        %(ss)s,
        %(zprava)s,
        %(uziv_identifikace)s,
        %(provedl)s,
        %(id_pokynu)s,
        %(komentar)s,
        %(upr_objem_mena)s,
        %(api_bic)s,
        %(reference_platce)s
    )
    ON DUPLICATE KEY UPDATE
        transaction_date = VALUES(transaction_date),
        amount = VALUES(amount),
        currency = VALUES(currency),
        protiucet = VALUES(protiucet),
        kod_banky = VALUES(kod_banky),
        nazev_protiuctu = VALUES(nazev_protiuctu),
        nazev_banky = VALUES(nazev_banky),
        typ = VALUES(typ),
        vs = VALUES(vs),
        ks = VALUES(ks),
        ss = VALUES(ss),
        zprava_pro_prijemce = VALUES(zprava_pro_prijemce),
        uziv_identifikace = VALUES(uziv_identifikace),
        provedl = VALUES(provedl),
        id_pokynu = VALUES(id_pokynu),
        komentar = VALUES(komentar),
        upr_objem_mena = VALUES(upr_objem_mena),
        api_bic = VALUES(api_bic),
        reference_platce = VALUES(reference_platce)
    """

    total_inserted = 0

    for acc in accounts:

        print(f"\n--- {acc['name']} ---")

        data = fetch_fio_json(acc["token"], d_from, d_to)
        if not data:
            continue

        save_json_for_account(JSON_BASE_DIR, acc, data, d_from, d_to)

        tlist = data["accountStatement"]["transactionList"].get("transaction", [])
        if isinstance(tlist, dict):
            tlist = [tlist]

        fio_acc_id = data["accountStatement"]["info"]["accountId"]

        rows = []

        for t in tlist:

            row = {
                "id_operace": safe_col(t, 22),
                "cislo_uctu": fio_acc_id,

                "transaction_date": clean_date(safe_col(t, 0)),
                "amount": safe_col(t, 1),
                "currency": safe_col(t, 14),

                "protiucet": safe_col(t, 2),
                "kod_banky": safe_col(t, 3),

                "nazev_protiuctu": safe_col(t, 10),
                "nazev_banky": safe_col(t, 15),

                "typ": safe_col(t, 8),

                "vs": safe_col(t, 5),
                "ks": safe_col(t, 4),
                "ss": safe_col(t, 6),

                "zprava": safe_col(t, 16),
                "uziv_identifikace": safe_col(t, 12),
                "provedl": safe_col(t, 12),

                "id_pokynu": safe_col(t, 19),
                "komentar": safe_col(t, 25),
                "upr_objem_mena": safe_col(t, 20),

                "api_bic": safe_col(t, 26),
                "reference_platce": safe_col(t, 27),
            }

            if row["id_operace"]:
                rows.append(row)

        inserted = 0

        for i in range(0, len(rows), BATCH_SIZE):
            chunk = rows[i:i+BATCH_SIZE]
            cur.executemany(sql, chunk)
            conn.commit()
            inserted += len(chunk)

        print(f"✓ Insert/Update: {inserted}")
        total_inserted += inserted

    cur.close()
    conn.close()

    print(f"\n=== DONE → {total_inserted} rows processed ===")


if __name__ == "__main__":
    main()
