# -*- coding: utf-8 -*-
"""Importa skillLevel_Name.lod para dbo.skill: a descricao de cada skill, por nivel.

    python tools/importar_skills.py            mostra o que faria
    python tools/importar_skills.py --aplicar  grava

Este script nasceu de um erro: em 24/08 eu apaguei a tabela dbo.skill do banco e, logo
depois, os arquivos exportados que eram a unica copia. A tabela tinha sido importada a mao
numa sessao antiga, sem script -- por isso nao havia como refazer. Agora ha.

    [0:4]  cabecalho
    [4:8]  numero de registros (4656)
    depois, por registro:
        [+0:4]  skill_id
        [+4:8]  nivel
        [+8:12] tamanho do texto em bytes
        [+12:]  texto, em latin-1

ATENCAO ao modo de decifracao: este arquivo precisa de `pular_zero=False`. Com o modo
padrao ele sai com 37% de bytes legiveis e parece lixo; com False sai com 81%. E um dos
casos que o docstring de lod_crypto avisa.
"""
import os
import struct
import sys

sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "server"))
import lod_crypto                                                    # noqa: E402
import pyodbc                                                        # noqa: E402

LOD = r"C:\Games\Karos\ResUnpak\Interface\IE_Lod\skillLevel_Name.lod_pt"
CONEXAO = ("DRIVER={ODBC Driver 18 for SQL Server};SERVER=localhost;"
           "DATABASE=Rosh;Trusted_Connection=yes;TrustServerCertificate=yes")
DDL = """
IF OBJECT_ID('dbo.skill') IS NULL
CREATE TABLE dbo.skill (
    skill_id  int           NOT NULL,
    nivel     int           NOT NULL,
    descricao nvarchar(400) NULL
)
"""


def registros(d):
    n = struct.unpack_from("<I", d, 4)[0]
    pos = 8
    for _ in range(n):
        if pos + 12 > len(d):
            break
        sid, nivel, tam = struct.unpack_from("<3I", d, pos)
        pos += 12
        texto = d[pos:pos + tam].decode("latin-1", "replace")
        pos += tam
        yield sid, nivel, texto


def main() -> int:
    aplicar = "--aplicar" in sys.argv
    d = lod_crypto.decrypt_lod_stream(open(LOD, "rb").read(), pular_zero=False)
    esperado = struct.unpack_from("<I", d, 4)[0]
    linhas = list(registros(d))
    print("cabecalho diz %d registros; li %d" % (esperado, len(linhas)))
    if len(linhas) != esperado:
        print("AVISO: contagem nao bate -- o layout pode ter mudado")
    print("   niveis distintos: %d" % len({n for _, n, _ in linhas}))
    print("   exemplos:")
    for sid, nivel, texto in linhas[:4]:
        print("      %-6d nv%-3d %s" % (sid, nivel, texto[:58]))

    if not aplicar:
        print()
        print("nada gravado. rode com --aplicar")
        return 0

    c = pyodbc.connect(CONEXAO)
    u = c.cursor()
    u.execute(DDL)
    c.commit()
    u.execute("DELETE FROM dbo.skill")
    u.fast_executemany = True
    u.executemany("INSERT INTO dbo.skill (skill_id, nivel, descricao) VALUES (?,?,?)",
                  [(a, b, e[:400]) for a, b, e in linhas])
    c.commit()
    u.execute("SELECT COUNT(*) FROM dbo.skill")
    print()
    print("gravadas %d linhas em dbo.skill" % u.fetchone()[0])
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
