# -*- coding: utf-8 -*-
"""Lượt phối màu THỨ HAI — chỉ dùng các màu bảng in ĐÃ LIÊN KẾT được với 26 mã TỒN KHO trong CSDL B
(để công thức đề xuất là thứ pha được ngay, không phải mua mã mới).
Liên kết theo tên gần đúng (ghi rõ trong báo cáo là 'cần xác nhận'):
   Đỏ F3RK           ↔ Novoperm Red F3RK 70-CN09 (CN09)
   Đỏ RB 97          ↔ Iron Oxide RB 4097 (200 kg) / Ferrispec FP RB-4097 (375 kg)
   Vàng YB 87        ↔ Ferrispec FP YB-2087 (800 kg)
   Vàng H4G          ↔ Hififast Yellow HF4G (190 kg)
   Nâu BS1008        ↔ Pigment Brown TB 1008 (1.047,5 kg) / Brown SP 1008 W (323,9 kg)
   Đen BT M100S      ↔ Carbon Black MA 100 (430 kg)
   Xanh Lá GT        ↔ Paste màu xanh lá TS-G007
   (KHÔNG có trên bảng in: Umber 645 · Hoover 778 BN · Red RO 4597 · VAP-330M · TR 718 · Chromaflo C4/C26/C27/C5/C6 · MH Black 20/56 · MH Yellow 57 · NS 29/NS 40 · BG 100)"""
import io, itertools, json, os, sqlite3
import numpy as np

B = r'C:\Claw 2\Nghien cuu\Du-an-B-He-mau-Stain-Glaze'
DB = os.path.join(B, 'CSDLB.db')
MUC_TIEU = np.array([47.1, 15.8, 5.6])
GO_MOC = np.array([69.0, -0.4, 2.1])
M_FWD = np.array([[0.4124, 0.3576, 0.1805], [0.2126, 0.7152, 0.0722], [0.0193, 0.1192, 0.9505]])
M_INV = np.array([[3.2406, -1.5372, -0.4986], [-0.9689, 1.8758, 0.0415], [0.0557, -0.2040, 1.0570]])
LINK = ['Đỏ F3RK', 'Đỏ RB 97', 'Vàng YB 87', 'Vàng H4G', 'Nâu BS1008', 'Đen BT M100S', 'Xanh Lá GT']


def lab_to_rgb01(lab):
    L, a, b = lab
    fy = (L + 16) / 116
    f = np.array([fy + a / 500, fy, fy - b / 200])
    f = np.where(f ** 3 > 0.008856, f ** 3, (116 * f - 16) / 903.3)
    r = M_INV @ (f * np.array([0.95047, 1.0, 1.08883]))
    r = np.where(r <= 0.0031308, 12.92 * r, 1.055 * np.clip(r, 0, None) ** (1 / 2.4) - 0.055)
    return np.clip(r, 0, 1)


def rgb01_to_lab(rgb):
    a = np.clip(np.asarray(rgb, float), 0, 1)
    a = np.where(a <= 0.04045, a / 12.92, ((a + 0.055) / 1.055) ** 2.4)
    xyz = (M_FWD @ a) / np.array([0.95047, 1.0, 1.08883])
    f = np.where(xyz > 0.008856, np.cbrt(xyz), 7.787 * xyz + 16 / 116)
    return np.array([116 * f[1] - 16, 500 * (f[0] - f[1]), 200 * (f[1] - f[2])])


def hexs(lab):
    return '#%02X%02X%02X' % tuple(np.round(lab_to_rgb01(lab) * 255).astype(int))


def ks_of(r):
    R = np.clip(r, 0.004, 1.0)
    return ((1 - R) ** 2) / (2 * R)


def km(KS, w):
    w = np.asarray(w, float); w = w / w.sum()
    K = (w[:, None] * KS).sum(0)
    return np.clip(1 + K - np.sqrt(K ** 2 + 2 * K), 1e-4, 1)


c = sqlite3.connect('file:%s?mode=ro' % DB.replace('\\', '/'), uri=True)
pool = []
for nhom, ten, nd, hexv, L, a, bb, tin in c.execute(
        """SELECT nhom, ma_mau, nong_do, hex, L_star, a_star, b_star, do_tin_cay FROM mau_bang_in
           WHERE L_star IS NOT NULL"""):
    if any(k.lower() in ten.lower() for k in LINK):
        pool.append(dict(nhom=nhom, ten=ten, nd=nd, hex=hexv, lab=np.array([L, a, bb]), tin=tin or '',
                         ks=ks_of(lab_to_rgb01(np.array([L, a, bb])))))
print('ô dùng được (đã liên kết tồn kho):', len(pool))
for x in pool:
    print('   %-30s ô %2s%%  %s  L*a*b* %5.1f/%5.1f/%5.1f  tin cậy %s' % (x['ten'], x['nd'], x['hex'], *x['lab'], x['tin']))

ket = []
for w in (0.40, 0.45, 0.50, 0.55, 0.60):
    for k in (1, 2, 3):
        for combo in itertools.combinations(range(len(pool)), k):
            KS = np.stack([pool[i]['ks'] for i in combo])
            grid = [np.arange(0.05, 1.0, 0.05)] * k
            for ws in itertools.product(*grid):
                if abs(sum(ws) - 1) > 1e-9:
                    continue
                lab_lop = rgb01_to_lab(km(KS, ws))
                pred = (1 - w) * GO_MOC + w * lab_lop
                ket.append((float(np.linalg.norm(pred - MUC_TIEU)), w, tuple(pool[i] for i in combo),
                            tuple(round(float(v), 2) for v in ws), lab_lop, pred))
ket.sort(key=lambda x: x[0])
print('\n=== TOP 12 (chỉ mã đã liên kết tồn kho) ===')
seen, dem = set(), 0
for e, w, comps, ws, lab_lop, pred in ket:
    key = tuple(sorted(x['ten'] for x in comps))
    if key in seen:
        continue
    seen.add(key); dem += 1
    print('  ΔE %-5.2f w=%.2f | %-52s | tỉ lệ %-14s | dự kiến %s' % (
        e, w, ' + '.join(x['ten'][:26] for x in comps), '/'.join('%.0f' % (100 * y) for y in ws), hexs(pred)))
    if dem >= 12:
        break

p = os.path.join(B, 'phan-tich-nen-mau-07-10', '_ket_qua_phoi_mau_TONKHO.json')
json.dump(dict(muc_tieu=[float(v) for v in MUC_TIEU], go_moc=[float(v) for v in GO_MOC],
               lien_ket=LINK, ket_qua=[dict(dE=round(e, 2), w=w,
                                            thanh_phan=[dict(ten=x['ten'], nhom=x['nhom'], nong_do_o=x['nd'],
                                                             hex=x['hex'], tin_cay=x['tin'], ti_le=y)
                                                         for x, y in zip(comps, ws)],
                                            hex_du_kien=hexs(pred), lab_du_kien=[round(float(v), 1) for v in pred])
                                       for e, w, comps, ws, lab_lop, pred in ket[:60]]),
          io.open(p, 'w', encoding='utf-8'), ensure_ascii=False, indent=1)
print('\nlưu:', p)
