-- ============================================================
-- AppForge — application schema (de-Supabased)
-- Target: plain PostgreSQL. No RLS, no auth.* schema.
-- User identity is owned by Better Auth ("user" table, text id).
-- All user references are TEXT referencing "user"(id).
-- This file is idempotent (safe to re-run).
-- ============================================================

-- gen_random_uuid() is built into PG13+ core; pgcrypto kept for safety.
CREATE EXTENSION IF NOT EXISTS pgcrypto;

-- ---------- Enums ----------
DO $$ BEGIN
  CREATE TYPE public.app_role AS ENUM ('admin', 'moderator', 'user');
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

DO $$ BEGIN
  CREATE TYPE public.payment_method AS ENUM ('paypal', 'crypto', 'bank_transfer', 'stripe');
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

DO $$ BEGIN
  CREATE TYPE public.subscription_tier AS ENUM ('free', 'pro', 'enterprise');
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

DO $$ BEGIN
  CREATE TYPE public.transaction_status AS ENUM ('pending', 'completed', 'failed', 'refunded');
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

-- ---------- updated_at trigger fn ----------
CREATE OR REPLACE FUNCTION public.update_updated_at_column() RETURNS trigger
  LANGUAGE plpgsql AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$;

-- ============================================================
-- Tables
-- ============================================================

