-- ============================================================
-- Migration: Unified Billing System
-- Timestamp: 20260322260000
-- Covers: billing_companies, billing_clients, billing_invoices,
--         billing_line_items, billing_payments, billing_sync_log,
--         ad_campaigns table, billing settings
-- ============================================================

-- ─── 1. billing_companies ────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS public.billing_companies (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL,
  legal_name TEXT NOT NULL,
  llc_entity TEXT,
  address TEXT,
  email TEXT,
  invoice_prefix TEXT NOT NULL DEFAULT 'INV-',
  stripe_account_id TEXT,
  mooninvoice_company_id TEXT,
  mooninvoice_api_key TEXT,
  stripe_secret_key TEXT,
  stripe_publishable_key TEXT,
  default_payment_terms TEXT NOT NULL DEFAULT 'Net 30',
  is_active BOOLEAN NOT NULL DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_billing_companies_active ON public.billing_companies(is_active);

ALTER TABLE public.billing_companies ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "admin_manage_billing_companies" ON public.billing_companies;
CREATE POLICY "admin_manage_billing_companies"
ON public.billing_companies FOR ALL TO authenticated
USING (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
)
WITH CHECK (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
);

-- ─── 2. billing_clients ──────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS public.billing_clients (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  company_id UUID REFERENCES public.billing_companies(id) ON DELETE CASCADE,
  name TEXT NOT NULL,
  organization TEXT,
  email TEXT,
  phone TEXT,
  billing_address TEXT,
  notes TEXT,
  mooninvoice_contact_id TEXT,
  stripe_customer_id TEXT,
  total_billed NUMERIC(12,2) NOT NULL DEFAULT 0,
  total_paid NUMERIC(12,2) NOT NULL DEFAULT 0,
  invoice_consolidation BOOLEAN NOT NULL DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_billing_clients_company_id ON public.billing_clients(company_id);
CREATE INDEX IF NOT EXISTS idx_billing_clients_mooninvoice_id ON public.billing_clients(mooninvoice_contact_id);

ALTER TABLE public.billing_clients ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "admin_manage_billing_clients" ON public.billing_clients;
CREATE POLICY "admin_manage_billing_clients"
ON public.billing_clients FOR ALL TO authenticated
USING (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
)
WITH CHECK (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
);

-- ─── 3. billing_invoices ─────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS public.billing_invoices (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  company_id UUID REFERENCES public.billing_companies(id) ON DELETE CASCADE,
  client_id UUID REFERENCES public.billing_clients(id) ON DELETE SET NULL,
  invoice_number TEXT NOT NULL,
  issue_date DATE,
  due_date DATE,
  status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft','sent','viewed','paid','overdue','cancelled')),
  subtotal NUMERIC(12,2) NOT NULL DEFAULT 0,
  tax NUMERIC(12,2) NOT NULL DEFAULT 0,
  total NUMERIC(12,2) NOT NULL DEFAULT 0,
  amount_paid NUMERIC(12,2) NOT NULL DEFAULT 0,
  currency TEXT NOT NULL DEFAULT 'USD',
  notes TEXT,
  internal_memo TEXT,
  stripe_payment_link TEXT,
  mooninvoice_invoice_id TEXT,
  pdf_url TEXT,
  paid_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_billing_invoices_company_id ON public.billing_invoices(company_id);
CREATE INDEX IF NOT EXISTS idx_billing_invoices_client_id ON public.billing_invoices(client_id);
CREATE INDEX IF NOT EXISTS idx_billing_invoices_status ON public.billing_invoices(status);
CREATE INDEX IF NOT EXISTS idx_billing_invoices_mooninvoice_id ON public.billing_invoices(mooninvoice_invoice_id);
CREATE INDEX IF NOT EXISTS idx_billing_invoices_due_date ON public.billing_invoices(due_date);

ALTER TABLE public.billing_invoices ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "admin_manage_billing_invoices" ON public.billing_invoices;
CREATE POLICY "admin_manage_billing_invoices"
ON public.billing_invoices FOR ALL TO authenticated
USING (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
)
WITH CHECK (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
);

-- ─── 4. billing_line_items ───────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS public.billing_line_items (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  invoice_id UUID REFERENCES public.billing_invoices(id) ON DELETE CASCADE,
  description TEXT NOT NULL,
  quantity NUMERIC(10,2) NOT NULL DEFAULT 1,
  rate NUMERIC(12,2) NOT NULL DEFAULT 0,
  amount NUMERIC(12,2) NOT NULL DEFAULT 0,
  campaign_id UUID,
  created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_billing_line_items_invoice_id ON public.billing_line_items(invoice_id);
CREATE INDEX IF NOT EXISTS idx_billing_line_items_campaign_id ON public.billing_line_items(campaign_id);

ALTER TABLE public.billing_line_items ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "admin_manage_billing_line_items" ON public.billing_line_items;
CREATE POLICY "admin_manage_billing_line_items"
ON public.billing_line_items FOR ALL TO authenticated
USING (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
)
WITH CHECK (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
);

-- ─── 5. billing_payments ─────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS public.billing_payments (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  invoice_id UUID REFERENCES public.billing_invoices(id) ON DELETE SET NULL,
  client_id UUID REFERENCES public.billing_clients(id) ON DELETE SET NULL,
  amount NUMERIC(12,2) NOT NULL DEFAULT 0,
  payment_date DATE,
  payment_method TEXT,
  stripe_charge_id TEXT,
  stripe_payment_intent_id TEXT,
  notes TEXT,
  status TEXT NOT NULL DEFAULT 'succeeded' CHECK (status IN ('succeeded','failed','pending','refunded','disputed')),
  created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_billing_payments_invoice_id ON public.billing_payments(invoice_id);
CREATE INDEX IF NOT EXISTS idx_billing_payments_client_id ON public.billing_payments(client_id);
CREATE INDEX IF NOT EXISTS idx_billing_payments_stripe_charge ON public.billing_payments(stripe_charge_id);

ALTER TABLE public.billing_payments ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "admin_manage_billing_payments" ON public.billing_payments;
CREATE POLICY "admin_manage_billing_payments"
ON public.billing_payments FOR ALL TO authenticated
USING (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
)
WITH CHECK (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
);

-- ─── 6. billing_sync_log ─────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS public.billing_sync_log (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  sync_type TEXT NOT NULL,
  company_id UUID REFERENCES public.billing_companies(id) ON DELETE SET NULL,
  records_synced INTEGER NOT NULL DEFAULT 0,
  errors JSONB,
  started_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
  completed_at TIMESTAMPTZ,
  status TEXT NOT NULL DEFAULT 'running' CHECK (status IN ('running','completed','failed'))
);

CREATE INDEX IF NOT EXISTS idx_billing_sync_log_company_id ON public.billing_sync_log(company_id);
CREATE INDEX IF NOT EXISTS idx_billing_sync_log_started_at ON public.billing_sync_log(started_at);

ALTER TABLE public.billing_sync_log ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "admin_manage_billing_sync_log" ON public.billing_sync_log;
CREATE POLICY "admin_manage_billing_sync_log"
ON public.billing_sync_log FOR ALL TO authenticated
USING (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
)
WITH CHECK (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
);

-- ─── 7. billing_settings ─────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS public.billing_settings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  billing_mode TEXT NOT NULL DEFAULT 'mooninvoice' CHECK (billing_mode IN ('mooninvoice','native')),
  sync_frequency_minutes INTEGER NOT NULL DEFAULT 15,
  last_sync_rmp TIMESTAMPTZ,
  last_sync_jtr TIMESTAMPTZ,
  default_payment_terms TEXT NOT NULL DEFAULT 'Net 30',
  default_currency TEXT NOT NULL DEFAULT 'USD',
  late_payment_reminder_enabled BOOLEAN NOT NULL DEFAULT false,
  late_payment_reminder_days INTEGER NOT NULL DEFAULT 7,
  auto_send_reminders BOOLEAN NOT NULL DEFAULT false,
  stripe_test_mode BOOLEAN NOT NULL DEFAULT true,
  migration_import_status JSONB,
  migration_last_run TIMESTAMPTZ,
  migration_verified BOOLEAN NOT NULL DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

ALTER TABLE public.billing_settings ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "admin_manage_billing_settings" ON public.billing_settings;
CREATE POLICY "admin_manage_billing_settings"
ON public.billing_settings FOR ALL TO authenticated
USING (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
)
WITH CHECK (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
);

-- ─── 8. ad_campaigns table ───────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS public.ad_campaigns (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL,
  client_name TEXT,
  campaign_type TEXT NOT NULL DEFAULT 'banner' CHECK (campaign_type IN ('banner','email','sponsored','newsletter')),
  site_id INTEGER REFERENCES public.sites(id) ON DELETE SET NULL,
  status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft','pending_approval','approved','active','paused','completed','cancelled')),
  start_date DATE,
  end_date DATE,
  budget NUMERIC(12,2),
  rate NUMERIC(12,2),
  notes TEXT,
  billing_invoice_id UUID REFERENCES public.billing_invoices(id) ON DELETE SET NULL,
  billing_company_id UUID REFERENCES public.billing_companies(id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_ad_campaigns_status ON public.ad_campaigns(status);
CREATE INDEX IF NOT EXISTS idx_ad_campaigns_billing_invoice ON public.ad_campaigns(billing_invoice_id);
CREATE INDEX IF NOT EXISTS idx_ad_campaigns_billing_company ON public.ad_campaigns(billing_company_id);
CREATE INDEX IF NOT EXISTS idx_ad_campaigns_site_id ON public.ad_campaigns(site_id);

ALTER TABLE public.ad_campaigns ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS "admin_manage_ad_campaigns" ON public.ad_campaigns;
CREATE POLICY "admin_manage_ad_campaigns"
ON public.ad_campaigns FOR ALL TO authenticated
USING (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
)
WITH CHECK (
  EXISTS (
    SELECT 1 FROM public.user_profiles up
    WHERE up.id = auth.uid() AND up.role IN ('administrator', 'admin')
  )
);

-- ─── 9. Seed default companies and settings ──────────────────────────────────
DO $$
DECLARE
  rmp_id UUID := gen_random_uuid();
  jtr_id UUID := gen_random_uuid();
BEGIN
  INSERT INTO public.billing_companies (id, name, legal_name, llc_entity, address, email, invoice_prefix, default_payment_terms, is_active)
  VALUES
    (rmp_id, 'Relevant Media Properties', 'Relevant Media Properties, LLC', 'RMP',
     '1309 Coffeen Ave, Suite 1200, Sheridan, WY 82801',
     'ryan.salazar@relevantmediaproperties.com', 'RMP-', 'Net 30', true),
    (jtr_id, 'Just Two Roommates', 'Just Two Roommates, LLC', 'JTR',
     '1309 Coffeen Ave, Suite 1200, Sheridan, WY 82801',
     'ryan.salazar@relevantmediaproperties.com', 'JTR-', 'Net 30', true)
  ON CONFLICT (id) DO NOTHING;

  INSERT INTO public.billing_settings (billing_mode, sync_frequency_minutes, default_payment_terms, default_currency)
  VALUES ('mooninvoice', 15, 'Net 30', 'USD')
  ON CONFLICT (id) DO NOTHING;

EXCEPTION
  WHEN OTHERS THEN
    RAISE NOTICE 'Seed data insertion failed: %', SQLERRM;
END $$;
