-- ============================================================================
-- MIGRATION: Complete Schema Updates for Pricing & Lead Requests
-- ============================================================================

BEGIN;

-- ============================================================================
-- 1. Update pricing_packages table with new columns
-- ============================================================================

ALTER TABLE pricing_packages 
    DROP COLUMN IF EXISTS user_role_profile_id,
    ADD COLUMN IF NOT EXISTS package_type VARCHAR(50) NOT NULL DEFAULT 'TRACECOIN_BUNDLE',
    ADD COLUMN IF NOT EXISTS applicable_roles TEXT[] DEFAULT '{}',
    ADD COLUMN IF NOT EXISTS tracecoins_amount INTEGER DEFAULT 0,
    ADD COLUMN IF NOT EXISTS valid_from TIMESTAMPTZ,
    ADD COLUMN IF NOT EXISTS valid_until TIMESTAMPTZ,
    ADD COLUMN IF NOT EXISTS is_promotional BOOLEAN DEFAULT false;

-- Add index for package lookup
CREATE INDEX IF NOT EXISTS idx_pricing_packages_type ON pricing_packages(package_type);

-- ============================================================================
-- 2. Update payments table with new columns
-- ============================================================================

ALTER TABLE payments
    ADD COLUMN IF NOT EXISTS package_id UUID,
    ADD COLUMN IF NOT EXISTS razorpay_order_id VARCHAR(255),
    ADD COLUMN IF NOT EXISTS razorpay_payment_id VARCHAR(255),
    ADD COLUMN IF NOT EXISTS tracecoins_credited INTEGER DEFAULT 0,
    ADD COLUMN IF NOT EXISTS verified_at TIMESTAMPTZ;

-- Add foreign key if not exists
ALTER TABLE payments
    ADD CONSTRAINT payments_package_id_fkey 
    FOREIGN KEY (package_id) REFERENCES pricing_packages(id) ON DELETE SET NULL;

CREATE INDEX IF NOT EXISTS idx_payments_package_id ON payments(package_id);
CREATE INDEX IF NOT EXISTS idx_payments_razorpay_order_id ON payments(razorpay_order_id);

-- ============================================================================
-- 3. Create lead_requests table
-- ============================================================================

