# -*- coding: utf-8 -*-
"""Nạp bảng màu đọc từ trang mausac.ngoducminh.com vào CSDL B (CSDLB.db).
Bảng mới `mau_bang_in`: mỗi dòng = 1 ô màu trên bảng (nhóm DYE/PIGMENT, mã màu, nồng độ %,
màu đo được hex/RGB/Lab, tông màu AGY đọc, file ảnh + vị trí ô) + liên kết `mau_id` sang bảng `mau`.
Chạy: python _nap_bang_mau_web_vao_B.py            (xem trước)
      python _nap_bang_mau_web_vao_B.py --commit   (ghi thật, có backup)
"""
import csv, io, os, shutil, sqlite3, sys, unicodedata
from datetime import datetime
import numpy as np

B = r'C:\Claw 2\Nghien cuu\Du-an-B-He-mau-Stain-Glaze\CSDLB.db'
CSV = r'C:\Claw 2\Nghien cuu\Du-an-B-He-mau-Stain-Glaze\trang-mausac\_bang_mau_web_chot.csv'
URL = 'https://mausac.ngoducminh.com/danh-sach-mau.html'
NGAY = '06/10/2026'
COMMIT = '--commit' in sys.argv


def norm(s):
    s = unicodedata.normalize('NFD', (s or '').lower())
    s = ''.join(c for c in s if unicodedata.category(c) != 'Mn')
    return ''.join(c for c in s if c.isalnum())


rows = list(csv.DictReader(io.open(CSV, encoding='utf-8-sig')))
print('CSV:', len(rows), 'dòng | đo được màu:', sum(1 for r in rows if r['do_duoc'] == 'co'))
print('theo nhóm:', {k: sum(1 for r in rows if r['nhom'] == k) for k in sorted(set(r['nhom'] for r in rows))})

con = sqlite3.connect(B)
cur = con.cursor()
CREATE_SQL = """CREATE TABLE IF NOT EXISTS mau_bang_in (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    nhom TEXT, ma_mau TEXT, ma_khong_pc TEXT, nong_do INTEGER, hex TEXT,
    r_srgb INTEGER, g_srgb INTEGER, b_srgb INTEGER,
    L_star REAL, a_star REAL, b_star REAL,
    hex_agy TEXT, dE_hai_nguon REAL, do_tin_cay TEXT,
    file_anh TEXT, o TEXT, nhan_goc TEXT, tong_mau TEXT, do_duoc TEXT, cach_gan TEXT,
    mau_id INTEGER, nguon_url TEXT, ngay_tai TEXT, ghi_chu TEXT)"""
cur.execute(CREATE_SQL)

# --- đọc HEX do AGY đọc (nếu có) để đối chiếu ---
AGY_MD = r'C:\Claw 2\Nghien cuu\Du-an-B-He-mau-Stain-Glaze\trang-mausac\_agy_hex_tung_o.md'
hex_agy = {}
if os.path.exists(AGY_MD):
    import re as _re
    for line in io.open(AGY_MD, encoding='utf-8', errors='replace'):
        m = _re.search(r'([\w\-]+\.jpg)\s*\|\s*(\d+)\s*[-–]\s*(\d+)\s*\|(.+)$', line)
        if not m:
            continue
        body = m.group(4)
        h = _re.search(r'#([0-9A-Fa-f]{6})', body)
        hex_agy[(m.group(1), '%d-%d' % (int(m.group(2)), int(m.group(3))))] = ('#' + h.group(1).upper()) if h else None
    print('HEX AGY đọc được:', sum(1 for v in hex_agy.values() if v), '/', len(hex_agy))


def hex_to_lab(hx):
    hx = hx.lstrip('#')
    r, g, b = int(hx[0:2], 16), int(hx[2:4], 16), int(hx[4:6], 16)
    v = np.array([r, g, b], dtype=float) / 255.0
    v = np.where(v > 0.04045, ((v + 0.055) / 1.055) ** 2.4, v / 12.92)
    M = np.array([[0.4124564, 0.3575761, 0.1804375], [0.2126729, 0.7151522, 0.0721750], [0.0193339, 0.1191920, 0.9503041]])
    xyz = (M @ v) / np.array([0.95047, 1.0, 1.08883])
    f = np.where(xyz > 0.008856, np.cbrt(xyz), 7.787 * xyz + 16 / 116)
    return 116 * f[1] - 16, 500 * (f[0] - f[1]), 200 * (f[1] - f[2])

cur.execute('SELECT id, ma, ten FROM mau')
ds_mau = [(r[0], r[1], r[2]) for r in cur.fetchall()]
print('bảng mau:', len(ds_mau), 'mã')


def tim(ma, ds):
    n = norm(ma)
    if len(n) < 3:
        return None
    for mid, m, ten in ds:
        for cand in (m, ten):
            nc = norm(cand)
            if nc and n == nc:
                return mid
    for mid, m, ten in ds:
        for cand in (m, ten):
            nc = norm(cand)
            if len(nc) >= 4 and (n in nc or nc in n):
                return mid
    return None


GHI_CHU = ('Số màu ĐO TỪ ẢNH CHỤP bảng in (không phải đo máy quang phổ); ô mẫu dán thủ công nên '
           'không phải lúc nào cũng đậm dần theo nồng độ ⇒ dùng THAM KHẢO, muốn số chính xác phải đo mẫu vật lý.')
