-- Create enum for invoice status
CREATE TYPE invoice_status AS ENUM ('DRAFT', 'SENT', 'PAID', 'PARTIALLY_PAID', 'OVERDUE', 'VOID', 'CANCELLED');

-- Create invoices table
CREATE TABLE IF NOT EXISTS invoices (
    id SERIAL PRIMARY KEY,
    invoice_number VARCHAR(50) UNIQUE NOT NULL,
    project_id INTEGER REFERENCES projects(id) ON DELETE SET NULL,
    client_id INTEGER NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
    amount DECIMAL(15, 2) NOT NULL,
    currency VARCHAR(10) NOT NULL DEFAULT 'USD',
    status invoice_status NOT NULL DEFAULT 'DRAFT',
    due_date DATE,
    issued_date DATE,
    paid_date DATE,
    blockchain_tx_hash VARCHAR(255), -- For on-chain payment proof
    ipfs_document_cid VARCHAR(255), -- CID for invoice PDF on IPFS
    notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Create indexes for invoices
CREATE INDEX idx_invoices_invoice_number ON invoices(invoice_number);
CREATE INDEX idx_invoices_project_id ON invoices(project_id);
CREATE INDEX idx_invoices_client_id ON invoices(client_id);
CREATE INDEX idx_invoices_status ON invoices(status);
CREATE INDEX idx_invoices_due_date ON invoices(due_date) WHERE due_date IS NOT NULL;
CREATE INDEX idx_invoices_blockchain_tx ON invoices(blockchain_tx_hash) WHERE blockchain_tx_hash IS NOT NULL;

-- Create enum for payment method
CREATE TYPE payment_method AS ENUM ('CREDIT_CARD', 'DEBIT_CARD', 'CRYPTO_BTC', 'CRYPTO_ETH', 'CRYPTO_OTHER', 'BLOCKCHAIN_TOKEN', 'BANK_TRANSFER', 'CASH', 'OTHER');

-- Create enum for payment status
CREATE TYPE payment_status AS ENUM ('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED', 'REFUNDED', 'CANCELLED');

-- Create payments table
CREATE TABLE IF NOT EXISTS payments (
    id SERIAL PRIMARY KEY,
    invoice_id INTEGER NOT NULL REFERENCES invoices(id) ON DELETE CASCADE,
    amount DECIMAL(15, 2) NOT NULL,
    currency VARCHAR(10) NOT NULL DEFAULT 'USD',
    payment_method payment_method NOT NULL,
    status payment_status NOT NULL DEFAULT 'PENDING',
    transaction_id VARCHAR(255), -- Stripe payment intent ID, BTCPay invoice ID, or blockchain tx hash
    blockchain_tx_hash VARCHAR(255), -- For crypto/blockchain payments
    blockchain_network VARCHAR(50), -- e.g., 'ethereum', 'bitcoin', 'polygon'
    payment_processor VARCHAR(50), -- e.g., 'stripe', 'btcpay', 'direct_blockchain'
    processor_fee DECIMAL(15, 2), -- Fee charged by payment processor
    metadata JSONB, -- Store processor-specific data
    processed_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Create indexes for payments
CREATE INDEX idx_payments_invoice_id ON payments(invoice_id);
CREATE INDEX idx_payments_transaction_id ON payments(transaction_id) WHERE transaction_id IS NOT NULL;
CREATE INDEX idx_payments_blockchain_tx ON payments(blockchain_tx_hash) WHERE blockchain_tx_hash IS NOT NULL;
CREATE INDEX idx_payments_status ON payments(status);
CREATE INDEX idx_payments_payment_method ON payments(payment_method);

-- Create invoice_items table for line items
CREATE TABLE IF NOT EXISTS invoice_items (
    id SERIAL PRIMARY KEY,
    invoice_id INTEGER NOT NULL REFERENCES invoices(id) ON DELETE CASCADE,
    description VARCHAR(500) NOT NULL,
    quantity DECIMAL(10, 2) NOT NULL DEFAULT 1,
    unit_price DECIMAL(15, 2) NOT NULL,
    tax_rate DECIMAL(5, 2) DEFAULT 0, -- Percentage
    total DECIMAL(15, 2) NOT NULL, -- Calculated: quantity * unit_price * (1 + tax_rate/100)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Create index for invoice_items
CREATE INDEX idx_invoice_items_invoice_id ON invoice_items(invoice_id);

-- Create triggers for updated_at
CREATE TRIGGER update_invoices_updated_at BEFORE UPDATE ON invoices
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_payments_updated_at BEFORE UPDATE ON payments
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_invoice_items_updated_at BEFORE UPDATE ON invoice_items
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- Create function to automatically update invoice status based on payments
CREATE OR REPLACE FUNCTION update_invoice_status()
RETURNS TRIGGER AS $$
DECLARE
    total_paid DECIMAL(15, 2);
    invoice_amount DECIMAL(15, 2);
BEGIN
    -- Get total paid amount for this invoice
    SELECT COALESCE(SUM(amount), 0) INTO total_paid
    FROM payments
    WHERE invoice_id = NEW.invoice_id AND status = 'COMPLETED';

    -- Get invoice amount
    SELECT amount INTO invoice_amount
    FROM invoices
    WHERE id = NEW.invoice_id;

    -- Update invoice status based on payment
    IF total_paid >= invoice_amount THEN
        UPDATE invoices SET status = 'PAID', paid_date = CURRENT_TIMESTAMP
        WHERE id = NEW.invoice_id AND status != 'PAID';
    ELSIF total_paid > 0 THEN
        UPDATE invoices SET status = 'PARTIALLY_PAID'
        WHERE id = NEW.invoice_id AND status NOT IN ('PAID', 'PARTIALLY_PAID');
    END IF;

    RETURN NEW;
END;
$$ language 'plpgsql';

-- Create trigger to update invoice status when payment is completed
CREATE TRIGGER update_invoice_on_payment AFTER INSERT OR UPDATE ON payments
    FOR EACH ROW
    WHEN (NEW.status = 'COMPLETED')
    EXECUTE FUNCTION update_invoice_status();
