-- «Мой налог» (НПД) export rail: the operator registers each rouble income with the tax service
-- and annuls its receipt on a refund. Two new tables plus one nullable column — strictly additive,
-- so it applies forward via goose with no data rewrite (no contour wipe) and an image rollback
-- simply ignores it. The ledger itself is untouched: it is append-only, so the export's working
-- state cannot live there.
-- +goose Up

-- The single stored «Мой налог» session and the rail's operating mode. The password is never
-- persisted: it is exchanged for a refresh token at login, and only that token is kept, encrypted
-- with BACKEND_MYNALOG_KEY. device_id pins the session to one synthetic "device" so repeated
-- logins do not look like a new one every time. Dropping the row logs the rail out and, by
-- design, also disarms the automatic mode.
CREATE TABLE payments.mynalog_session (
    only_row boolean DEFAULT true NOT NULL,
    inn text NOT NULL,
    device_id text NOT NULL,
    refresh_token_enc bytea NOT NULL,
    auto_enabled boolean DEFAULT false NOT NULL,
    paused_at timestamp with time zone,
    pause_reason text DEFAULT '' NOT NULL,
    last_ok_at timestamp with time zone,
    last_alert_at timestamp with time zone,
    last_alert_kind text DEFAULT '' NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    CONSTRAINT mynalog_session_pkey PRIMARY KEY (only_row),
    CONSTRAINT mynalog_session_single_row_chk CHECK (only_row)
);

-- One row per income we act on, keyed on the ledger row it reports. The queue itself is NOT
-- materialised here — it is derived by joining the ledger against this table — so a row appears
-- only once we have decided something about that income.
--
-- receipt_name is the exact services[].name we sent, frozen BEFORE the request: the tax API has no
-- idempotency key, so after a timeout the only way to find out whether our receipt was created is
-- to search the tax service's own income list by that string. It carries the order id for exactly
-- that reason.
CREATE TABLE payments.mynalog_receipt (
    ledger_id uuid NOT NULL,
    order_id uuid NOT NULL,
    account_id uuid NOT NULL,
    status text NOT NULL,
    receipt_uuid text,
    receipt_name text NOT NULL,
    operation_time timestamp with time zone NOT NULL,
    amount_minor bigint NOT NULL,
    currency text NOT NULL,
    entered_manually boolean DEFAULT false NOT NULL,
    attempts integer DEFAULT 0 NOT NULL,
    last_error text DEFAULT '' NOT NULL,
    sent_at timestamp with time zone,
    receipt_mail_sent_at timestamp with time zone,
    cancel_status text DEFAULT 'none' NOT NULL,
    cancel_refund_ledger_id uuid,
    cancelled_at timestamp with time zone,
    cancel_mail_sent_at timestamp with time zone,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    CONSTRAINT mynalog_receipt_pkey PRIMARY KEY (ledger_id),
    CONSTRAINT mynalog_receipt_ledger_fkey FOREIGN KEY (ledger_id)
        REFERENCES payments.ledger (ledger_id),
    CONSTRAINT mynalog_receipt_order_fkey FOREIGN KEY (order_id)
        REFERENCES payments.orders (order_id),
    CONSTRAINT mynalog_receipt_refund_fkey FOREIGN KEY (cancel_refund_ledger_id)
        REFERENCES payments.ledger (ledger_id),
    CONSTRAINT mynalog_receipt_status_chk
        CHECK ((status = ANY (ARRAY['sending'::text, 'sent'::text, 'unknown'::text,
                                    'failed'::text, 'not_required'::text]))),
    CONSTRAINT mynalog_receipt_cancel_status_chk
        CHECK ((cancel_status = ANY (ARRAY['none'::text, 'cancelled'::text, 'failed'::text]))),
    CONSTRAINT mynalog_receipt_amount_chk CHECK ((amount_minor >= 0)),
    CONSTRAINT mynalog_receipt_attempts_chk CHECK ((attempts >= 0)),
    -- A sent receipt must carry its uuid: without it the refund could never annul anything.
    CONSTRAINT mynalog_receipt_sent_uuid_chk
        CHECK ((status <> 'sent') OR (receipt_uuid IS NOT NULL AND receipt_uuid <> ''))
);

CREATE INDEX mynalog_receipt_status_idx ON payments.mynalog_receipt (status);
CREATE INDEX mynalog_receipt_cancel_idx ON payments.mynalog_receipt (cancel_status);
CREATE INDEX mynalog_receipt_order_idx ON payments.mynalog_receipt (order_id);

-- A second, independent cursor over the existing payment-event outbox: dispatched_at drives the
-- in-app wallet-refresh push, mailed_at drives the buyer's purchase-confirmation letter. The
-- column means "the mail decision has been made", not "a letter was sent" — an event that needs
-- no letter (a store rail, or an account with no confirmed address) is stamped and skipped.
ALTER TABLE payments.payment_events ADD COLUMN mailed_at timestamp with time zone;

CREATE INDEX payment_events_mail_idx
    ON payments.payment_events (mailed_at)
    WHERE mailed_at IS NULL;

-- +goose Down

DROP INDEX payments.payment_events_mail_idx;
ALTER TABLE payments.payment_events DROP COLUMN mailed_at;
DROP TABLE payments.mynalog_receipt;
DROP TABLE payments.mynalog_session;
