-- =============================================================================
-- Life OS - Release 1 Schema
-- Self-hosted PostgreSQL on defiant-01 (Hetzner)
-- =============================================================================

CREATE EXTENSION IF NOT EXISTS "pgcrypto";

-- =============================================================================
-- SYSTEM LEVEL: Context Types
-- =============================================================================

CREATE TABLE context_types (
    id              SERIAL          PRIMARY KEY,
    name            TEXT            NOT NULL UNIQUE,
    label           TEXT            NOT NULL,
    description     TEXT,
    is_system       BOOLEAN         NOT NULL DEFAULT true,
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

-- =============================================================================
-- ORGANIZATIONAL HIERARCHY
-- =============================================================================

CREATE TABLE domains (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    name            TEXT            NOT NULL,
    color           TEXT,
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE TABLE areas (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    domain_id       UUID            NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
    name            TEXT            NOT NULL,
    description     TEXT,
    status          TEXT            NOT NULL DEFAULT 'active',
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE TABLE projects (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    domain_id       UUID            NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
    area_id         UUID            REFERENCES areas(id) ON DELETE SET NULL,
    name            TEXT            NOT NULL,
    description     TEXT,
    status          TEXT            NOT NULL DEFAULT 'active',
    priority        INTEGER         NOT NULL DEFAULT 3,
    start_date      DATE,
    target_date     DATE,
    completed_at    TIMESTAMPTZ,
    tags            TEXT[],
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE TABLE tasks (
    id                  UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
    domain_id           UUID        NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
    area_id             UUID        REFERENCES areas(id) ON DELETE SET NULL,
    project_id          UUID        REFERENCES projects(id) ON DELETE SET NULL,
    parent_id           UUID        REFERENCES tasks(id) ON DELETE SET NULL,
    title               TEXT        NOT NULL,
    description         TEXT,
    priority            INTEGER     NOT NULL DEFAULT 3,
    status              TEXT        NOT NULL DEFAULT 'open',
    due_date            DATE,
    deadline            TIMESTAMPTZ,
    recurrence          TEXT,
    tags                TEXT[],
    context             TEXT,
    is_custom_context   BOOLEAN     NOT NULL DEFAULT false,
    sort_order          INTEGER     NOT NULL DEFAULT 0,
    created_at          TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at          TIMESTAMPTZ NOT NULL DEFAULT now(),
    completed_at        TIMESTAMPTZ
);

CREATE TABLE notes (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    domain_id       UUID            NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
    title           TEXT            NOT NULL,
    body            TEXT,
    content_format  TEXT            NOT NULL DEFAULT 'rich',
    tags            TEXT[],
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE TABLE lists (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    domain_id       UUID            NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
    area_id         UUID            REFERENCES areas(id) ON DELETE SET NULL,
    project_id      UUID            REFERENCES projects(id) ON DELETE SET NULL,
    name            TEXT            NOT NULL,
    list_type       TEXT            NOT NULL DEFAULT 'checklist',
    description     TEXT,
    tags            TEXT[],
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE TABLE list_items (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    list_id         UUID            NOT NULL REFERENCES lists(id) ON DELETE CASCADE,
    parent_item_id  UUID            REFERENCES list_items(id) ON DELETE SET NULL,
    content         TEXT            NOT NULL,
    completed       BOOLEAN         NOT NULL DEFAULT false,
    completed_at    TIMESTAMPTZ,
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE TABLE links (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    domain_id       UUID            NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
    area_id         UUID            REFERENCES areas(id) ON DELETE SET NULL,
    project_id      UUID            REFERENCES projects(id) ON DELETE SET NULL,
    label           TEXT            NOT NULL,
    url             TEXT            NOT NULL,
    description     TEXT,
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE TABLE files (
    id                  UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
    filename            TEXT        NOT NULL,
    original_filename   TEXT        NOT NULL,
    storage_path        TEXT        NOT NULL,
    mime_type           TEXT,
    size_bytes          INTEGER,
    description         TEXT,
    tags                TEXT[],
    sort_order          INTEGER     NOT NULL DEFAULT 0,
    created_at          TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at          TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- =============================================================================
-- SYSTEM LEVEL: Contacts
-- =============================================================================

CREATE TABLE contacts (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    name            TEXT            NOT NULL,
    company         TEXT,
    role            TEXT,
    email           TEXT,
    phone           TEXT,
    notes           TEXT,
    tags            TEXT[],
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

-- =============================================================================
-- SYSTEM LEVEL: Appointments
-- =============================================================================

CREATE TABLE appointments (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    title           TEXT            NOT NULL,
    description     TEXT,
    location        TEXT,
    start_at        TIMESTAMPTZ     NOT NULL,
    end_at          TIMESTAMPTZ,
    all_day         BOOLEAN         NOT NULL DEFAULT false,
    recurrence      TEXT,
    tags            TEXT[],
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

-- =============================================================================
-- SYSTEM LEVEL: Weblink Directory
-- =============================================================================

CREATE TABLE weblink_folders (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    parent_id       UUID            REFERENCES weblink_folders(id) ON DELETE CASCADE,
    name            TEXT            NOT NULL,
    auto_generated  BOOLEAN         NOT NULL DEFAULT false,
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE TABLE weblinks (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    label           TEXT            NOT NULL,
    url             TEXT            NOT NULL,
    description     TEXT,
    tags            TEXT[],
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

-- =============================================================================
-- SYSTEM LEVEL: Daily Focus
-- =============================================================================

CREATE TABLE daily_focus (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    focus_date      DATE            NOT NULL,
    task_id         UUID            NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
    slot            INTEGER,
    completed       BOOLEAN         NOT NULL DEFAULT false,
    note            TEXT,
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

-- =============================================================================
-- SYSTEM LEVEL: Capture Queue
-- =============================================================================

CREATE TABLE capture (
    id                  UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
    raw_text            TEXT        NOT NULL,
    processed           BOOLEAN     NOT NULL DEFAULT false,
    converted_to_type   TEXT,
    converted_to_id     UUID,
    area_id             UUID        REFERENCES areas(id) ON DELETE SET NULL,
    project_id          UUID        REFERENCES projects(id) ON DELETE SET NULL,
    list_id             UUID        REFERENCES lists(id) ON DELETE SET NULL,
    sort_order          INTEGER     NOT NULL DEFAULT 0,
    created_at          TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- =============================================================================
-- SYSTEM LEVEL: Reminders
-- =============================================================================

CREATE TABLE reminders (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    task_id         UUID            NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
    remind_at       TIMESTAMPTZ     NOT NULL,
    delivered       BOOLEAN         NOT NULL DEFAULT false,
    channel         TEXT            NOT NULL DEFAULT 'web',
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now()
);

-- =============================================================================
-- JUNCTION TABLES
-- =============================================================================

-- Notes <-> Projects (M2M)
CREATE TABLE note_projects (
    note_id         UUID            NOT NULL REFERENCES notes(id) ON DELETE CASCADE,
    project_id      UUID            NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
    is_primary      BOOLEAN         NOT NULL DEFAULT false,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    PRIMARY KEY (note_id, project_id)
);

-- Files <-> any entity (polymorphic M2M)
CREATE TABLE file_mappings (
    id              UUID            PRIMARY KEY DEFAULT gen_random_uuid(),
    file_id         UUID            NOT NULL REFERENCES files(id) ON DELETE CASCADE,
    context_type    TEXT            NOT NULL,
    context_id      UUID            NOT NULL,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    UNIQUE (file_id, context_type, context_id)
);

-- Contacts <-> Tasks
CREATE TABLE contact_tasks (
    contact_id      UUID            NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
    task_id         UUID            NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
    role            TEXT,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    PRIMARY KEY (contact_id, task_id)
);

-- Contacts <-> Lists
CREATE TABLE contact_lists (
    contact_id      UUID            NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
    list_id         UUID            NOT NULL REFERENCES lists(id) ON DELETE CASCADE,
    role            TEXT,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    PRIMARY KEY (contact_id, list_id)
);

-- Contacts <-> List Items
CREATE TABLE contact_list_items (
    contact_id      UUID            NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
    list_item_id    UUID            NOT NULL REFERENCES list_items(id) ON DELETE CASCADE,
    role            TEXT,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    PRIMARY KEY (contact_id, list_item_id)
);

-- Contacts <-> Projects
CREATE TABLE contact_projects (
    contact_id      UUID            NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
    project_id      UUID            NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
    role            TEXT,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    PRIMARY KEY (contact_id, project_id)
);

-- Contacts <-> Appointments
CREATE TABLE contact_appointments (
    contact_id      UUID            NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
    appointment_id  UUID            NOT NULL REFERENCES appointments(id) ON DELETE CASCADE,
    role            TEXT,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    PRIMARY KEY (contact_id, appointment_id)
);

-- Weblinks <-> Folders (M2M)
CREATE TABLE folder_weblinks (
    folder_id       UUID            NOT NULL REFERENCES weblink_folders(id) ON DELETE CASCADE,
    weblink_id      UUID            NOT NULL REFERENCES weblinks(id) ON DELETE CASCADE,
    sort_order      INTEGER         NOT NULL DEFAULT 0,
    created_at      TIMESTAMPTZ     NOT NULL DEFAULT now(),
    PRIMARY KEY (folder_id, weblink_id)
);

-- =============================================================================
-- INDEXES
-- =============================================================================

-- Sort order indexes (used on every list render)
CREATE INDEX idx_domains_sort           ON domains(sort_order);
CREATE INDEX idx_areas_sort             ON areas(domain_id, sort_order);
CREATE INDEX idx_projects_sort          ON projects(domain_id, sort_order);
CREATE INDEX idx_projects_area_sort     ON projects(area_id, sort_order);
CREATE INDEX idx_tasks_project_sort     ON tasks(project_id, sort_order);
CREATE INDEX idx_tasks_parent_sort      ON tasks(parent_id, sort_order);
CREATE INDEX idx_tasks_domain_sort      ON tasks(domain_id, sort_order);
CREATE INDEX idx_list_items_sort        ON list_items(list_id, sort_order);
CREATE INDEX idx_list_items_parent_sort ON list_items(parent_item_id, sort_order);
CREATE INDEX idx_weblinks_sort          ON weblink_folders(parent_id, sort_order);

-- Lookup indexes
CREATE INDEX idx_tasks_status           ON tasks(status);
CREATE INDEX idx_tasks_due_date         ON tasks(due_date);
CREATE INDEX idx_tasks_priority         ON tasks(priority);
CREATE INDEX idx_projects_status        ON projects(status);
CREATE INDEX idx_daily_focus_date       ON daily_focus(focus_date);
CREATE INDEX idx_appointments_start     ON appointments(start_at);
CREATE INDEX idx_capture_processed      ON capture(processed);
CREATE INDEX idx_file_mappings_context  ON file_mappings(context_type, context_id);