CREATE TABLE IF NOT EXISTS public.profiles (
  id text PRIMARY KEY,
  email text,
  display_name text,
  avatar_url text,
  company_name text,
  stripe_customer_id text UNIQUE,
  marketing_consent boolean DEFAULT false,
  marketing_consent_date timestamptz,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.user_roles (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL,
  role public.app_role NOT NULL,
  created_at timestamptz DEFAULT now() NOT NULL,
  CONSTRAINT user_roles_user_id_role_key UNIQUE (user_id, role)
);

CREATE TABLE IF NOT EXISTS public.subscription_plans (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  tier public.subscription_tier NOT NULL UNIQUE,
  name text NOT NULL,
  description text,
  price_monthly numeric(10,2) DEFAULT 0 NOT NULL,
  price_yearly numeric(10,2) DEFAULT 0 NOT NULL,
  monthly_credits integer DEFAULT 0 NOT NULL,
  features jsonb DEFAULT '[]'::jsonb NOT NULL,
  is_active boolean DEFAULT true NOT NULL,
  stripe_price_id text,
  stripe_yearly_price_id text,
  paypal_plan_id text,
  paypal_yearly_plan_id text,
  paypal_product_id text,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.user_credits (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL UNIQUE,
  monthly_credits integer DEFAULT 0 NOT NULL,
  bonus_credits integer DEFAULT 0 NOT NULL,
  credits_reset_at timestamptz,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.user_subscriptions (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL UNIQUE,
  plan_id uuid NOT NULL REFERENCES public.subscription_plans(id),
  status text DEFAULT 'active'::text NOT NULL,
  billing_cycle text DEFAULT 'monthly'::text NOT NULL,
  current_period_start timestamptz DEFAULT now() NOT NULL,
  current_period_end timestamptz NOT NULL,
  cancel_at_period_end boolean DEFAULT false NOT NULL,
  payment_method public.payment_method,
  external_subscription_id text,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.app_projects (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL,
  website_url text NOT NULL,
  app_name text NOT NULL,
  primary_color text DEFAULT '#22D3EE'::text,
  accent_color text DEFAULT '#A855F7'::text,
  navigation_style text DEFAULT 'bottom-nav'::text,
  features text[] DEFAULT '{}'::text[],
  app_category text,
  description text,
  icon_style text DEFAULT 'modern'::text,
  splash_screen_style text DEFAULT 'centered-logo'::text,
  build_status text DEFAULT 'draft'::text,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL,
  CONSTRAINT app_projects_user_id_website_url_key UNIQUE (user_id, website_url)
);

CREATE TABLE IF NOT EXISTS public.app_builds (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL,
  project_id uuid REFERENCES public.app_projects(id) ON DELETE SET NULL,
  website_url text NOT NULL,
  app_name text NOT NULL,
  package_name text NOT NULL,
  config jsonb DEFAULT '{}'::jsonb NOT NULL,
  status text DEFAULT 'pending'::text NOT NULL,
  progress integer DEFAULT 0 NOT NULL,
  download_url text,
  file_size_bytes bigint,
  error_message text,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL,
  CONSTRAINT app_builds_status_check CHECK (status = ANY (ARRAY['pending'::text,'building'::text,'complete'::text,'failed'::text]))
);

CREATE TABLE IF NOT EXISTS public.app_templates (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL,
  name text NOT NULL,
  description text,
  config jsonb NOT NULL,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.automation_configs (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  project_id uuid NOT NULL REFERENCES public.app_projects(id) ON DELETE CASCADE,
  user_id text NOT NULL,
  workflow_type text NOT NULL,
  is_enabled boolean DEFAULT true NOT NULL,
  config jsonb DEFAULT '{}'::jsonb NOT NULL,
  last_run_at timestamptz,
  next_run_at timestamptz,
  run_count integer DEFAULT 0 NOT NULL,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL,
  CONSTRAINT automation_configs_project_id_workflow_type_key UNIQUE (project_id, workflow_type)
);

CREATE TABLE IF NOT EXISTS public.automation_logs (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  automation_id uuid NOT NULL REFERENCES public.automation_configs(id) ON DELETE CASCADE,
  user_id text NOT NULL,
  status text DEFAULT 'pending'::text NOT NULL,
  message text,
  metadata jsonb DEFAULT '{}'::jsonb,
  started_at timestamptz DEFAULT now() NOT NULL,
  completed_at timestamptz,
  created_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.credit_packs (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  name text NOT NULL,
  credits integer NOT NULL,
  price numeric(10,2) NOT NULL,
  description text,
  is_active boolean DEFAULT true NOT NULL,
  stripe_price_id text,
  created_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.credit_usage_history (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL,
  amount integer NOT NULL,
  action_type text NOT NULL,
  description text,
  metadata jsonb DEFAULT '{}'::jsonb,
  created_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.payment_transactions (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL,
  amount numeric(10,2) NOT NULL,
  currency text DEFAULT 'USD'::text NOT NULL,
  payment_method public.payment_method NOT NULL,
  status public.transaction_status DEFAULT 'pending'::public.transaction_status NOT NULL,
  transaction_type text NOT NULL,
  reference_id text,
  external_transaction_id text,
  paypal_order_id text,
  paypal_subscription_id text,
  metadata jsonb DEFAULT '{}'::jsonb,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.bank_transfer_requests (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL,
  transaction_id uuid REFERENCES public.payment_transactions(id),
  amount numeric(10,2) NOT NULL,
  currency text DEFAULT 'USD'::text NOT NULL,
  plan_id uuid REFERENCES public.subscription_plans(id),
  credit_pack_id uuid REFERENCES public.credit_packs(id),
  status text DEFAULT 'pending'::text NOT NULL,
  proof_of_payment_url text,
  admin_notes text,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.chat_messages (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text NOT NULL,
  role text NOT NULL,
  content text NOT NULL,
  project_id uuid REFERENCES public.app_projects(id) ON DELETE CASCADE,
  created_at timestamptz DEFAULT now() NOT NULL,
  CONSTRAINT chat_messages_role_check CHECK (role = ANY (ARRAY['user'::text,'assistant'::text]))
);

CREATE TABLE IF NOT EXISTS public.consent_records (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id text,
  email text,
  consent_type text NOT NULL,
  consented boolean DEFAULT false NOT NULL,
  ip_address text,
  user_agent text,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.email_templates (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  name text NOT NULL UNIQUE,
  subject text NOT NULL,
  html_content text NOT NULL,
  text_content text,
  variables jsonb DEFAULT '[]'::jsonb,
  is_active boolean DEFAULT true NOT NULL,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.invoices (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  invoice_number text NOT NULL UNIQUE,
  user_id text NOT NULL,
  amount numeric NOT NULL,
  currency text DEFAULT 'USD'::text NOT NULL,
  status text DEFAULT 'draft'::text NOT NULL,
  due_date timestamptz,
  paid_at timestamptz,
  items jsonb DEFAULT '[]'::jsonb NOT NULL,
  notes text,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.api_configurations (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  name text NOT NULL,
  provider text NOT NULL,
  api_key_masked text,
  is_active boolean DEFAULT false NOT NULL,
  rate_limit integer DEFAULT 1000,
  usage_count integer DEFAULT 0,
  last_used_at timestamptz,
  config jsonb DEFAULT '{}'::jsonb NOT NULL,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.plugins (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  name text NOT NULL,
  slug text NOT NULL UNIQUE,
  type text NOT NULL,
  description text,
  config jsonb DEFAULT '{}'::jsonb,
  is_active boolean DEFAULT false NOT NULL,
  version text DEFAULT '1.0.0'::text,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.system_settings (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  key text NOT NULL UNIQUE,
  value jsonb DEFAULT '{}'::jsonb NOT NULL,
  category text DEFAULT 'general'::text NOT NULL,
  description text,
  updated_at timestamptz DEFAULT now() NOT NULL,
  updated_by text
);

CREATE TABLE IF NOT EXISTS public.settings_audit_log (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  setting_id uuid REFERENCES public.system_settings(id) ON DELETE SET NULL,
  setting_key text NOT NULL,
  old_value jsonb,
  new_value jsonb NOT NULL,
  changed_by text,
  changed_by_email text,
  change_type text DEFAULT 'update'::text NOT NULL,
  created_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.payment_gateway_configs (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  gateway text NOT NULL UNIQUE,
  is_enabled boolean DEFAULT false,
  is_test_mode boolean DEFAULT true,
  sandbox_config jsonb DEFAULT '{}'::jsonb,
  live_config jsonb DEFAULT '{}'::jsonb,
  created_at timestamptz DEFAULT now() NOT NULL,
  updated_at timestamptz DEFAULT now() NOT NULL
);

CREATE TABLE IF NOT EXISTS public.webhook_event_logs (
  id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
  gateway text NOT NULL,
  event_type text NOT NULL,
  event_id text,
  status text NOT NULL DEFAULT 'received',
  payload jsonb DEFAULT '{}'::jsonb,
  response_status integer,
  error_message text,
  processing_time_ms integer,
  created_at timestamptz DEFAULT now() NOT NULL
);

-- ---------- Indexes ----------
CREATE INDEX IF NOT EXISTS idx_automation_configs_project ON public.automation_configs (project_id);
CREATE INDEX IF NOT EXISTS idx_automation_configs_type ON public.automation_configs (workflow_type);
CREATE INDEX IF NOT EXISTS idx_automation_configs_user ON public.automation_configs (user_id);
CREATE INDEX IF NOT EXISTS idx_automation_logs_automation ON public.automation_logs (automation_id);
CREATE INDEX IF NOT EXISTS idx_automation_logs_status ON public.automation_logs (status);
CREATE INDEX IF NOT EXISTS idx_chat_messages_user_project ON public.chat_messages (user_id, project_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_consent_records_email ON public.consent_records (email);
CREATE INDEX IF NOT EXISTS idx_consent_records_user_id ON public.consent_records (user_id);
CREATE INDEX IF NOT EXISTS idx_credit_usage_action ON public.credit_usage_history (action_type);
CREATE INDEX IF NOT EXISTS idx_credit_usage_user_date ON public.credit_usage_history (user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_app_builds_user ON public.app_builds (user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_app_projects_user ON public.app_projects (user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_settings_audit_log_created_at ON public.settings_audit_log (created_at DESC);
CREATE INDEX IF NOT EXISTS idx_settings_audit_log_setting_id ON public.settings_audit_log (setting_id);
CREATE INDEX IF NOT EXISTS idx_webhook_event_logs_gateway ON public.webhook_event_logs (gateway);
CREATE INDEX IF NOT EXISTS idx_webhook_event_logs_created_at ON public.webhook_event_logs (created_at DESC);
CREATE INDEX IF NOT EXISTS idx_webhook_event_logs_status ON public.webhook_event_logs (status);

-- ---------- updated_at triggers ----------
DO $$
DECLARE t text;
BEGIN
  FOR t IN
    SELECT unnest(ARRAY[
      'api_configurations','app_builds','app_projects','app_templates','automation_configs',
      'bank_transfer_requests','consent_records','email_templates','invoices','payment_transactions',
      'plugins','profiles','subscription_plans','system_settings','user_credits','user_subscriptions',
      'payment_gateway_configs'
    ])
  LOOP
    EXECUTE format('DROP TRIGGER IF EXISTS update_%1$s_updated_at ON public.%1$s;', t);
    EXECUTE format('CREATE TRIGGER update_%1$s_updated_at BEFORE UPDATE ON public.%1$s FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();', t);
  END LOOP;
END $$;

-- ============================================================
-- Seed data
-- ============================================================
INSERT INTO public.subscription_plans (tier, name, description, price_monthly, price_yearly, monthly_credits, features, is_active)
VALUES
  ('free', 'Free', 'Get started building apps', 0, 0, 5,
    '["5 credits / month","Community support","Standard build queue"]'::jsonb, true),
  ('pro', 'Pro', 'For serious builders', 19, 190, 100,
    '["100 credits / month","Priority builds","Email support","Custom branding"]'::jsonb, true),
  ('enterprise', 'Enterprise', 'For teams and agencies', 99, 990, 1000,
    '["1000 credits / month","Fastest builds","Dedicated support","Team seats","White-label"]'::jsonb, true)
ON CONFLICT (tier) DO NOTHING;

INSERT INTO public.system_settings (key, value, category, description)
VALUES
  ('credits_per_build', '1'::jsonb, 'builds', 'Number of credits consumed per app build'),
  ('default_signup_credits', '5'::jsonb, 'app', 'Number of free credits given to new users on signup')
ON CONFLICT (key) DO NOTHING;

INSERT INTO public.payment_gateway_configs (gateway, is_enabled, is_test_mode)
VALUES ('paypal', false, true), ('stripe', false, true), ('coinbase', false, true), ('bank_transfer', false, false)
ON CONFLICT (gateway) DO NOTHING;
