-- ============================================================================
-- SCHEMA: users
-- TABLE: kyc_verifications
-- DESCRIPTION: Verificacion de identidad KYC (Know Your Customer)
-- VERSION: 1.0.0
-- CREATED: 2026-01-16
-- SPRINT: Sprint 1 - DDL Implementation Roadmap Q1-2026
-- ============================================================================

-- Enum para estado de verificacion KYC
DO $$ BEGIN
    CREATE TYPE users.kyc_status AS ENUM (
        'not_started',      -- No ha iniciado proceso
        'pending',          -- Documentos enviados, pendiente revision
        'under_review',     -- En proceso de revision manual
        'approved',         -- Aprobado completamente
        'rejected',         -- Rechazado (puede reintentar)
        'expired',          -- Verificacion expirada, requiere re-verificacion
        'suspended'         -- Suspendido por actividad sospechosa
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Enum para nivel de verificacion
DO $$ BEGIN
    CREATE TYPE users.kyc_level AS ENUM (
        'none',         -- Sin verificacion
        'basic',        -- Email + telefono verificado
        'standard',     -- Documento ID verificado
        'enhanced',     -- ID + prueba de direccion
        'full'          -- Verificacion completa con video
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Tabla de Verificaciones KYC
CREATE TABLE IF NOT EXISTS users.kyc_verifications (
    -- Identificadores
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users.users(id) ON DELETE CASCADE,
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,

    -- Estado actual
    status users.kyc_status NOT NULL DEFAULT 'not_started',
    level users.kyc_level NOT NULL DEFAULT 'none',

    -- Verificacion de Email
    email_verified BOOLEAN NOT NULL DEFAULT FALSE,
    email_verified_at TIMESTAMPTZ,
    email_verification_method VARCHAR(50),  -- 'code', 'link'

    -- Verificacion de Telefono
    phone_verified BOOLEAN NOT NULL DEFAULT FALSE,
    phone_verified_at TIMESTAMPTZ,
    phone_verification_method VARCHAR(50),  -- 'sms', 'call'

    -- Verificacion de Documento ID
    id_document_verified BOOLEAN NOT NULL DEFAULT FALSE,
    id_document_verified_at TIMESTAMPTZ,
    id_document_type VARCHAR(50),           -- 'passport', 'national_id', 'drivers_license'
    id_document_number_hash VARCHAR(255),   -- Hash del numero para verificacion
    id_document_country VARCHAR(100),
    id_document_expiry DATE,
    id_document_front_url TEXT,             -- URL segura al documento (encriptado)
    id_document_back_url TEXT,
    id_selfie_url TEXT,                     -- Selfie con documento

    -- Verificacion de Direccion
    address_verified BOOLEAN NOT NULL DEFAULT FALSE,
    address_verified_at TIMESTAMPTZ,
    address_document_type VARCHAR(50),      -- 'utility_bill', 'bank_statement', 'tax_document'
    address_document_url TEXT,
    address_document_date DATE,             -- Fecha del documento (max 3 meses)

    -- Verificacion de Video (enhanced)
    video_verified BOOLEAN NOT NULL DEFAULT FALSE,
    video_verified_at TIMESTAMPTZ,
    video_url TEXT,
    video_liveness_score DECIMAL(5, 4),     -- 0.0000 - 1.0000

    -- Proveedor de verificacion externo
    external_provider VARCHAR(50),          -- 'sumsub', 'onfido', 'jumio'
    external_verification_id VARCHAR(255),
    external_status VARCHAR(50),
    external_risk_score DECIMAL(5, 4),

    -- Informacion de revision
    reviewer_id UUID,
    reviewed_at TIMESTAMPTZ,
    review_notes TEXT,
    rejection_reason TEXT,
    rejection_codes JSONB,                  -- Array de codigos de rechazo

    -- AML/PEP checks
    aml_checked BOOLEAN NOT NULL DEFAULT FALSE,
    aml_checked_at TIMESTAMPTZ,
    aml_result VARCHAR(50),                 -- 'clear', 'match', 'potential_match'
    aml_details JSONB,

    pep_checked BOOLEAN NOT NULL DEFAULT FALSE,
    pep_checked_at TIMESTAMPTZ,
    pep_result VARCHAR(50),
    pep_details JSONB,

    sanctions_checked BOOLEAN NOT NULL DEFAULT FALSE,
    sanctions_checked_at TIMESTAMPTZ,
    sanctions_result VARCHAR(50),
    sanctions_details JSONB,

    -- Expiracion
    expires_at TIMESTAMPTZ,
    reminder_sent_at TIMESTAMPTZ,

    -- Intentos
    verification_attempts INTEGER NOT NULL DEFAULT 0,
    max_attempts INTEGER NOT NULL DEFAULT 3,
    locked_until TIMESTAMPTZ,

    -- Metadata
    ip_address INET,
    user_agent TEXT,
    device_fingerprint VARCHAR(255),
    metadata JSONB DEFAULT '{}'::JSONB,

    -- Timestamps
    started_at TIMESTAMPTZ,
    completed_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- Constraints
    CONSTRAINT kyc_unique_user UNIQUE (user_id)
);

COMMENT ON TABLE users.kyc_verifications IS
'Registro de verificacion KYC de usuarios para compliance regulatorio';

COMMENT ON COLUMN users.kyc_verifications.level IS
'Nivel de verificacion alcanzado: none, basic, standard, enhanced, full';

COMMENT ON COLUMN users.kyc_verifications.external_risk_score IS
'Score de riesgo del proveedor externo (0-1, menor es mejor)';

-- Indices
CREATE INDEX IF NOT EXISTS idx_kyc_user_id
    ON users.kyc_verifications(user_id);

CREATE INDEX IF NOT EXISTS idx_kyc_tenant_id
    ON users.kyc_verifications(tenant_id);

CREATE INDEX IF NOT EXISTS idx_kyc_status
    ON users.kyc_verifications(status);

CREATE INDEX IF NOT EXISTS idx_kyc_level
    ON users.kyc_verifications(level);

CREATE INDEX IF NOT EXISTS idx_kyc_expires_at
    ON users.kyc_verifications(expires_at)
    WHERE expires_at IS NOT NULL AND status = 'approved';

CREATE INDEX IF NOT EXISTS idx_kyc_pending_review
    ON users.kyc_verifications(created_at)
    WHERE status IN ('pending', 'under_review');

CREATE INDEX IF NOT EXISTS idx_kyc_aml_matches
    ON users.kyc_verifications(tenant_id, aml_result)
    WHERE aml_result IN ('match', 'potential_match');

-- Trigger para updated_at
DROP TRIGGER IF EXISTS kyc_updated_at ON users.kyc_verifications;
CREATE TRIGGER kyc_updated_at
    BEFORE UPDATE ON users.kyc_verifications
    FOR EACH ROW
    EXECUTE FUNCTION users.update_user_timestamp();

-- Funcion para actualizar nivel de KYC automaticamente
CREATE OR REPLACE FUNCTION users.update_kyc_level()
RETURNS TRIGGER AS $$
BEGIN
    -- Calcular nivel basado en verificaciones completadas
    IF NEW.video_verified AND NEW.address_verified AND NEW.id_document_verified AND NEW.phone_verified AND NEW.email_verified THEN
        NEW.level := 'full';
    ELSIF NEW.address_verified AND NEW.id_document_verified AND NEW.phone_verified AND NEW.email_verified THEN
        NEW.level := 'enhanced';
    ELSIF NEW.id_document_verified AND (NEW.phone_verified OR NEW.email_verified) THEN
        NEW.level := 'standard';
    ELSIF NEW.email_verified AND NEW.phone_verified THEN
        NEW.level := 'basic';
    ELSE
        NEW.level := 'none';
    END IF;

    -- Actualizar status si todas las verificaciones del nivel estan completas
    IF NEW.level = 'full' AND OLD.status IN ('pending', 'under_review') THEN
        NEW.status := 'approved';
        NEW.completed_at := NOW();
        -- Set expiration (typically 1-2 years)
        NEW.expires_at := NOW() + INTERVAL '2 years';
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS kyc_level_update ON users.kyc_verifications;
CREATE TRIGGER kyc_level_update
    BEFORE UPDATE ON users.kyc_verifications
    FOR EACH ROW
    EXECUTE FUNCTION users.update_kyc_level();

-- RLS Policy para multi-tenancy
ALTER TABLE users.kyc_verifications ENABLE ROW LEVEL SECURITY;

CREATE POLICY kyc_tenant_isolation ON users.kyc_verifications
    FOR ALL
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- Policy especial para revisores (pueden ver todos los pendientes)
CREATE POLICY kyc_reviewer_access ON users.kyc_verifications
    FOR SELECT
    USING (
        current_setting('app.is_kyc_reviewer', true)::boolean = true
        AND status IN ('pending', 'under_review')
    );

-- Grants
GRANT SELECT, INSERT, UPDATE ON users.kyc_verifications TO trading_app;
GRANT SELECT ON users.kyc_verifications TO trading_readonly;
