-- Схема MedArchive. Четыре сущности из ТЗ §3, адаптированные под реальные данные:
-- многотарифные цены (резидент/нерезидент/СНГ/…) хранятся в prices (jsonb),
-- а два главных тарифа продублированы отдельными колонками под ТЗ и API.

CREATE EXTENSION IF NOT EXISTS vector;          -- pgvector для семантического сопоставления
CREATE EXTENSION IF NOT EXISTS pg_trgm;         -- триграммы для нечёткого поиска

-- Эталонный справочник услуг (1281 позиция, загружается из xlsx).
CREATE TABLE service (
    service_id        text PRIMARY KEY,         -- «<ID>-<Code>» из справочника
    specialty         text NOT NULL DEFAULT '', -- специальность = категория + сужение поиска
    name_ru           text NOT NULL,
    name_norm         text NOT NULL,            -- нормализованная форма для точного совпадения
    tarificator_code  text,                     -- код тарификатора, если задан
    synonyms          jsonb NOT NULL DEFAULT '[]'::jsonb,  -- наращиваем при ручной верификации
    embedding         vector(384),              -- эмбеддинг name_ru (multilingual)
    is_active         boolean NOT NULL DEFAULT true
);
CREATE INDEX service_tarificator_idx ON service (tarificator_code) WHERE tarificator_code IS NOT NULL;
CREATE INDEX service_name_trgm_idx ON service USING gin (name_ru gin_trgm_ops);
CREATE INDEX service_embedding_idx ON service USING hnsw (embedding vector_cosine_ops);

-- Клиника-партнёр.
CREATE TABLE partner (
    partner_id     uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    name           text NOT NULL,
    city           text,
    address        text,
    bin            varchar(12),                 -- БИН организации, для дедупликации
    contact_email  text,
    contact_phone  text,
    is_active      boolean NOT NULL DEFAULT true,
    created_at     timestamptz NOT NULL DEFAULT now(),
    updated_at     timestamptz NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX partner_bin_idx ON partner (bin) WHERE bin IS NOT NULL;

-- Исходный прайс-документ (один файл = прайс одной клиники на дату).
CREATE TABLE price_document (
    doc_id         uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    partner_id     uuid NOT NULL REFERENCES partner(partner_id),
    file_name      text NOT NULL,
    file_format    text NOT NULL,               -- pdf / scan_pdf / docx / xlsx / xls
    effective_date date,                         -- дата вступления в силу (год из имени файла)
    parsed_at      timestamptz,
    parse_status   text NOT NULL DEFAULT 'pending',  -- pending/processing/done/error/needs_review
    parse_log      text,
    raw_content    text                          -- сырой извлечённый текст для аудита
);

-- Позиция прайса (услуга + цены). Это рабочая лошадка системы.
CREATE TABLE price_item (
    item_id              uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    doc_id               uuid NOT NULL REFERENCES price_document(doc_id),
    partner_id           uuid NOT NULL REFERENCES partner(partner_id),  -- денормализация ради скорости
    service_name_raw     text NOT NULL,          -- название как в документе
    service_code_source  text,                   -- код из источника (внутренний или тарификатора)
    service_id           text REFERENCES service(service_id),           -- нормализованная услуга (nullable)
    prices               jsonb NOT NULL DEFAULT '{}'::jsonb,  -- {resident, nonresident, cis, far, insurance, partner}
    price_resident_kzt   numeric,                -- главный тариф, продублирован под ТЗ/API
    price_nonresident_kzt numeric,
    currency_original    text NOT NULL DEFAULT 'KZT',
    unit                 text,
    effective_date       date,
    map_method           text,                   -- code/exact/embedding/fuzzy/manual
    map_confidence       numeric,
    is_verified          boolean NOT NULL DEFAULT false,
    verification_note    text,
    is_active            boolean NOT NULL DEFAULT true,
    created_at           timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX price_item_service_idx ON price_item (service_id);
CREATE INDEX price_item_partner_idx ON price_item (partner_id);
CREATE INDEX price_item_unmatched_idx ON price_item (service_id) WHERE service_id IS NULL;
CREATE INDEX price_item_raw_trgm_idx ON price_item USING gin (service_name_raw gin_trgm_ops);
-- Активная позиция уникальна по клинике, названию и дате прайса (версионирование — через is_active).
CREATE UNIQUE INDEX price_item_active_idx
    ON price_item (partner_id, service_name_raw, effective_date) WHERE is_active;
