CREATE TABLE IF NOT EXISTS accounts (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    email VARCHAR(255) NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    full_name VARCHAR(255) NOT NULL DEFAULT 'Unknown',
    first_name VARCHAR(255) NOT NULL DEFAULT 'FirstName',
    last_name VARCHAR(255) NOT NULL DEFAULT 'LastName',
    phone VARCHAR(255),
    city VARCHAR(255),
    organization_form VARCHAR(255),
    organization_name VARCHAR(255),
    organization_short VARCHAR(255),
    inn VARCHAR(255),
    personal_inn VARCHAR(255),
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    is_verified BOOLEAN NOT NULL DEFAULT FALSE,
    role VARCHAR(255) NOT NULL DEFAULT 'user'
);
CREATE INDEX IF NOT EXISTS idx_accounts_deleted_at ON accounts(deleted_at);
CREATE UNIQUE INDEX IF NOT EXISTS idx_accounts_email ON accounts(email);

CREATE TABLE IF NOT EXISTS update_histories (
    id BIGSERIAL PRIMARY KEY,
    model_id BIGINT,
    model_type VARCHAR(255),
    timestamp TIMESTAMPTZ,
    updated_by BIGINT
);
CREATE INDEX IF NOT EXISTS idx_update_histories_updated_by ON update_histories(updated_by);

