-- ============================================================================
-- Asaas Gateway — Tier 1 (cobrança de paciente) — schema foundation
-- ----------------------------------------------------------------------------
-- Cria 3 tabelas novas + adiciona 4 colunas em payment_settings.
-- Schema preparado pra Fase 3 do ROADMAP (gateway de pagamento).
--
-- ⚠️ Não habilita o gateway sozinho. Requer:
--   - Edge Functions deployadas
--   - API keys configuradas em payment_settings
--   - Webhook setado no dashboard Asaas
--
-- Ver: development/02-auditoria/DESIGN_ASAAS_GATEWAY.md
-- ============================================================================

BEGIN;

-- ──────────────────────────────────────────────────────────────────────────
-- 1. asaas_customers — mapping patient ↔ Asaas customer
-- ──────────────────────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS public.asaas_customers (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id uuid NOT NULL,
    patient_id uuid NOT NULL REFERENCES public.patients(id) ON DELETE CASCADE,
    asaas_customer_id text NOT NULL,
    environment text NOT NULL DEFAULT 'sandbox' CHECK (environment IN ('sandbox', 'prod')),
    -- dados cacheados (sincronizados quando atualizar patient)
    name text NOT NULL,
    email text,
    cpf_cnpj text,
    phone text,
    address jsonb,
    created_at timestamptz DEFAULT now() NOT NULL,
    updated_at timestamptz DEFAULT now() NOT NULL,
    deleted_at timestamptz,
    CONSTRAINT asaas_customers_unique_per_env UNIQUE (tenant_id, patient_id, environment)
);

COMMENT ON TABLE public.asaas_customers IS
    'Mapping de pacientes para Asaas customers (1:1 por environment). Cacheado pra evitar re-criação a cada cobrança.';

CREATE INDEX IF NOT EXISTS idx_asaas_customers_lookup
    ON public.asaas_customers (tenant_id, patient_id)
    WHERE deleted_at IS NULL;

-- ──────────────────────────────────────────────────────────────────────────
-- 2. asaas_payments — 1 row por cobrança gerada
-- ──────────────────────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS public.asaas_payments (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id uuid NOT NULL,
    financial_record_id uuid NOT NULL REFERENCES public.financial_records(id) ON DELETE CASCADE,
    asaas_customer_id uuid REFERENCES public.asaas_customers(id),
    asaas_payment_id text NOT NULL,
    asaas_invoice_id text,
    environment text NOT NULL DEFAULT 'sandbox' CHECK (environment IN ('sandbox', 'prod')),
    billing_type text NOT NULL CHECK (billing_type IN ('PIX', 'BOLETO', 'CREDIT_CARD', 'UNDEFINED')),
    status text NOT NULL,
    value numeric(10, 2) NOT NULL,
    net_value numeric(10, 2),
    due_date date NOT NULL,
    payment_date timestamptz,
    invoice_url text,
    payment_url text,
    bank_slip_url text,
    pix_qr_code text,
    pix_copy_paste text,
    created_at timestamptz DEFAULT now() NOT NULL,
    updated_at timestamptz DEFAULT now() NOT NULL,
    cancelled_at timestamptz,
    CONSTRAINT asaas_payments_unique_per_env UNIQUE (asaas_payment_id, environment)
);

COMMENT ON TABLE public.asaas_payments IS
    'Cobranças geradas no Asaas. Status raw do Asaas; mapeamento pra financial_records.status acontece no JS.';

CREATE INDEX IF NOT EXISTS idx_asaas_payments_record
    ON public.asaas_payments (financial_record_id);
CREATE INDEX IF NOT EXISTS idx_asaas_payments_lookup
    ON public.asaas_payments (tenant_id, status, due_date)
    WHERE cancelled_at IS NULL;

-- ──────────────────────────────────────────────────────────────────────────
-- 3. asaas_webhook_events — idempotência + audit
-- ──────────────────────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS public.asaas_webhook_events (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    event_id text,
    event_type text NOT NULL,
    asaas_payment_id text,
    payload jsonb NOT NULL,
    processed_at timestamptz,
    processing_error text,
    received_at timestamptz DEFAULT now() NOT NULL
);

COMMENT ON TABLE public.asaas_webhook_events IS
    'Audit + idempotência de webhooks Asaas. event_id usado pra dedupe (Asaas faz retry).';

-- event_id UNIQUE quando preenchido (Asaas nem sempre manda)
CREATE UNIQUE INDEX IF NOT EXISTS idx_asaas_webhook_events_event_id
    ON public.asaas_webhook_events (event_id)
    WHERE event_id IS NOT NULL;

CREATE INDEX IF NOT EXISTS idx_asaas_webhook_events_payment
    ON public.asaas_webhook_events (asaas_payment_id);

CREATE INDEX IF NOT EXISTS idx_asaas_webhook_events_unprocessed
    ON public.asaas_webhook_events (received_at)
    WHERE processed_at IS NULL;

-- ──────────────────────────────────────────────────────────────────────────
-- 4. payment_settings — colunas pra config Asaas por tenant
-- ──────────────────────────────────────────────────────────────────────────
-- API keys plaintext nesta migration. Em produção, mover pra pgsodium/Vault.

ALTER TABLE public.payment_settings
    ADD COLUMN IF NOT EXISTS asaas_api_key_sandbox text,
    ADD COLUMN IF NOT EXISTS asaas_api_key_prod text,
    ADD COLUMN IF NOT EXISTS asaas_environment text DEFAULT 'sandbox'
        CHECK (asaas_environment IN ('sandbox', 'prod')),
    ADD COLUMN IF NOT EXISTS asaas_webhook_token text,
    ADD COLUMN IF NOT EXISTS asaas_enabled boolean DEFAULT false NOT NULL;

COMMENT ON COLUMN public.payment_settings.asaas_api_key_sandbox IS
    'API key Asaas SANDBOX. PLAINTEXT por enquanto — migrar pra Vault em prod.';
COMMENT ON COLUMN public.payment_settings.asaas_api_key_prod IS
    'API key Asaas PRODUÇÃO. PLAINTEXT por enquanto — migrar pra Vault em prod.';
COMMENT ON COLUMN public.payment_settings.asaas_environment IS
    'Qual key usar: sandbox (testes) ou prod (real). Default sandbox por segurança.';
COMMENT ON COLUMN public.payment_settings.asaas_webhook_token IS
    'Token customizado pra webhook receiver validar. Setar mesmo valor no dashboard Asaas.';
COMMENT ON COLUMN public.payment_settings.asaas_enabled IS
    'Flag que controla se gateway Asaas está habilitado pro tenant. Default false (opt-in).';

COMMIT;
