-- ═══════════════════════════════════════════════════════════════════════════
-- AAMOS Ledger Engine — PostgreSQL Schema
-- Etapp 1 — Vertikal stängning
-- Principer: Audit First · Tenant Isolation · Deterministic · Reproducible
-- ═══════════════════════════════════════════════════════════════════════════

-- ── Chart of Accounts (Kontoplan) ───────────────────────────────────────────
-- Separerad från Rule Engine per arkitekturprincipen.
-- Stöder: BAS (SE), IFRS, US GAAP, lokala kontoplaner
CREATE TABLE IF NOT EXISTS ledger_accounts (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id       TEXT NOT NULL,
  account_number  TEXT NOT NULL,           -- t.ex. '1910', '3000'
  name            TEXT NOT NULL,
  account_type    TEXT NOT NULL,           -- 'asset'|'liability'|'equity'|'revenue'|'expense'
  normal_balance  TEXT NOT NULL,           -- 'debit'|'credit'
  coa_standard    TEXT NOT NULL DEFAULT 'BAS', -- 'BAS'|'IFRS'|'USGAAP'|'custom'
  parent_account  TEXT,                    -- för kontostruktur/gruppering
  vat_code        TEXT,                    -- koppling till momsregel
  is_active       BOOLEAN NOT NULL DEFAULT TRUE,
  metadata        JSONB NOT NULL DEFAULT '{}',
  created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE (tenant_id, account_number, coa_standard)
);

-- ── Journal Entries (Verifikationer) ────────────────────────────────────────
-- Ledgerns sanning. IMMUTABLE efter posted.
-- Alla fält för full spårbarhet per BYGGPLAN 0.001.
CREATE TABLE IF NOT EXISTS ledger_journal_entries (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id       TEXT NOT NULL,
  entry_number    BIGINT,                  -- löpnummer per tenant+räkenskapsår
  fiscal_year     INTEGER NOT NULL,        -- t.ex. 2026
  period          TEXT NOT NULL,           -- 'YYYY-MM'
  entry_date      DATE NOT NULL,
  description     TEXT NOT NULL,
  reference       TEXT,                    -- externt ref (fakturanr, kvittonr)
  source_type     TEXT NOT NULL,           -- 'manual'|'import_sie'|'import_csv'|'bank'|'system'
  source_id       TEXT,                    -- ID i källsystemet
  status          TEXT NOT NULL DEFAULT 'draft', -- 'draft'|'posted'|'voided'
  void_reason     TEXT,
  voided_at       TIMESTAMPTZ,
  voided_by       TEXT,
  -- Observability / Trace
  trace_id        TEXT NOT NULL,
  correlation_id  TEXT NOT NULL,
  user_id         TEXT NOT NULL,
  decision_source TEXT NOT NULL DEFAULT 'user', -- 'user'|'system'|'agent'
  -- Metadata
  metadata        JSONB NOT NULL DEFAULT '{}',
  created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  posted_at       TIMESTAMPTZ,
  CONSTRAINT chk_status CHECK (status IN ('draft','posted','voided')),
  CONSTRAINT chk_source  CHECK (source_type IN ('manual','import_sie','import_csv','bank','system','agent'))
);

CREATE SEQUENCE IF NOT EXISTS ledger_entry_number_seq START 1;

-- ── Journal Lines (Verifikationsrader) ──────────────────────────────────────
-- Dubbelbokföring: sum(debit) == sum(credit) enforced i applikationskoden.
CREATE TABLE IF NOT EXISTS ledger_journal_lines (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  entry_id        UUID NOT NULL REFERENCES ledger_journal_entries(id) ON DELETE CASCADE,
  tenant_id       TEXT NOT NULL,
  line_number     INTEGER NOT NULL,        -- rad 1, 2, 3…
  account_number  TEXT NOT NULL,
  account_name    TEXT,                    -- denormaliserat för rapporter
  debit           NUMERIC(18,2),
  credit          NUMERIC(18,2),
  currency        TEXT NOT NULL DEFAULT 'SEK',
  amount_base     NUMERIC(18,2),           -- belopp i basvaluta
  vat_code        TEXT,                    -- momsregel vid tidpunkten
  vat_amount      NUMERIC(18,2),
  cost_center     TEXT,
  project_code    TEXT,
  description     TEXT,
  metadata        JSONB NOT NULL DEFAULT '{}',
  CONSTRAINT chk_debit_credit CHECK (
    (debit IS NOT NULL AND credit IS NULL) OR
    (debit IS NULL AND credit IS NOT NULL)
  ),
  CONSTRAINT chk_positive_debit  CHECK (debit  IS NULL OR debit  > 0),
  CONSTRAINT chk_positive_credit CHECK (credit IS NULL OR credit > 0)
);

