-- =====================================================
-- P2P MERCHANT SYSTEM - PHASE 4
-- Merchant tiers, stats, and advanced features
-- =====================================================

-- =====================================================
-- MERCHANT TIERS TABLE
-- =====================================================
CREATE TABLE IF NOT EXISTS public.p2p_merchant_tiers (
  user_id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,

  -- Tier info
  tier VARCHAR(20) DEFAULT 'lite' CHECK (tier IN ('lite', 'super', 'diamond')),

  -- Deposit (for higher tiers)
  deposit_amount DECIMAL(18,2) DEFAULT 0,
  deposit_token VARCHAR(10) DEFAULT 'HEZ',
  deposit_tx_hash TEXT,
  deposit_locked_at TIMESTAMPTZ,

  -- Limits based on tier
  max_pending_orders INT DEFAULT 5,
  max_order_amount DECIMAL(18,2) DEFAULT 10000,
  featured_ads_allowed INT DEFAULT 0,

  -- Application status
  application_status VARCHAR(20) CHECK (application_status IN ('pending', 'approved', 'rejected', 'suspended')),
  applied_at TIMESTAMPTZ,
  applied_for_tier VARCHAR(20),
  approved_at TIMESTAMPTZ,
  approved_by UUID REFERENCES auth.users(id),
  rejection_reason TEXT,

  -- Review
  last_review_at TIMESTAMPTZ,
  next_review_at TIMESTAMPTZ,
  review_notes TEXT,

  -- Timestamps
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indexes
CREATE INDEX idx_merchant_tiers_tier ON public.p2p_merchant_tiers(tier);
CREATE INDEX idx_merchant_tiers_pending ON public.p2p_merchant_tiers(application_status)
  WHERE application_status = 'pending';

-- Enable RLS
ALTER TABLE public.p2p_merchant_tiers ENABLE ROW LEVEL SECURITY;

-- Users can view their own tier
CREATE POLICY "p2p_merchant_own_read" ON public.p2p_merchant_tiers
  FOR SELECT USING (user_id = auth.uid());

-- Users can apply for tier (insert/update own)
CREATE POLICY "p2p_merchant_own_apply" ON public.p2p_merchant_tiers
  FOR INSERT WITH CHECK (user_id = auth.uid());

CREATE POLICY "p2p_merchant_own_update" ON public.p2p_merchant_tiers
  FOR UPDATE USING (user_id = auth.uid())
  WITH CHECK (
    -- Can only update application_status to 'pending' and applied_for_tier
    user_id = auth.uid()
  );

-- Public can see tier info (for display in ads)
CREATE POLICY "p2p_merchant_public_tier" ON public.p2p_merchant_tiers
  FOR SELECT USING (true);

-- Admins can manage all
CREATE POLICY "p2p_merchant_admin" ON public.p2p_merchant_tiers
  FOR ALL USING (
    EXISTS (
      SELECT 1 FROM public.admin_roles
      WHERE user_id = auth.uid() AND role IN ('admin')
    )
  );

-- =====================================================
-- MERCHANT STATS TABLE (Rolling 30-day stats)
-- =====================================================
CREATE TABLE IF NOT EXISTS public.p2p_merchant_stats (
  user_id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,

  -- Volume stats (30 day rolling)
  total_volume_30d DECIMAL(18,2) DEFAULT 0,
  [REDACTED] INT DEFAULT 0,
  buy_volume_30d DECIMAL(18,2) DEFAULT 0,
  sell_volume_30d DECIMAL(18,2) DEFAULT 0,

  -- Performance metrics
  completion_rate_30d DECIMAL(5,2) DEFAULT 0,
  avg_release_time_minutes INT,
  avg_payment_time_minutes INT,

  -- Lifetime stats
  total_volume_lifetime DECIMAL(18,2) DEFAULT 0,
  total_trades_lifetime INT DEFAULT 0,

  -- Ranking
  volume_rank INT,
  trade_count_rank INT,

  -- Timestamps
  last_calculated_at TIMESTAMPTZ DEFAULT NOW(),
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indexes
CREATE INDEX idx_merchant_stats_volume ON public.p2p_merchant_stats(total_volume_30d DESC);
CREATE INDEX idx_merchant_stats_trades ON public.p2p_merchant_stats(total_trades_30d DESC);

-- Enable RLS
ALTER TABLE public.p2p_merchant_stats ENABLE ROW LEVEL SECURITY;

-- Public read (for leaderboards)
CREATE POLICY "p2p_merchant_stats_public" ON public.p2p_merchant_stats
  FOR SELECT USING (true);

-- =====================================================
-- FEATURED ADS TABLE
-- =====================================================
CREATE TABLE IF NOT EXISTS public.p2p_featured_ads (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  offer_id UUID NOT NULL REFERENCES public.p2p_fiat_offers(id) ON DELETE CASCADE,
  user_id UUID NOT NULL REFERENCES auth.users(id),

  -- Featuring details
  position INT DEFAULT 1, -- 1 = top, 2 = second, etc.
  start_at TIMESTAMPTZ NOT NULL,
  end_at TIMESTAMPTZ NOT NULL,

  -- Payment
  fee_amount DECIMAL(18,2) NOT NULL,
  fee_token VARCHAR(10) DEFAULT 'HEZ',
  fee_tx_hash TEXT,
  paid_at TIMESTAMPTZ,

  -- Status
  status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'active', 'expired', 'cancelled')),

  -- Timestamps
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indexes
CREATE INDEX idx_featured_ads_active ON public.p2p_featured_ads(status, start_at, end_at)
  WHERE status = 'active';
CREATE INDEX idx_featured_ads_offer ON public.p2p_featured_ads(offer_id);

-- Enable RLS
ALTER TABLE public.p2p_featured_ads ENABLE ROW LEVEL SECURITY;

-- Users can view active featured ads
CREATE POLICY "p2p_featured_public_read" ON public.p2p_featured_ads
  FOR SELECT USING (status = 'active' OR user_id = auth.uid());

-- Users can create featured ads for own offers
CREATE POLICY "p2p_featured_own_create" ON public.p2p_featured_ads
  FOR INSERT WITH CHECK (
    user_id = auth.uid() AND
    EXISTS (
      SELECT 1 FROM public.p2p_fiat_offers
      WHERE id = offer_id AND seller_id = auth.uid()
    )
  );

-- =====================================================
-- USER PAYMENT METHODS (Saved methods)
-- =====================================================
CREATE TABLE IF NOT EXISTS public.p2p_user_payment_methods (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
  payment_method_id UUID NOT NULL REFERENCES public.payment_methods(id),

  -- Account details (encrypted)
  account_details_encrypted TEXT NOT NULL,
  account_name TEXT, -- For display/verification

  -- Settings
  is_default BOOLEAN DEFAULT FALSE,
  is_verified BOOLEAN DEFAULT FALSE,
  verified_at TIMESTAMPTZ,

  -- Timestamps
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indexes
CREATE INDEX idx_user_payment_methods_user ON public.p2p_user_payment_methods(user_id);
CREATE UNIQUE INDEX idx_user_payment_methods_default ON public.p2p_user_payment_methods(user_id)
  WHERE is_default = true;

-- Enable RLS
ALTER TABLE public.p2p_user_payment_methods ENABLE ROW LEVEL SECURITY;

-- Users can manage own payment methods
CREATE POLICY "p2p_user_payment_own" ON public.p2p_user_payment_methods
  FOR ALL USING (user_id = auth.uid());

-- =====================================================
-- TIER REQUIREMENTS CONSTANTS
-- =====================================================
CREATE TABLE IF NOT EXISTS public.p2p_tier_requirements (
  tier VARCHAR(20) PRIMARY KEY,
  min_trades INT NOT NULL,
  min_completion_rate DECIMAL(5,2) NOT NULL,
  min_volume_30d DECIMAL(18,2) NOT NULL,
  deposit_required DECIMAL(18,2) NOT NULL,
  deposit_token VARCHAR(10) DEFAULT 'HEZ',
  max_pending_orders INT NOT NULL,
  max_order_amount DECIMAL(18,2) NOT NULL,
  featured_ads_allowed INT NOT NULL,
  description TEXT
);

-- Insert tier requirements
INSERT INTO public.p2p_tier_requirements (tier, min_trades, min_completion_rate, min_volume_30d, deposit_required, max_pending_orders, max_order_amount, featured_ads_allowed, description)
VALUES
  ('lite', 0, 0, 0, 0, 5, 10000, 0, 'Basic tier for all verified users'),
  ('super', 20, 90, 5000, 10000, 20, 100000, 3, 'Professional trader tier with higher limits'),
  ('diamond', 100, 95, 25000, 50000, 50, 150000, 10, 'Elite merchant tier with maximum privileges')
ON CONFLICT (tier) DO UPDATE SET
  min_trades = EXCLUDED.min_trades,
  min_completion_rate = EXCLUDED.min_completion_rate,
  min_volume_30d = EXCLUDED.min_volume_30d,
  deposit_required = EXCLUDED.deposit_required,
  max_pending_orders = EXCLUDED.max_pending_orders,
  max_order_amount = EXCLUDED.max_order_amount,
  featured_ads_allowed = EXCLUDED.featured_ads_allowed,
  description = EXCLUDED.description;

-- =====================================================
-- FUNCTION: Check Tier Eligibility
-- =====================================================
CREATE OR REPLACE FUNCTION public.check_tier_eligibility(
  p_user_id UUID,
  p_target_tier VARCHAR(20)
) RETURNS TABLE(
  eligible BOOLEAN,
  missing_requirements TEXT[]
) AS $$
DECLARE
  v_reputation RECORD;
  v_stats RECORD;
  v_requirements RECORD;
  v_missing TEXT[] := '{}';
BEGIN
  -- Get requirements
  SELECT * INTO v_requirements
  FROM public.p2p_tier_requirements
  WHERE tier = p_target_tier;

  IF NOT FOUND THEN
    eligible := FALSE;
    missing_requirements := ARRAY['Invalid tier'];
    RETURN NEXT;
    RETURN;
  END IF;

  -- Get user reputation
  SELECT * INTO v_reputation
  FROM public.p2p_reputation
  WHERE user_id = p_user_id;

  -- Get user stats
  SELECT * INTO v_stats
  FROM public.p2p_merchant_stats
  WHERE user_id = p_user_id;

  -- Check completed trades
  IF COALESCE(v_reputation.completed_trades, 0) < v_requirements.min_trades THEN
    v_missing := array_append(v_missing,
      format('Need %s completed trades (have %s)',
        v_requirements.min_trades,
        COALESCE(v_reputation.completed_trades, 0)));
  END IF;

  -- Check completion rate
  IF COALESCE(v_stats.completion_rate_30d, 0) < v_requirements.min_completion_rate THEN
    v_missing := array_append(v_missing,
      format('Need %s%% completion rate (have %s%%)',
        v_requirements.min_completion_rate,
        COALESCE(v_stats.completion_rate_30d, 0)));
  END IF;

  -- Check 30-day volume
  IF COALESCE(v_stats.total_volume_30d, 0) < v_requirements.min_volume_30d THEN
    v_missing := array_append(v_missing,
      format('Need $%s 30-day volume (have $%s)',
        v_requirements.min_volume_30d,
        COALESCE(v_stats.total_volume_30d, 0)));
  END IF;

  -- Check deposit requirement
  IF v_requirements.deposit_required > 0 THEN
    v_missing := array_append(v_missing,
      format('Deposit of %s %s required',
        v_requirements.deposit_required,
        v_requirements.deposit_token));
  END IF;

  eligible := array_length(v_missing, 1) IS NULL OR array_length(v_missing, 1) = 0;
  missing_requirements := v_missing;

  RETURN NEXT;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- =====================================================
-- FUNCTION: Apply for Tier Upgrade
-- =====================================================
CREATE OR REPLACE FUNCTION public.apply_for_tier_upgrade(
  p_user_id UUID,
  p_target_tier VARCHAR(20)
) RETURNS TABLE(
  success BOOLEAN,
  message TEXT
) AS $$
DECLARE
  v_eligibility RECORD;
  v_current_tier RECORD;
BEGIN
  -- Check current tier
  SELECT * INTO v_current_tier
  FROM public.p2p_merchant_tiers
  WHERE user_id = p_user_id;

  -- Check if already at or above target tier
  IF v_current_tier IS NOT NULL THEN
    IF v_current_tier.tier = p_target_tier THEN
      success := FALSE;
      message := 'You are already at this tier';
      RETURN NEXT;
      RETURN;
    END IF;

    IF v_current_tier.application_status = 'pending' THEN
      success := FALSE;
      message := 'You already have a pending application';
      RETURN NEXT;
      RETURN;
    END IF;
  END IF;

  -- Check eligibility
  SELECT * INTO v_eligibility
  FROM public.check_tier_eligibility(p_user_id, p_target_tier);

  IF NOT v_eligibility.eligible THEN
    success := FALSE;
    message := 'Not eligible: ' || array_to_string(v_eligibility.missing_requirements, ', ');
    RETURN NEXT;
    RETURN;
  END IF;

  -- Create or update application
  INSERT INTO public.p2p_merchant_tiers (
    user_id, application_status, applied_at, applied_for_tier
  ) VALUES (
    p_user_id, 'pending', NOW(), p_target_tier
  )
  ON CONFLICT (user_id) DO UPDATE SET
    application_status = 'pending',
    applied_at = NOW(),
    applied_for_tier = p_target_tier,
    updated_at = NOW();

  success := TRUE;
  message := 'Application submitted successfully';

  RETURN NEXT;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- =====================================================
-- FUNCTION: Approve Tier Application (Admin)
-- =====================================================
CREATE OR REPLACE FUNCTION public.approve_tier_application(
  p_user_id UUID,
  p_admin_id UUID
) RETURNS void AS $$
DECLARE
  v_application RECORD;
  v_requirements RECORD;
BEGIN
  -- Get application
  SELECT * INTO v_application
  FROM public.p2p_merchant_tiers
  WHERE user_id = p_user_id AND application_status = 'pending';

  IF NOT FOUND THEN
    RAISE EXCEPTION 'No pending application found';
  END IF;

  -- Get tier requirements
  SELECT * INTO v_requirements
  FROM public.p2p_tier_requirements
  WHERE tier = v_application.applied_for_tier;

  -- Update tier
  UPDATE public.p2p_merchant_tiers
  SET
    tier = v_application.applied_for_tier,
    application_status = 'approved',
    approved_at = NOW(),
    approved_by = p_admin_id,
    max_pending_orders = v_requirements.max_pending_orders,
    max_order_amount = v_requirements.max_order_amount,
    featured_ads_allowed = v_requirements.featured_ads_allowed,
    updated_at = NOW()
  WHERE user_id = p_user_id;

  -- Create notification
  PERFORM public.create_p2p_notification(
    p_user_id,
    'system',
    'Tier Upgrade Approved!',
    format('Congratulations! You have been upgraded to %s tier.', v_application.applied_for_tier),
    NULL,
    NULL,
    '/p2p/merchant'
  );
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- =====================================================
-- FUNCTION: Calculate Merchant Stats
-- =====================================================
CREATE OR REPLACE FUNCTION public.calculate_merchant_stats(p_user_id UUID)
RETURNS void AS $$
DECLARE
  v_stats RECORD;
BEGIN
  -- Calculate 30-day stats
  SELECT
    COUNT(*) as trades_30d,
    COALESCE(SUM(fiat_amount), 0) as volume_30d,
    COALESCE(SUM(CASE WHEN buyer_id = p_user_id THEN fiat_amount ELSE 0 END), 0) as buy_volume,
    COALESCE(SUM(CASE WHEN seller_id = p_user_id THEN fiat_amount ELSE 0 END), 0) as sell_volume,
    COALESCE(
      (COUNT(*) FILTER (WHERE status = 'completed')::DECIMAL /
       NULLIF(COUNT(*), 0) * 100), 0
    ) as completion_rate,
    AVG(EXTRACT(EPOCH FROM (seller_confirmed_at - buyer_marked_paid_at)) / 60)
      FILTER (WHERE seller_id = p_user_id AND seller_confirmed_at IS NOT NULL) as avg_release,
    AVG(EXTRACT(EPOCH FROM (buyer_marked_paid_at - created_at)) / 60)
      FILTER (WHERE buyer_id = p_user_id AND buyer_marked_paid_at IS NOT NULL) as avg_payment
  INTO v_stats
  FROM public.p2p_fiat_trades
  WHERE (buyer_id = p_user_id OR seller_id = p_user_id)
    AND created_at >= NOW() - INTERVAL '30 days';

  -- Upsert stats
  INSERT INTO public.p2p_merchant_stats (
    user_id,
    total_volume_30d,
    total_trades_30d,
    buy_volume_30d,
    sell_volume_30d,
    completion_rate_30d,
    avg_release_time_minutes,
    avg_payment_time_minutes,
    last_calculated_at
  ) VALUES (
    p_user_id,
    v_stats.volume_30d,
    v_stats.trades_30d,
    v_stats.buy_volume,
    v_stats.sell_volume,
    v_stats.completion_rate,
    v_stats.avg_release::INT,
    v_stats.avg_payment::INT,
    NOW()
  )
  ON CONFLICT (user_id) DO UPDATE SET
    total_volume_30d = v_stats.volume_30d,
    total_trades_30d = v_stats.trades_30d,
    buy_volume_30d = v_stats.buy_volume,
    sell_volume_30d = v_stats.sell_volume,
    completion_rate_30d = v_stats.completion_rate,
    avg_release_time_minutes = v_stats.avg_release::INT,
    avg_payment_time_minutes = v_stats.avg_payment::INT,
    last_calculated_at = NOW();
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- =====================================================
-- TRIGGER: Update stats on trade completion
-- =====================================================
CREATE OR REPLACE FUNCTION update_merchant_stats_on_trade()
RETURNS TRIGGER AS $$
BEGIN
  IF NEW.status = 'completed' AND (OLD.status IS NULL OR OLD.status != 'completed') THEN
    PERFORM public.calculate_merchant_stats(NEW.buyer_id);
    PERFORM public.calculate_merchant_stats(NEW.seller_id);
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

CREATE TRIGGER trigger_update_merchant_stats
  AFTER UPDATE ON public.p2p_fiat_trades
  FOR EACH ROW EXECUTE FUNCTION update_merchant_stats_on_trade();

-- =====================================================
-- ADD is_featured COLUMN TO OFFERS
-- =====================================================
ALTER TABLE public.p2p_fiat_offers
  ADD COLUMN IF NOT EXISTS is_featured BOOLEAN DEFAULT FALSE;

ALTER TABLE public.p2p_fiat_offers
  ADD COLUMN IF NOT EXISTS featured_until TIMESTAMPTZ;

CREATE INDEX IF NOT EXISTS idx_p2p_offers_featured ON public.p2p_fiat_offers(is_featured, featured_until)
  WHERE is_featured = true;

-- =====================================================
-- GRANTS
-- =====================================================
GRANT EXECUTE ON FUNCTION public.check_tier_eligibility TO authenticated;
GRANT EXECUTE ON FUNCTION public.apply_for_tier_upgrade TO authenticated;
GRANT EXECUTE ON FUNCTION public.approve_tier_application TO authenticated;
GRANT EXECUTE ON FUNCTION public.calculate_merchant_stats TO authenticated;

-- =====================================================
-- COMMENTS
-- =====================================================
COMMENT ON TABLE public.p2p_merchant_tiers IS 'Merchant tier assignments and applications';
COMMENT ON TABLE public.p2p_merchant_stats IS 'Rolling 30-day trading statistics for merchants';
COMMENT ON TABLE public.p2p_featured_ads IS 'Featured/promoted P2P advertisements';
COMMENT ON TABLE public.p2p_tier_requirements IS 'Requirements for each merchant tier level';
