CREATE TABLE legal_market_access_controls (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    control_key text NOT NULL UNIQUE,
    control_type text NOT NULL CHECK (control_type IN (
        'regulated_activity_decision',
        'operating_model',
        'legal_memo',
        'product_term_approval',
        'provider_contract',
        'safeguarding_model',
        'policy_document',
        'jurisdiction_product_rule'
    )),
    jurisdiction text NOT NULL DEFAULT 'GLOBAL',
    product_scope text NOT NULL DEFAULT '',
    provider_category text NOT NULL DEFAULT '',
    provider_name text NOT NULL DEFAULT '',
    status text NOT NULL DEFAULT 'draft' CHECK (status IN (
        'draft',
        'in_review',
        'approved',
        'rejected',
        'blocked',
        'signed',
        'published',
        'expired',
        'disabled',
        'test_only',
        'allowed',
        'prohibited',
        'requires_disclaimer',
        'in_scope',
        'out_of_scope',
        'needs_legal_review'
    )),
    risk_level text NOT NULL DEFAULT 'high' CHECK (risk_level IN ('low', 'medium', 'high', 'critical')),
    owner_team text NOT NULL DEFAULT 'legal' CHECK (owner_team IN ('legal', 'compliance', 'risk', 'finance', 'operations', 'security', 'product', 'engineering')),
    decision_summary text NOT NULL,
    legal_memo_reference text NOT NULL DEFAULT '',
    contract_reference text NOT NULL DEFAULT '',
    policy_version text NOT NULL DEFAULT '',
    evidence_reference text NOT NULL DEFAULT '',
    required_disclosures text[] NOT NULL DEFAULT '{}',
    effective_at timestamptz,
    expires_at timestamptz,
    metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
    created_by_admin_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
    approved_by_admin_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
    approved_at timestamptz,
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now(),
    CHECK (jurisdiction = upper(jurisdiction)),
    CHECK (expires_at IS NULL OR effective_at IS NULL OR expires_at >= effective_at),
    CHECK (
        status NOT IN ('approved', 'signed', 'published', 'allowed', 'prohibited', 'out_of_scope')
        OR evidence_reference <> ''
        OR legal_memo_reference <> ''
        OR contract_reference <> ''
    )
);

CREATE INDEX legal_market_access_controls_type_status_idx
    ON legal_market_access_controls (control_type, status, updated_at DESC);

CREATE INDEX legal_market_access_controls_jurisdiction_scope_idx
    ON legal_market_access_controls (jurisdiction, product_scope, status);

CREATE INDEX legal_market_access_controls_expiry_idx
    ON legal_market_access_controls (expires_at)
    WHERE expires_at IS NOT NULL;

CREATE TRIGGER legal_market_access_controls_set_updated_at
BEFORE UPDATE ON legal_market_access_controls
FOR EACH ROW EXECUTE FUNCTION set_updated_at();