-- ── Audit Log ────────────────────────────────────────────────────────────────
-- Varje förändring i ledgern genererar en auditpost.
-- APPEND ONLY — aldrig DELETE eller UPDATE.
CREATE TABLE IF NOT EXISTS ledger_audit_log (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id       TEXT NOT NULL,
  trace_id        TEXT NOT NULL,
  correlation_id  TEXT NOT NULL,
  user_id         TEXT NOT NULL,
  entity_type     TEXT NOT NULL,           -- 'journal_entry'|'account'|'period'
  entity_id       TEXT NOT NULL,
  action          TEXT NOT NULL,           -- 'created'|'posted'|'voided'|'imported'
  decision_source TEXT NOT NULL,
  before_state    JSONB,
  after_state     JSONB,
  ip_address      TEXT,
  session_id      TEXT,
  ts              TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- ── Periods ──────────────────────────────────────────────────────────────────
-- Workflow-styrd periodstängning.
CREATE TABLE IF NOT EXISTS ledger_periods (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id       TEXT NOT NULL,
  fiscal_year     INTEGER NOT NULL,
  period          TEXT NOT NULL,           -- 'YYYY-MM'
  status          TEXT NOT NULL DEFAULT 'open', -- 'open'|'review'|'approved'|'closed'
  opened_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  closed_at       TIMESTAMPTZ,
  closed_by       TEXT,
  workflow_id     UUID,                    -- referens till workflow engine
  trial_balance   JSONB,                   -- snapshot vid stängning
  trace_id        TEXT NOT NULL,
  metadata        JSONB NOT NULL DEFAULT '{}',
  UNIQUE (tenant_id, fiscal_year, period),
  CONSTRAINT chk_period_status CHECK (status IN ('open','review','approved','closed'))
);

-- ── Indexes ───────────────────────────────────────────────────────────────────
CREATE INDEX IF NOT EXISTS idx_journal_tenant_period
  ON ledger_journal_entries (tenant_id, fiscal_year, period);

CREATE INDEX IF NOT EXISTS idx_journal_status
  ON ledger_journal_entries (tenant_id, status);

CREATE INDEX IF NOT EXISTS idx_journal_date
  ON ledger_journal_entries (tenant_id, entry_date);

CREATE INDEX IF NOT EXISTS idx_journal_reference
  ON ledger_journal_entries (tenant_id, reference);

CREATE INDEX IF NOT EXISTS idx_lines_entry
  ON ledger_journal_lines (entry_id);

CREATE INDEX IF NOT EXISTS idx_lines_account
  ON ledger_journal_lines (tenant_id, account_number);

CREATE INDEX IF NOT EXISTS idx_audit_entity
  ON ledger_audit_log (tenant_id, entity_type, entity_id);

CREATE INDEX IF NOT EXISTS idx_audit_trace
  ON ledger_audit_log (trace_id);

CREATE INDEX IF NOT EXISTS idx_accounts_tenant
  ON ledger_accounts (tenant_id, account_number);

CREATE INDEX IF NOT EXISTS idx_periods_tenant
  ON ledger_periods (tenant_id, fiscal_year, period);

-- ── BAS 2024 — Bas-konton för Wavult Group (seed) ───────────────────────────
-- Läggs in via seed-script, inte här. Schema är rent.
