-- PIRP vollständiges Schema (inkl. Journal-Modul)

-- Reihenfolge beachten wegen Foreign Keys
DROP TABLE IF EXISTS journal_monthly_summary_values CASCADE;
DROP TABLE IF EXISTS journal_monthly_summary CASCADE;
DROP TABLE IF EXISTS journal_entry_accounts CASCADE;
DROP TABLE IF EXISTS journal_entries CASCADE;
DROP TABLE IF EXISTS journal_summary_items CASCADE;
DROP TABLE IF EXISTS journal_deduction_categories CASCADE;
DROP TABLE IF EXISTS journal_expense_categories CASCADE;
DROP TABLE IF EXISTS journal_revenue_categories CASCADE;
DROP TABLE IF EXISTS journal_suppliers CASCADE;
DROP TABLE IF EXISTS journal_years CASCADE;
DROP TABLE IF EXISTS recurring_log CASCADE;
DROP TABLE IF EXISTS recurring_template_items CASCADE;
DROP TABLE IF EXISTS recurring_templates CASCADE;
DROP TABLE IF EXISTS invoice_items CASCADE;
DROP TABLE IF EXISTS invoices CASCADE;
DROP TABLE IF EXISTS expenses CASCADE;
DROP TABLE IF EXISTS customers CASCADE;
DROP TABLE IF EXISTS settings CASCADE;
DROP TABLE IF EXISTS users CASCADE;

-- ============================================================
-- Basis-Tabellen
-- ============================================================

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    password_hash TEXT NOT NULL,
    created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE settings (
    id SERIAL PRIMARY KEY,
    company_name TEXT,
    company_address TEXT,
    company_zip TEXT,
    company_city TEXT,
    company_country TEXT,
    tax_id TEXT,
    vat_mode VARCHAR(10) DEFAULT 'klein',
    default_vat_rate NUMERIC(5,2) DEFAULT 19.00,
    payment_terms TEXT,
    footer_text TEXT,
    logo_path TEXT,
    iban TEXT,
    phone TEXT,
    email TEXT,
    website TEXT
);

CREATE TABLE customers (
    id SERIAL PRIMARY KEY,
    customer_number VARCHAR(20) UNIQUE,
    name TEXT NOT NULL,
    address TEXT,
    zip TEXT,
    city TEXT,
    country TEXT,
    created_at TIMESTAMPTZ DEFAULT now()
);

-- ============================================================
-- Rechnungen
-- ============================================================