INSERT INTO legal_market_access_controls (
    control_key, control_type, jurisdiction, product_scope, status, risk_level, owner_team,
    decision_summary, evidence_reference, required_disclosures, metadata
) VALUES
    ('regulated-activity-e-money-issuance', 'regulated_activity_decision', 'GLOBAL', 'e_money_issuance', 'needs_legal_review', 'critical', 'legal', 'Classify whether stored value, e-money issuance, safeguarding and redemption obligations are in scope before real balances launch.', 'seed-legal-gap-2026-07-26', ARRAY['Do not market as regulated e-money until approved'], '{"launch_gate":true}'::jsonb),
    ('regulated-activity-payment-initiation', 'regulated_activity_decision', 'GLOBAL', 'payment_initiation', 'needs_legal_review', 'critical', 'legal', 'Classify whether customer-initiated payments are payment initiation or money transmission in each target market.', 'seed-legal-gap-2026-07-26', ARRAY['Payment services require legal approval'], '{"launch_gate":true}'::jsonb),
    ('regulated-activity-account-information', 'regulated_activity_decision', 'GLOBAL', 'account_information', 'needs_legal_review', 'high', 'legal', 'Classify whether account information services or open banking access are in scope.', 'seed-legal-gap-2026-07-26', ARRAY['Account information features require jurisdiction review'], '{"launch_gate":true}'::jsonb),
    ('regulated-activity-money-transmission', 'regulated_activity_decision', 'GLOBAL', 'money_transmission', 'needs_legal_review', 'critical', 'legal', 'Classify remittance, outbound payment and wallet transfer obligations before any real-money movement.', 'seed-legal-gap-2026-07-26', ARRAY['Money transmission requires legal approval'], '{"launch_gate":true}'::jsonb),
    ('regulated-activity-card-issuing', 'regulated_activity_decision', 'GLOBAL', 'card_issuing', 'needs_legal_review', 'critical', 'legal', 'Classify card issuing, processor sponsorship and card scheme obligations before real card spend.', 'seed-legal-gap-2026-07-26', ARRAY['Card issuing requires issuer and PCI evidence'], '{"launch_gate":true}'::jsonb),
    ('regulated-activity-fx', 'regulated_activity_decision', 'GLOBAL', 'fx', 'needs_legal_review', 'high', 'legal', 'Classify spot FX, markup disclosure, quote expiry and treasury obligations before customer FX launch.', 'seed-legal-gap-2026-07-26', ARRAY['FX rates and fees must be disclosed'], '{"launch_gate":true}'::jsonb),
    ('regulated-activity-crypto-custody', 'regulated_activity_decision', 'GLOBAL', 'crypto_custody', 'needs_legal_review', 'critical', 'legal', 'Classify crypto custody, wallet address control and private-key responsibility before real crypto movement.', 'seed-legal-gap-2026-07-26', ARRAY['Real crypto movement is disabled until approved'], '{"launch_gate":true}'::jsonb),
    ('regulated-activity-stablecoins', 'regulated_activity_decision', 'GLOBAL', 'stablecoins', 'needs_legal_review', 'critical', 'legal', 'Classify stablecoin custody, issuer risk, supported networks and redemption messaging before launch.', 'seed-legal-gap-2026-07-26', ARRAY['Stablecoins are not deposits'], '{"launch_gate":true}'::jsonb),
    ('regulated-activity-savings-deposits', 'regulated_activity_decision', 'GLOBAL', 'savings_deposits', 'needs_legal_review', 'critical', 'legal', 'Classify whether savings goals could be marketed as deposits or protected savings in each jurisdiction.', 'seed-legal-gap-2026-07-26', ARRAY['Savings goals are not deposits unless approved'], '{"launch_gate":true}'::jsonb),
    ('regulated-activity-credit', 'regulated_activity_decision', 'GLOBAL', 'credit', 'out_of_scope', 'high', 'legal', 'Credit and lending are out of scope for the current launch unless product scope changes.', 'seed-out-of-scope-2026-07-26', ARRAY[]::text[], '{"launch_gate":false}'::jsonb),
    ('regulated-activity-investment-services', 'regulated_activity_decision', 'GLOBAL', 'investment_services', 'out_of_scope', 'high', 'legal', 'Investment services are out of scope for the current launch unless product scope changes.', 'seed-out-of-scope-2026-07-26', ARRAY[]::text[], '{"launch_gate":false}'::jsonb)
ON CONFLICT (control_key) DO NOTHING;

INSERT INTO legal_market_access_controls (
    control_key, control_type, jurisdiction, product_scope, status, risk_level, owner_team,
    decision_summary, evidence_reference, required_disclosures, metadata
) VALUES
    ('operating-model-global', 'operating_model', 'GLOBAL', 'platform', 'in_review', 'critical', 'legal', 'Choose licensed entity, registered agent, sponsor bank, EMI/payment institution partner, BaaS partner or software-only launch model.', 'seed-legal-gap-2026-07-26', ARRAY['Real-money features remain blocked until the operating model is approved'], '{"candidate_models":["licensed_entity","registered_agent","sponsor_bank","emi_partner","payment_institution_partner","baas_partner","software_only"]}'::jsonb),
    ('safeguarding-model-global', 'safeguarding_model', 'GLOBAL', 'client_money', 'in_review', 'critical', 'finance', 'Define safeguarding, client money, insolvency treatment and funds segregation with legal and finance before real balances.', 'seed-legal-gap-2026-07-26', ARRAY['Customer money handling depends on licensed provider terms'], '{"required_owners":["legal","finance","risk"]}'::jsonb)
ON CONFLICT (control_key) DO NOTHING;

INSERT INTO legal_market_access_controls (
    control_key, control_type, jurisdiction, product_scope, status, risk_level, owner_team,
    decision_summary, legal_memo_reference, evidence_reference, required_disclosures, metadata
) VALUES
    ('legal-memo-nl-platform', 'legal_memo', 'NL', 'platform', 'draft', 'critical', 'legal', 'Obtain Netherlands legal memo covering payments, e-money, restricted wording, cards, FX, crypto/stablecoins and customer disclosures.', '', 'seed-legal-gap-2026-07-26', ARRAY['No real customer onboarding in NL until memo approved'], '{"review_frequency_days":365}'::jsonb),
    ('legal-memo-eu-platform', 'legal_memo', 'EU', 'platform', 'draft', 'critical', 'legal', 'Obtain EU/EEA legal memo covering PSD2/EMI implications, GDPR, DORA applicability, MiCA where relevant and passporting model.', '', 'seed-legal-gap-2026-07-26', ARRAY['EU launch requires jurisdiction-specific confirmation'], '{"review_frequency_days":365}'::jsonb),
    ('legal-memo-us-platform', 'legal_memo', 'US', 'platform', 'draft', 'critical', 'legal', 'Obtain United States memo covering money transmission, sponsor-bank model, card program, crypto/stablecoin and state eligibility.', '', 'seed-legal-gap-2026-07-26', ARRAY['US launch requires state-by-state eligibility review'], '{"review_frequency_days":365}'::jsonb)
