#!/usr/bin/env python3
"""Учебная перестановка и отдельные pin/hide; не алгоритм Algolia."""
import argparse
import csv
import json
from pathlib import Path


def run(data):
    catalog = {x['sku']: x for x in data['catalog']}
    if len(catalog) != len(data['catalog']):
        raise ValueError('Повтор SKU в каталоге')
    retrieval = data['retrieval_order']
    if len(set(retrieval)) != len(retrieval) or not set(retrieval) <= catalog.keys():
        raise ValueError('Неверный первичный отбор')
    eligible = [s for s in retrieval if catalog[s]['in_stock'] == data['filter']['in_stock']]
    teaching = data['teaching_order']
    if len(teaching) != len(eligible) or set(teaching) != set(eligible):
        raise ValueError('Учебный порядок обязан быть перестановкой кандидатов')
    # Никаких ML-баллов: редакция явно задаёт перестановку кандидатов.
    reranked = list(teaching)
    hidden = set(data['rules']['hide'])
    if not hidden <= catalog.keys():
        raise ValueError('Неизвестный скрытый SKU')
    visible = [s for s in reranked if s not in hidden]
    pin = data['rules']['pin']
    sku, position = pin['sku'], pin['position_1_based']
    if sku not in eligible:
        raise ValueError('Пример допускает pin только уже найденного кандидата')
    if sku in hidden:
        raise ValueError('Конфликт pin/hide вне области примера')
    if not isinstance(position, int) or isinstance(position, bool) or not 1 <= position <= len(visible):
        raise ValueError('Позиция pin за пределами видимого списка')
    final = [s for s in visible if s != sku]
    final.insert(position - 1, sku)
    return {'retrieval': list(retrieval), 'eligible': eligible, 'reranked': reranked, 'after_hide': visible, 'final': final}


def main():
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument('--input', type=Path, default=Path(__file__).with_name('input.json'))
    ap.add_argument('--hide-c', action='store_true')
    ap.add_argument('--out', type=Path, required=True)
    a = ap.parse_args()
    data = json.loads(a.input.read_text(encoding='utf-8'))
    if a.hide_c:
        data['rules']['hide'] = ['C']
    result = run(data)
    a.out.mkdir(parents=True, exist_ok=True)
    (a.out / 'result.json').write_text(json.dumps(result, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
    with (a.out / 'stages.csv').open('w', encoding='utf-8', newline='') as f:
        w = csv.writer(f, lineterminator='\n'); w.writerow(['stage', 'position_1_based', 'sku'])
        for stage, skus in result.items():
            w.writerows((stage, i, s) for i, s in enumerate(skus, 1))
    print(json.dumps(result, ensure_ascii=False))


if __name__ == '__main__':
    main()
