-- =====================================================
-- ORBIQUANT IA - INVOICES TABLE
-- =====================================================
-- Description: Invoice records for subscriptions and one-time charges
-- Schema: financial
-- =====================================================

CREATE TABLE financial.invoices (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

  -- Referencias
  user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE RESTRICT,
  subscription_id UUID REFERENCES financial.subscriptions(id) ON DELETE SET NULL,

  -- Stripe integration
  stripe_invoice_id VARCHAR(255) UNIQUE,
  stripe_customer_id VARCHAR(255),

  -- Invoice details
  invoice_number VARCHAR(100) UNIQUE, -- Número de factura interno
  invoice_type financial.invoice_type NOT NULL,
  status financial.invoice_status NOT NULL DEFAULT 'draft',

  -- Amounts
  subtotal DECIMAL(15,2) NOT NULL DEFAULT 0,
  tax DECIMAL(15,2) DEFAULT 0,
  total DECIMAL(15,2) NOT NULL,
  amount_paid DECIMAL(15,2) DEFAULT 0,
  amount_due DECIMAL(15,2) GENERATED ALWAYS AS (total - amount_paid) STORED,

  currency financial.currency_code NOT NULL DEFAULT 'USD',

  -- Dates
  invoice_date TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  due_date TIMESTAMPTZ,
  period_start TIMESTAMPTZ,
  period_end TIMESTAMPTZ,

  -- Payment
  paid BOOLEAN DEFAULT false,
  paid_at TIMESTAMPTZ,
  attempted BOOLEAN DEFAULT false,
  attempt_count INTEGER DEFAULT 0,
  next_payment_attempt TIMESTAMPTZ,

  -- URLs
  hosted_invoice_url TEXT, -- Stripe hosted invoice URL
  invoice_pdf_url TEXT,

  -- Billing details
  billing_email VARCHAR(255),
  billing_name VARCHAR(255),
  billing_address JSONB,

  -- Line items (si se quiere detalle simple)
  line_items JSONB DEFAULT '[]',

  -- Metadata
  description TEXT,
  notes TEXT,
  metadata JSONB DEFAULT '{}',

  -- Timestamps
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  finalized_at TIMESTAMPTZ,
  voided_at TIMESTAMPTZ,

  -- Constraints
  CONSTRAINT positive_subtotal CHECK (subtotal >= 0),
  CONSTRAINT positive_tax CHECK (tax >= 0),
  CONSTRAINT positive_total CHECK (total >= 0),
  CONSTRAINT positive_paid CHECK (amount_paid >= 0),
  CONSTRAINT paid_lte_total CHECK (amount_paid <= total),
  CONSTRAINT total_equals_subtotal_plus_tax CHECK (total = subtotal + tax),
  CONSTRAINT paid_has_timestamp CHECK (
    (paid = false) OR
    (paid = true AND paid_at IS NOT NULL)
  ),
  CONSTRAINT finalized_for_open_paid CHECK (
    (status IN ('open', 'paid') AND finalized_at IS NOT NULL) OR
    (status NOT IN ('open', 'paid'))
  ),
  CONSTRAINT void_has_timestamp CHECK (
    (status = 'void' AND voided_at IS NOT NULL) OR
    (status != 'void')
  ),
  CONSTRAINT due_date_after_invoice CHECK (
    due_date IS NULL OR due_date >= invoice_date
  ),
  CONSTRAINT period_dates_order CHECK (
    (period_start IS NULL AND period_end IS NULL) OR
    (period_start IS NOT NULL AND period_end IS NOT NULL AND period_start < period_end)
  )
);

-- Sequence para invoice numbers
CREATE SEQUENCE financial.invoice_number_seq START 1000;

-- Indexes
CREATE INDEX idx_invoices_user_id ON financial.invoices(user_id);
CREATE INDEX idx_invoices_subscription_id ON financial.invoices(subscription_id) WHERE subscription_id IS NOT NULL;
CREATE INDEX idx_invoices_status ON financial.invoices(status);
CREATE INDEX idx_invoices_stripe_id ON financial.invoices(stripe_invoice_id) WHERE stripe_invoice_id IS NOT NULL;
CREATE INDEX idx_invoices_invoice_number ON financial.invoices(invoice_number);
CREATE INDEX idx_invoices_due_date ON financial.invoices(due_date) WHERE due_date IS NOT NULL AND status = 'open';
CREATE INDEX idx_invoices_invoice_date ON financial.invoices(invoice_date DESC);
CREATE INDEX idx_invoices_user_date ON financial.invoices(user_id, invoice_date DESC);
CREATE INDEX idx_invoices_unpaid ON financial.invoices(user_id, status) WHERE paid = false AND status = 'open';
CREATE INDEX idx_invoices_period ON financial.invoices(period_start, period_end) WHERE period_start IS NOT NULL;

-- Comments
COMMENT ON TABLE financial.invoices IS 'Invoice records for subscriptions and one-time charges';
COMMENT ON COLUMN financial.invoices.invoice_number IS 'Internal unique invoice number (auto-generated)';
COMMENT ON COLUMN financial.invoices.invoice_type IS 'Type: subscription, one_time, or usage-based';
COMMENT ON COLUMN financial.invoices.amount_due IS 'Computed: total - amount_paid';
COMMENT ON COLUMN financial.invoices.line_items IS 'JSON array of invoice line items with description, amount, quantity';
COMMENT ON COLUMN financial.invoices.billing_address IS 'JSON object with billing address details';
COMMENT ON COLUMN financial.invoices.hosted_invoice_url IS 'URL to Stripe-hosted invoice page';
COMMENT ON COLUMN financial.invoices.attempt_count IS 'Number of payment attempts made';