ON CONFLICT (control_key) DO NOTHING;

INSERT INTO legal_market_access_controls (
    control_key, control_type, jurisdiction, product_scope, status, risk_level, owner_team,
    decision_summary, evidence_reference, required_disclosures, metadata
) VALUES
    ('product-term-bank-global', 'product_term_approval', 'GLOBAL', 'bank', 'requires_disclaimer', 'critical', 'legal', 'Review and approve whether the product may use the word bank or banking in each jurisdiction.', 'seed-legal-gap-2026-07-26', ARRAY['Do not imply the company is a licensed bank unless counsel approves'], '{"restricted_term":true}'::jsonb),
    ('product-term-savings-global', 'product_term_approval', 'GLOBAL', 'savings', 'requires_disclaimer', 'critical', 'legal', 'Review and approve whether savings goal wording could imply deposit-taking, interest or statutory protection.', 'seed-legal-gap-2026-07-26', ARRAY['Savings goals are planning tools unless a licensed deposit model is approved'], '{"restricted_term":true}'::jsonb),
    ('product-term-deposit-global', 'product_term_approval', 'GLOBAL', 'deposit', 'prohibited', 'critical', 'legal', 'Do not use deposit wording until legal confirms deposit-taking permissions and protection disclosures.', 'seed-legal-gap-2026-07-26', ARRAY['Deposit wording is prohibited without legal approval'], '{"restricted_term":true}'::jsonb)
ON CONFLICT (control_key) DO NOTHING;

INSERT INTO legal_market_access_controls (
    control_key, control_type, jurisdiction, provider_category, provider_name, status, risk_level, owner_team,
    decision_summary, contract_reference, evidence_reference, required_disclosures, metadata
) VALUES
    ('provider-contract-bank-payment', 'provider_contract', 'GLOBAL', 'bank_payment_provider', 'pending_licensed_provider', 'in_review', 'critical', 'operations', 'Sign licensed bank/payment provider contract before real IBAN/account issuance or real payment movement.', '', 'seed-legal-gap-2026-07-26', ARRAY['Real IBAN/account issuance requires licensed provider contract'], '{"required_for":["iban","account_issuance","sepa","wallet_balances"]}'::jsonb),
    ('provider-contract-card-issuer', 'provider_contract', 'GLOBAL', 'card_issuer_processor', 'pending_card_processor', 'in_review', 'critical', 'operations', 'Sign card issuer/processor contract before real card creation or authorization handling.', '', 'seed-legal-gap-2026-07-26', ARRAY['Real card issuing requires contracted issuer/processor'], '{"required_for":["card_create","authorization","clearing","disputes"]}'::jsonb),
    ('provider-contract-kyc-aml', 'provider_contract', 'GLOBAL', 'kyc_aml_provider', 'pending_kyc_aml_provider', 'in_review', 'critical', 'compliance', 'Sign KYC, sanctions, PEP, adverse media and transaction monitoring provider contracts before onboarding real customers.', '', 'seed-legal-gap-2026-07-26', ARRAY['Real onboarding requires contracted KYC/AML providers'], '{"required_for":["identity","sanctions","pep","adverse_media","ongoing_monitoring"]}'::jsonb),
    ('provider-contract-crypto-custody', 'provider_contract', 'GLOBAL', 'crypto_custody_provider', 'pending_custody_provider', 'in_review', 'critical', 'operations', 'Sign custody/provider contract or explicitly keep real crypto and stablecoin movement disabled.', '', 'seed-legal-gap-2026-07-26', ARRAY['Real crypto movement remains disabled until custody is approved'], '{"required_for":["crypto_wallets","stablecoins","withdrawals","deposits"]}'::jsonb)
ON CONFLICT (control_key) DO NOTHING;