ins = []
so_ss = 0
for r in rows:
    h_a = hex_agy.get((r['file'], r['o']))
    dE = None
    tc = ''
    if h_a and r['do_duoc'] == 'co':
        L1, a1, b1 = hex_to_lab(h_a)
        L2, a2, b2 = float(r['L']), float(r['a']), float(r['b'])
        dE = round(float(np.sqrt((L1 - L2) ** 2 + (a1 - a2) ** 2 + (b1 - b2) ** 2)), 1)
        sat = max(int(r['R']), int(r['G']), int(r['B'])) - min(int(r['R']), int(r['G']), int(r['B']))
        # mức tin cậy của số đo: khớp AGY tốt và ô thực sự có màu (không phải giấy nền xanh nhạt)
        if sat < 35:
            tc = 'thap (nghi lấy nhầm nền giấy)'
        elif dE <= 10:
            tc = 'cao'
        elif dE <= 25:
            tc = 'trung-binh'
        else:
            tc = 'thap (lệch AGY nhiều)'
        so_ss += 1
    elif r['do_duoc'] == 'co':
        tc = 'chi-co-so-do'
    ins.append((r['nhom'], (r['nhan'] or '').strip(), r['ma_mau'], int(r['nong_do']) if r['nong_do'] else None, r['hex'] or None,
                int(r['R']) if r['R'] else None, int(r['G']) if r['G'] else None, int(r['B']) if r['B'] else None,
                float(r['L']) if r['L'] else None, float(r['a']) if r['a'] else None, float(r['b']) if r['b'] else None,
                h_a, dE, tc,
                r['file'], r['o'], r['nhan'], r.get('tong_mau', ''), r['do_duoc'], r.get('cach_gan', ''),
                tim(r['ma_mau'], ds_mau), URL, NGAY,
                GHI_CHU if r['do_duoc'] == 'co' else 'Chưa gán được ô màu (ảnh lệch lưới) — chỉ có nhãn'))
print('số ô đối chiếu được 2 nguồn hex:', so_ss)
print('mức tin cậy:', {k: sum(1 for x in ins if x[13] == k) for k in sorted(set(x[13] for x in ins))})
print('liên kết được với bảng mau:', sum(1 for x in ins if x[20]))
if not COMMIT:
    print('\n-- XEM TRƯỚC (chưa ghi) — 12 dòng đầu:')
    for x in ins[:12]:
        print('   %-7s | %-30s | %s%% | %s | %-24s | mau_id %s' % (x[0], x[1], x[3], x[4], x[13], x[20]))
    con.close(); sys.exit(0)

bk = B.replace('.db', '_bak_%s.db' % datetime.now().strftime('%Y%m%d_%H%M'))
shutil.copy2(B, bk)
print('backup:', bk)
cur.execute('DROP TABLE IF EXISTS mau_bang_in')
cur.execute(CREATE_SQL)
cur.executemany("""INSERT INTO mau_bang_in (nhom, ma_mau, ma_khong_pc, nong_do, hex, r_srgb, g_srgb, b_srgb,
                   L_star, a_star, b_star, hex_agy, dE_hai_nguon, do_tin_cay, file_anh, o, nhan_goc,
                   tong_mau, do_duoc, cach_gan, mau_id, nguon_url, ngay_tai, ghi_chu)
                   VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""", ins)
tc_dem = {k: sum(1 for x in ins if x[13] == k) for k in sorted(set(x[13] for x in ins))}
cur.execute("""INSERT INTO nhat_ky (ngay, viec, chi_tiet, nguon) VALUES (?,?,?,?)""",
            (NGAY, 'Nạp bảng màu từ trang mausac.ngoducminh.com vào CSDL B',
             'Bảng mau_bang_in: %d ô màu (DYE %d + PIGMENT %d), %d ô đo được hex/Lab, %d ô đối chiếu hex với AGY, '
             'liên kết %d mã với bảng mau. Mức tin cậy: %s. Cột ma_mau giữ NGUYÊN VĂN tên in trên bảng kèm %%; '
             'cột ma_khong_pc = tên đã bỏ %% để gom nhóm.'
             % (len(ins), sum(1 for x in ins if x[0] == 'DYE'), sum(1 for x in ins if x[0] == 'PIGMENT'),
                sum(1 for x in ins if x[4]), so_ss, sum(1 for x in ins if x[20]), tc_dem), URL))
con.commit()
print('\n=== SAU KHI GHI ===')
for t in ('mau', 'mau_bang_in', 'phan_tan', 'lien_ket_gia', 'nhat_ky'):
    print(' ', t, cur.execute('SELECT COUNT(*) FROM %s' % t).fetchone()[0])
print(' theo nhóm:', cur.execute("SELECT nhom, COUNT(*), SUM(CASE WHEN hex IS NOT NULL THEN 1 ELSE 0 END) FROM mau_bang_in GROUP BY nhom").fetchall())
print(' theo ảnh:', cur.execute("SELECT file_anh, COUNT(*), SUM(CASE WHEN hex IS NOT NULL THEN 1 ELSE 0 END) FROM mau_bang_in GROUP BY file_anh ORDER BY file_anh").fetchall())
cur.execute('PRAGMA integrity_check'); print(' integrity:', cur.fetchone()[0])
con.close()