CREATE TABLE IF NOT EXISTS objects (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    owner_id BIGINT,
    title VARCHAR(255) DEFAULT '',
    short_name VARCHAR(255) NOT NULL,
    long_name VARCHAR(255),
    type VARCHAR(255),
    price DECIMAL DEFAULT 0,
    price_period VARCHAR(255) DEFAULT 'per_unit',
    phone VARCHAR(255),
    email VARCHAR(255),
    site VARCHAR(255),
    short_description VARCHAR(255),
    description VARCHAR(255),
    address VARCHAR(255),
    latitude DECIMAL,
    longitude DECIMAL,
    is_active BOOLEAN DEFAULT TRUE,
    is_verified BOOLEAN DEFAULT FALSE,
    status VARCHAR(255) DEFAULT 'active',
    view_count BIGINT DEFAULT 0,
    feedback_count BIGINT DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_objects_deleted_at ON objects(deleted_at);
CREATE INDEX IF NOT EXISTS idx_objects_is_active ON objects(is_active);

CREATE TABLE IF NOT EXISTS object_images (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    object_id BIGINT NOT NULL,
    url VARCHAR(255) NOT NULL,
    is_primary BOOLEAN DEFAULT FALSE,
    sort_order BIGINT DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_object_images_deleted_at ON object_images(deleted_at);
CREATE INDEX IF NOT EXISTS idx_object_images_object_id ON object_images(object_id);

CREATE TABLE IF NOT EXISTS amenities (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    category VARCHAR(255),
    icon VARCHAR(255),
    description VARCHAR(255)
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_amenities_name ON amenities(name);

CREATE TABLE IF NOT EXISTS object_amenities (
    object_id BIGINT NOT NULL,
    amenity_id BIGINT NOT NULL,
    PRIMARY KEY (object_id, amenity_id)
);

CREATE TABLE IF NOT EXISTS ratings (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    owner_id BIGINT,
    object_id BIGINT,
    platform VARCHAR(255),
    average_score DECIMAL,
    total_votes BIGINT DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_ratings_deleted_at ON ratings(deleted_at);

CREATE TABLE IF NOT EXISTS vote_breakdowns (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    rating_id BIGINT,
    score_1 BIGINT DEFAULT 0,
    score_2 BIGINT DEFAULT 0,
    score_3 BIGINT DEFAULT 0,
    score_4 BIGINT DEFAULT 0,
    score_5 BIGINT DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_vote_breakdowns_deleted_at ON vote_breakdowns(deleted_at);

CREATE TABLE IF NOT EXISTS rating_votes (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    platform VARCHAR(255),
    target_id BIGINT,
    voter_id BIGINT,
    score BIGINT
);
CREATE INDEX IF NOT EXISTS idx_rating_votes_deleted_at ON rating_votes(deleted_at);

CREATE TABLE IF NOT EXISTS feedbacks (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    owner_id BIGINT NOT NULL,
    object_id BIGINT NOT NULL,
    platform VARCHAR(255),
    score BIGINT,
    comment_count BIGINT DEFAULT 0,
    text VARCHAR(255)
);
CREATE INDEX IF NOT EXISTS idx_feedbacks_deleted_at ON feedbacks(deleted_at);
CREATE INDEX IF NOT EXISTS idx_feedbacks_owner_id ON feedbacks(owner_id);
CREATE INDEX IF NOT EXISTS idx_feedbacks_object_id ON feedbacks(object_id);

CREATE TABLE IF NOT EXISTS comments (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    author_id BIGINT NOT NULL,
    feedback_id BIGINT NOT NULL,
    text VARCHAR(255) NOT NULL,
    parent_id BIGINT,
    is_edited BOOLEAN DEFAULT FALSE,
    is_verified BOOLEAN DEFAULT FALSE
);
CREATE INDEX IF NOT EXISTS idx_comments_deleted_at ON comments(deleted_at);
CREATE INDEX IF NOT EXISTS idx_comments_author_id ON comments(author_id);
CREATE INDEX IF NOT EXISTS idx_comments_feedback_id ON comments(feedback_id);
CREATE INDEX IF NOT EXISTS idx_comments_parent_id ON comments(parent_id);

CREATE TABLE IF NOT EXISTS appeals (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    author_id BIGINT,
    type VARCHAR(255) NOT NULL,
    status VARCHAR(255) NOT NULL DEFAULT 'new',
    priority VARCHAR(255) NOT NULL DEFAULT 'medium',
    title VARCHAR(255) NOT NULL,
    message TEXT NOT NULL,
    attachments TEXT[],
    contact_name VARCHAR(255),
    contact_email VARCHAR(255),
    contact_phone VARCHAR(255),
    object_id BIGINT,
    feedback_id BIGINT,
    comment_id BIGINT,
    ip_address VARCHAR(255),
    user_agent VARCHAR(255),
    assigned_to_id BIGINT,
    resolved_at TIMESTAMPTZ,
    resolved_by BIGINT,
    resolution VARCHAR(255),
    category VARCHAR(255),
    labels TEXT[],
    custom_data JSONB
);
CREATE INDEX IF NOT EXISTS idx_appeals_deleted_at ON appeals(deleted_at);
CREATE INDEX IF NOT EXISTS idx_appeals_author_id ON appeals(author_id);
CREATE INDEX IF NOT EXISTS idx_appeals_type ON appeals(type);
CREATE INDEX IF NOT EXISTS idx_appeals_status ON appeals(status);
CREATE INDEX IF NOT EXISTS idx_appeals_priority ON appeals(priority);
CREATE INDEX IF NOT EXISTS idx_appeals_object_id ON appeals(object_id);
CREATE INDEX IF NOT EXISTS idx_appeals_feedback_id ON appeals(feedback_id);
CREATE INDEX IF NOT EXISTS idx_appeals_comment_id ON appeals(comment_id);
CREATE INDEX IF NOT EXISTS idx_appeals_assigned_to_id ON appeals(assigned_to_id);

CREATE TABLE IF NOT EXISTS appeal_histories (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    appeal_id BIGINT NOT NULL,
    user_id BIGINT,
    old_status VARCHAR(255),
    new_status VARCHAR(255),
    comment VARCHAR(255)
);
CREATE INDEX IF NOT EXISTS idx_appeal_histories_deleted_at ON appeal_histories(deleted_at);
CREATE INDEX IF NOT EXISTS idx_appeal_histories_appeal_id ON appeal_histories(appeal_id);

CREATE TABLE IF NOT EXISTS password_resets (
    id BIGSERIAL PRIMARY KEY,
    created_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ,
    deleted_at TIMESTAMPTZ,
    account_id BIGINT NOT NULL,
    token VARCHAR(255) NOT NULL,
    expires_at TIMESTAMPTZ NOT NULL,
    used BOOLEAN DEFAULT FALSE
);
CREATE INDEX IF NOT EXISTS idx_password_resets_deleted_at ON password_resets(deleted_at);
CREATE INDEX IF NOT EXISTS idx_password_resets_account_id ON password_resets(account_id);
CREATE UNIQUE INDEX IF NOT EXISTS idx_password_resets_token ON password_resets(token);