INSERT INTO legal_market_access_controls (
    control_key, control_type, jurisdiction, product_scope, status, risk_level, owner_team,
    decision_summary, policy_version, evidence_reference, required_disclosures, metadata
) VALUES
    ('policy-terms-of-service', 'policy_document', 'GLOBAL', 'terms_of_service', 'draft', 'critical', 'legal', 'Terms of service must be versioned, approved and published before customer onboarding.', 'draft-2026-07-26', 'seed-legal-gap-2026-07-26', ARRAY['Terms must identify the licensed provider or software-only limitation'], '{"customer_facing":true}'::jsonb),
    ('policy-privacy-notice', 'policy_document', 'GLOBAL', 'privacy_notice', 'draft', 'critical', 'legal', 'Privacy notice must be legal-approved and aligned with data inventory, lawful basis, DSAR and retention controls.', 'draft-2026-07-26', 'seed-legal-gap-2026-07-26', ARRAY['Privacy notice must be published before tracking or onboarding'], '{"customer_facing":true}'::jsonb),
    ('policy-fee-schedule', 'policy_document', 'GLOBAL', 'fee_schedule', 'draft', 'high', 'finance', 'Fee schedule must disclose transfer, card, FX, crypto/stablecoin and operational fees before charging customers.', 'draft-2026-07-26', 'seed-legal-gap-2026-07-26', ARRAY['Fees must be shown before execution'], '{"customer_facing":true}'::jsonb),
    ('policy-risk-disclosures', 'policy_document', 'GLOBAL', 'risk_disclosures', 'draft', 'critical', 'risk', 'Risk disclosures must cover payment execution timing, FX, cards, crypto/stablecoins, provider dependency and no-deposit caveats.', 'draft-2026-07-26', 'seed-legal-gap-2026-07-26', ARRAY['High-risk product disclosures must be accepted before use'], '{"customer_facing":true}'::jsonb),
    ('policy-complaints', 'policy_document', 'GLOBAL', 'complaints_policy', 'draft', 'high', 'compliance', 'Complaints policy must define intake, SLA, escalation, evidence retention and regulator referral paths.', 'draft-2026-07-26', 'seed-legal-gap-2026-07-26', ARRAY['Complaint channels must be visible to customers'], '{"customer_facing":true}'::jsonb),
    ('policy-chargeback-disputes', 'policy_document', 'GLOBAL', 'chargeback_dispute_policy', 'draft', 'high', 'operations', 'Chargeback and dispute policy must explain eligibility, timing, evidence and processor/scheme dependencies.', 'draft-2026-07-26', 'seed-legal-gap-2026-07-26', ARRAY['Card dispute rights depend on issuer/processor program terms'], '{"customer_facing":true}'::jsonb)
ON CONFLICT (control_key) DO NOTHING;

INSERT INTO legal_market_access_controls (
    control_key, control_type, jurisdiction, product_scope, status, risk_level, owner_team,
    decision_summary, evidence_reference, required_disclosures, metadata
) VALUES
    ('jurisdiction-rule-nl-platform', 'jurisdiction_product_rule', 'NL', 'platform', 'test_only', 'critical', 'legal', 'Netherlands product access remains test-money only until legal memo, provider contracts and restricted-wording approval are attached.', 'seed-legal-gap-2026-07-26', ARRAY['Test money only', 'No real banking services until approved'], '{"default_customer_access":"blocked_for_real_money"}'::jsonb),
    ('jurisdiction-rule-eu-platform', 'jurisdiction_product_rule', 'EU', 'platform', 'test_only', 'critical', 'legal', 'EU/EEA product access remains test-money only until jurisdiction-specific legal approvals and provider passporting/contract evidence are attached.', 'seed-legal-gap-2026-07-26', ARRAY['Test money only', 'Local eligibility checks required'], '{"default_customer_access":"blocked_for_real_money"}'::jsonb),
    ('jurisdiction-rule-us-platform', 'jurisdiction_product_rule', 'US', 'platform', 'blocked', 'critical', 'legal', 'United States real-money access is blocked until state eligibility, money-transmission/sponsor-bank and crypto/card program analysis is approved.', 'seed-legal-gap-2026-07-26', ARRAY['US access blocked for real-money launch'], '{"default_customer_access":"blocked"}'::jsonb)
ON CONFLICT (control_key) DO NOTHING;

INSERT INTO data_archival_policies (
    table_name, data_category, retention_days, archive_after_days, archive_strategy, archive_destination,
    legal_hold_supported, delete_after_archive, evidence_required, status, owner
) VALUES
    ('legal_market_access_controls', 'operational', 2555, 365, 'cold_storage_export', 'legal-market-access-archive', true, false, true, 'active', 'legal')
ON CONFLICT (table_name) DO NOTHING;

INSERT INTO privacy_data_inventory (
    table_name, field_name, data_category, classification, lawful_basis, retention_policy, residency_scope, encrypted_at_rest, owner, notes
) VALUES
    ('legal_market_access_controls', '*', 'audit', 'confidential', 'legal_obligation/risk_management', 'audit_logs_default', 'default', false, 'legal', 'Legal market-access decisions, provider contract references, customer-policy approvals, jurisdiction rules and evidence pointers; no raw legal contracts or secrets stored')
ON CONFLICT (system_name, table_name, field_name) DO NOTHING;