CREATE TABLE IF NOT EXISTS lead_requests (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    lead_id UUID NOT NULL REFERENCES leads(id) ON DELETE CASCADE,
    user_role_profile_id UUID NOT NULL REFERENCES user_role_profiles(id) ON DELETE CASCADE,
    customer_user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    status VARCHAR(50) NOT NULL DEFAULT 'PENDING',
    tracecoins_reserved INTEGER NOT NULL DEFAULT 25,
    message TEXT,
    expires_at TIMESTAMPTZ NOT NULL,
    accepted_at TIMESTAMPTZ,
    rejected_at TIMESTAMPTZ,
    rejected_reason TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_lead_requests_lead_id ON lead_requests(lead_id);
CREATE INDEX IF NOT EXISTS idx_lead_requests_user_role_profile_id ON lead_requests(user_role_profile_id);
CREATE INDEX IF NOT EXISTS idx_lead_requests_customer_user_id ON lead_requests(customer_user_id);
CREATE INDEX IF NOT EXISTS idx_lead_requests_status ON lead_requests(status);
CREATE INDEX IF NOT EXISTS idx_lead_requests_expires_at ON lead_requests(expires_at);

-- ============================================================================
-- 4. Add display_code to company_profiles
-- ============================================================================

ALTER TABLE company_profiles
    ADD COLUMN IF NOT EXISTS display_code VARCHAR(20) UNIQUE;

-- ============================================================================
-- 5. Add display_code to customer_profiles
-- ============================================================================

ALTER TABLE customer_profiles
    ADD COLUMN IF NOT EXISTS display_code VARCHAR(20) UNIQUE;

-- ============================================================================
-- 6. Add display_code to job_seeker_profiles
-- ============================================================================

ALTER TABLE job_seeker_profiles
    ADD COLUMN IF NOT EXISTS display_code VARCHAR(20) UNIQUE;

-- ============================================================================
-- 7. Add free_requirement_slots and purchased_requirement_slots to customer_profiles
-- ============================================================================

ALTER TABLE customer_profiles
    ADD COLUMN IF NOT EXISTS free_requirement_slots INTEGER DEFAULT 2,
    ADD COLUMN IF NOT EXISTS purchased_requirement_slots INTEGER DEFAULT 0;

-- ============================================================================
-- 8. Update leads table with new columns
-- ============================================================================

ALTER TABLE leads
    ADD COLUMN IF NOT EXISTS customer_user_id UUID REFERENCES users(id),
    ADD COLUMN IF NOT EXISTS max_acceptances INTEGER DEFAULT 10,
    ADD COLUMN IF NOT EXISTS current_acceptances INTEGER DEFAULT 0,
    ADD COLUMN IF NOT EXISTS expires_at TIMESTAMPTZ,
    ADD COLUMN IF NOT EXISTS cover_image_url TEXT;

-- ============================================================================
-- 9. Add tracecoins_reserved column to lead_requests for proper tracking
-- ============================================================================

-- Already added in step 3

-- ============================================================================
-- 10. Create function to auto-generate display codes
-- ============================================================================

CREATE OR REPLACE FUNCTION generate_display_code(prefix VARCHAR(10))
RETURNS VARCHAR(20) AS $$
DECLARE
    new_code VARCHAR(20);
    seq_num INTEGER;
BEGIN
    -- Get the next sequence number for this prefix
    SELECT COALESCE(
        (SELECT MAX(CAST(SUBSTRING(code FROM 4) AS INTEGER)) + 1
         FROM (
             SELECT display_code as code FROM company_profiles WHERE display_code LIKE prefix || '%'
             UNION ALL
             SELECT display_code as code FROM customer_profiles WHERE display_code LIKE prefix || '%'
             UNION ALL
             SELECT display_code as code FROM job_seeker_profiles WHERE display_code LIKE prefix || '%'
         ) all_codes
        ),
        1
    ) INTO seq_num;
    
    new_code := prefix || LPAD(seq_num::TEXT, 4, '0');
    RETURN new_code;
END;
$$ LANGUAGE plpgsql;

-- ============================================================================
-- 11. Create indexes for performance
-- ============================================================================

CREATE INDEX IF NOT EXISTS idx_leads_customer_user_id ON leads(customer_user_id);
CREATE INDEX IF NOT EXISTS idx_leads_status_expires ON leads(status, expires_at);
CREATE INDEX IF NOT EXISTS idx_user_role_profiles_role_key ON user_role_profiles(role_key);

-- ============================================================================
-- 12. Create tracecoin ledger entry types enum support
-- ============================================================================

-- Add transaction_type values for ledger tracking
-- The ledger already has 'type' column, ensure we have proper entries

-- ============================================================================
-- 13. Add indexes for verification queries
-- ============================================================================

CREATE INDEX IF NOT EXISTS idx_verifications_user_role_profile_id ON verifications(user_role_profile_id);
CREATE INDEX IF NOT EXISTS idx_verifications_status ON verifications(status);
CREATE INDEX IF NOT EXISTS idx_verification_requests_user_role_profile_id ON verification_requests(user_role_profile_id);

-- ============================================================================
-- 14. Add tracecoin refund support to ledger
-- ============================================================================

-- Reserve tracecoins for lead request
CREATE OR REPLACE FUNCTION reserve_tracecoins_for_lead_request(
    p_user_id UUID,
    p_amount INTEGER,
    p_lead_request_id UUID
) RETURNS BOOLEAN AS $$
DECLARE
    v_wallet_id UUID;
    v_balance BIGINT;
BEGIN
    -- Get wallet
    SELECT id, balance INTO v_wallet_id, v_balance
    FROM tracecoin_wallets
    WHERE user_id = p_user_id
    FOR UPDATE;
    
    IF v_wallet_id IS NULL THEN
        RETURN FALSE;
    END IF;
    
    IF v_balance < p_amount THEN
        RETURN FALSE;
    END IF;
    
    -- Deduct from balance (reserved, not yet spent)
    UPDATE tracecoin_wallets 
    SET balance = balance - p_amount, 
        reserved = COALESCE(reserved, 0) + p_amount,
        updated_at = NOW()
    WHERE id = v_wallet_id;
    
    -- Add ledger entry
    INSERT INTO tracecoin_ledger (wallet_id, type, amount, balance_after, reference_type, reference_id, reason)
    VALUES (v_wallet_id, 'RESERVE', -p_amount, v_balance - p_amount, 'LEAD_REQUEST', p_lead_request_id, 'Lead request reservation');
    
    RETURN TRUE;
END;
$$ LANGUAGE plpgsql;

-- Confirm tracecoins (when customer accepts)
CREATE OR REPLACE FUNCTION confirm_tracecoins_for_lead(
    p_user_id UUID,
    p_amount INTEGER,
    p_lead_request_id UUID
) RETURNS BOOLEAN AS $$
DECLARE
    v_wallet_id UUID;
    v_balance BIGINT;
BEGIN
    -- Get wallet
    SELECT id, balance, COALESCE(reserved, 0) INTO v_wallet_id, v_balance, v_balance
    FROM tracecoin_wallets
    WHERE user_id = p_user_id
    FOR UPDATE;
    
    IF v_wallet_id IS NULL THEN
        RETURN FALSE;
    END IF;
    
    -- Move from reserved to spent
    UPDATE tracecoin_wallets 
    SET reserved = reserved - p_amount,
        updated_at = NOW()
    WHERE id = v_wallet_id;
    
    -- Add ledger entry for confirmation
    INSERT INTO tracecoin_ledger (wallet_id, type, amount, balance_after, reference_type, reference_id, reason)
    VALUES (v_wallet_id, 'SPEND', -p_amount, v_balance, 'LEAD_REQUEST', p_lead_request_id, 'Lead request accepted');
    
    RETURN TRUE;
END;
$$ LANGUAGE plpgsql;

-- Release tracecoins (when customer rejects or request expires)
CREATE OR REPLACE FUNCTION release_tracecoins_for_lead(
    p_user_id UUID,
    p_amount INTEGER,
    p_lead_request_id UUID
) RETURNS BOOLEAN AS $$
DECLARE
    v_wallet_id UUID;
    v_balance BIGINT;
BEGIN
    -- Get wallet
    SELECT id, balance INTO v_wallet_id, v_balance
    FROM tracecoin_wallets
    WHERE user_id = p_user_id
    FOR UPDATE;
    
    IF v_wallet_id IS NULL THEN
        RETURN FALSE;
    END IF;
    
    -- Return to available balance from reserved
    UPDATE tracecoin_wallets 
    SET balance = balance + p_amount,
        reserved = reserved - p_amount,
        updated_at = NOW()
    WHERE id = v_wallet_id;
    
    -- Add ledger entry for release
    INSERT INTO tracecoin_ledger (wallet_id, type, amount, balance_after, reference_type, reference_id, reason)
    VALUES (v_wallet_id, 'RELEASE', p_amount, v_balance + p_amount, 'LEAD_REQUEST', p_lead_request_id, 'Lead request rejected/expired');
    
    RETURN TRUE;
END;
$$ LANGUAGE plpgsql;

-- ============================================================================
-- 15. Update tracecoin_wallets to have reserved column
-- ============================================================================

ALTER TABLE tracecoin_wallets
    ADD COLUMN IF NOT EXISTS reserved BIGINT DEFAULT 0;

COMMIT;