CREATE TABLE invoices (
    id SERIAL PRIMARY KEY,
    invoice_number VARCHAR(50) UNIQUE NOT NULL,
    customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE RESTRICT,
    invoice_date DATE NOT NULL,
    service_date DATE,
    vat_mode VARCHAR(10) NOT NULL DEFAULT 'klein',
    vat_rate NUMERIC(5,2) NOT NULL DEFAULT 19.00,
    payment_terms TEXT,
    notes_internal TEXT,
    total_net NUMERIC(12,2) NOT NULL DEFAULT 0,
    total_vat NUMERIC(12,2) NOT NULL DEFAULT 0,
    total_gross NUMERIC(12,2) NOT NULL DEFAULT 0,
    paid BOOLEAN NOT NULL DEFAULT FALSE,
    payment_date DATE,
    pdf_path TEXT,
    pdf_hash VARCHAR(64),
    pdf_generated_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE invoice_items (
    id SERIAL PRIMARY KEY,
    invoice_id INTEGER NOT NULL REFERENCES invoices(id) ON DELETE CASCADE,
    position_no INTEGER NOT NULL,
    description TEXT NOT NULL,
    quantity NUMERIC(12,2) NOT NULL DEFAULT 1,
    unit_price NUMERIC(12,2) NOT NULL DEFAULT 0,
    vat_rate NUMERIC(5,2) NOT NULL DEFAULT 19.00
);

-- ============================================================
-- Ausgaben
-- ============================================================

CREATE TABLE expenses (
    id SERIAL PRIMARY KEY,
    expense_date DATE NOT NULL,
    description TEXT NOT NULL,
    category TEXT,
    amount NUMERIC(12,2) NOT NULL,
    vat_rate NUMERIC(5,2) DEFAULT 0,
    total_net NUMERIC(12,2),
    total_vat NUMERIC(12,2) DEFAULT 0,
    expense_category_id INTEGER,
    paid BOOLEAN NOT NULL DEFAULT TRUE,
    payment_date DATE,
    attachment_path TEXT,
    created_at TIMESTAMPTZ DEFAULT now()
);

-- ============================================================
-- Wiederkehrende Rechnungen (Abo-Rechnungen)
-- ============================================================

CREATE TABLE recurring_templates (
    id SERIAL PRIMARY KEY,
    template_name VARCHAR(100) NOT NULL,
    customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE RESTRICT,
    interval_type VARCHAR(20) NOT NULL CHECK (interval_type IN ('monthly', 'quarterly', 'yearly')),
    start_date DATE NOT NULL,
    end_date DATE,
    next_due_date DATE NOT NULL,
    vat_mode VARCHAR(10) NOT NULL DEFAULT 'klein',
    vat_rate NUMERIC(5,2) NOT NULL DEFAULT 19.00,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    notes_internal TEXT,
    created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE recurring_template_items (
    id SERIAL PRIMARY KEY,
    template_id INTEGER NOT NULL REFERENCES recurring_templates(id) ON DELETE CASCADE,
    position_no INTEGER NOT NULL,
    description TEXT NOT NULL,
    quantity NUMERIC(12,2) NOT NULL DEFAULT 1,
    unit_price NUMERIC(12,2) NOT NULL DEFAULT 0
);

CREATE TABLE recurring_log (
    id SERIAL PRIMARY KEY,
    template_id INTEGER NOT NULL REFERENCES recurring_templates(id) ON DELETE CASCADE,
    invoice_id INTEGER REFERENCES invoices(id) ON DELETE SET NULL,
    generated_at TIMESTAMPTZ DEFAULT now(),
    due_date DATE NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'generated'
);

-- ============================================================
-- Journal-Modul: Doppelte Buchführung
-- ============================================================

CREATE TABLE journal_years (
    id SERIAL PRIMARY KEY,
    year INTEGER NOT NULL UNIQUE,
    is_closed BOOLEAN NOT NULL DEFAULT FALSE,
    notes TEXT,
    created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE journal_suppliers (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    sort_order INTEGER NOT NULL DEFAULT 0,
    is_active BOOLEAN NOT NULL DEFAULT TRUE
);

CREATE TABLE journal_revenue_categories (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    category_type VARCHAR(20) NOT NULL CHECK (category_type IN ('wareneingang', 'erloese')),
    vat_rate NUMERIC(5,2) NOT NULL DEFAULT 19.00,
    sort_order INTEGER NOT NULL DEFAULT 0,
    is_active BOOLEAN NOT NULL DEFAULT TRUE
);

CREATE TABLE journal_expense_categories (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    side VARCHAR(10) NOT NULL DEFAULT 'soll' CHECK (side IN ('soll', 'soll_haben')),
    sort_order INTEGER NOT NULL DEFAULT 0,
    is_active BOOLEAN NOT NULL DEFAULT TRUE
);

CREATE TABLE journal_deduction_categories (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    sort_order INTEGER NOT NULL DEFAULT 0,
    is_active BOOLEAN NOT NULL DEFAULT TRUE
);

CREATE TABLE journal_entries (
    id SERIAL PRIMARY KEY,
    year_id INTEGER NOT NULL REFERENCES journal_years(id) ON DELETE RESTRICT,
    entry_date DATE NOT NULL,
    month INTEGER NOT NULL CHECK (month BETWEEN 1 AND 12),
    description TEXT NOT NULL,
    attachment_note TEXT,
    amount NUMERIC(12,2) NOT NULL DEFAULT 0,
    supplier_id INTEGER REFERENCES journal_suppliers(id) ON DELETE SET NULL,
    invoice_id INTEGER REFERENCES invoices(id) ON DELETE SET NULL,
    expense_id INTEGER REFERENCES expenses(id) ON DELETE SET NULL,
    source_type VARCHAR(20) DEFAULT 'manual',
    sort_order INTEGER NOT NULL DEFAULT 0,
    created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE journal_entry_accounts (
    id SERIAL PRIMARY KEY,
    entry_id INTEGER NOT NULL REFERENCES journal_entries(id) ON DELETE CASCADE,
    account_type VARCHAR(20) NOT NULL,
    side VARCHAR(5) NOT NULL CHECK (side IN ('soll', 'haben')),
    amount NUMERIC(12,2) NOT NULL DEFAULT 0,
    revenue_category_id INTEGER REFERENCES journal_revenue_categories(id) ON DELETE SET NULL,
    expense_category_id INTEGER REFERENCES journal_expense_categories(id) ON DELETE SET NULL,
    note TEXT
);

CREATE TABLE journal_monthly_summary (
    id SERIAL PRIMARY KEY,
    year_id INTEGER NOT NULL REFERENCES journal_years(id) ON DELETE CASCADE,
    month INTEGER NOT NULL CHECK (month BETWEEN 1 AND 12),
    manual_corrections JSONB DEFAULT '{}',
    notes TEXT,
    UNIQUE(year_id, month)
);

CREATE TABLE journal_summary_items (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    sort_order INTEGER NOT NULL DEFAULT 0,
    is_active BOOLEAN NOT NULL DEFAULT TRUE
);

CREATE TABLE journal_monthly_summary_values (
    id SERIAL PRIMARY KEY,
    year_id INTEGER NOT NULL REFERENCES journal_years(id) ON DELETE CASCADE,
    month INTEGER NOT NULL CHECK (month BETWEEN 1 AND 12),
    summary_item_id INTEGER NOT NULL REFERENCES journal_summary_items(id) ON DELETE CASCADE,
    amount NUMERIC(12,2) NOT NULL DEFAULT 0,
    UNIQUE(year_id, month, summary_item_id)
);

-- Foreign Key für expenses -> journal_expense_categories (nachträglich, da Tabelle erst jetzt existiert)
ALTER TABLE expenses ADD CONSTRAINT fk_expenses_category
    FOREIGN KEY (expense_category_id) REFERENCES journal_expense_categories(id) ON DELETE SET NULL;

-- ============================================================
-- Indizes
-- ============================================================

CREATE INDEX idx_journal_entries_year_month ON journal_entries(year_id, month);
CREATE INDEX idx_journal_entries_date ON journal_entries(entry_date);
CREATE INDEX idx_journal_entries_invoice ON journal_entries(invoice_id);
CREATE INDEX idx_journal_entries_expense ON journal_entries(expense_id);
CREATE INDEX idx_journal_entries_source ON journal_entries(source_type);

-- Unique-Constraints: max. 1 Journal-Eintrag pro Rechnung/Ausgabe (verhindert Doppelbuchungen)
CREATE UNIQUE INDEX idx_unique_journal_invoice ON journal_entries(invoice_id) WHERE invoice_id IS NOT NULL;
CREATE UNIQUE INDEX idx_unique_journal_expense ON journal_entries(expense_id) WHERE expense_id IS NOT NULL;
CREATE INDEX idx_journal_entry_accounts_entry ON journal_entry_accounts(entry_id);
CREATE INDEX idx_journal_entry_accounts_type ON journal_entry_accounts(account_type);
