CREATE TABLE IF NOT EXISTS miningcheck_projects (
    project_key VARCHAR(64) PRIMARY KEY,
    project_name VARCHAR(160) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS miningcheck_settings (
    id BIGSERIAL PRIMARY KEY,
    project_key VARCHAR(64) NOT NULL,
    owner_sub VARCHAR(128) NOT NULL,
    baseline_measured_at TIMESTAMP NOT NULL,
    baseline_coins_total NUMERIC(20,6) NOT NULL,
    daily_cost_amount NUMERIC(20,10) NOT NULL,
    daily_cost_currency VARCHAR(10) NOT NULL,
    report_currency VARCHAR(10),
    crypto_currency VARCHAR(10),
    display_timezone VARCHAR(64),
    fx_max_age_hours NUMERIC(10,2),
    module_theme_mode VARCHAR(16),
    module_theme_accent VARCHAR(16),
    preferred_currencies JSONB,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_settings_project FOREIGN KEY (project_key) REFERENCES miningcheck_projects(project_key) ON DELETE CASCADE,
    CONSTRAINT uq_mining_settings_project_owner UNIQUE (project_key, owner_sub)
);

CREATE TABLE IF NOT EXISTS miningcheck_cost_plans (
    id BIGSERIAL PRIMARY KEY,
    project_key VARCHAR(64) NOT NULL,
    owner_sub VARCHAR(128) NOT NULL,
    label VARCHAR(120) NOT NULL,
    starts_at TIMESTAMP NOT NULL,
    runtime_months INTEGER NOT NULL,
    mining_speed_value NUMERIC(20,4),
    mining_speed_unit VARCHAR(8),
    bonus_speed_value NUMERIC(20,4),
    bonus_speed_unit VARCHAR(8),
    auto_renew BOOLEAN NOT NULL DEFAULT FALSE,
    base_price_amount NUMERIC(20,8),
    payment_type VARCHAR(10) NOT NULL DEFAULT 'fiat',
    total_cost_amount NUMERIC(20,8) NOT NULL,
    currency VARCHAR(10) NOT NULL,
    note TEXT,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_cost_plans_project FOREIGN KEY (project_key) REFERENCES miningcheck_projects(project_key) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_miningcheck_cost_plans_project_start
    ON miningcheck_cost_plans(project_key, owner_sub, starts_at);

CREATE TABLE IF NOT EXISTS miningcheck_measurements (
    id BIGSERIAL PRIMARY KEY,
    project_key VARCHAR(64) NOT NULL,
    owner_sub VARCHAR(128) NOT NULL,
    measured_at TIMESTAMP NOT NULL,
    coins_total NUMERIC(20,6) NOT NULL,
    coin_currency VARCHAR(10) NOT NULL DEFAULT 'DOGE',
    price_per_coin NUMERIC(20,8),
    price_currency VARCHAR(10),
    fx_fetch_id BIGINT,
    note TEXT,
    source VARCHAR(16) NOT NULL CHECK (source IN ('manual', 'image_ocr', 'seed_import')),
    image_path VARCHAR(255),
    ocr_raw_text TEXT,
    ocr_confidence NUMERIC(6,4),
    ocr_flags JSONB,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_measurements_project FOREIGN KEY (project_key) REFERENCES miningcheck_projects(project_key) ON DELETE CASCADE,
    CONSTRAINT uq_mining_measurements_unique UNIQUE (project_key, owner_sub, measured_at, coins_total)
);

CREATE INDEX IF NOT EXISTS idx_miningcheck_measurements_project_measured_at
    ON miningcheck_measurements(project_key, owner_sub, measured_at);

CREATE INDEX IF NOT EXISTS idx_miningcheck_measurements_fx_fetch
    ON miningcheck_measurements(fx_fetch_id);

CREATE TABLE IF NOT EXISTS miningcheck_measurement_rates (
    id BIGSERIAL PRIMARY KEY,
    measurement_id BIGINT NOT NULL,
    project_key VARCHAR(64) NOT NULL,
    owner_sub VARCHAR(128) NOT NULL,
    base_currency VARCHAR(10) NOT NULL,
    quote_currency VARCHAR(10) NOT NULL,
    rate NUMERIC(20,10) NOT NULL,
    provider VARCHAR(32) NOT NULL DEFAULT 'derived',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_measurement_rates_measurement FOREIGN KEY (measurement_id) REFERENCES miningcheck_measurements(id) ON DELETE CASCADE,
    CONSTRAINT uq_mining_measurement_rate_pair UNIQUE (measurement_id, base_currency, quote_currency)
);

CREATE INDEX IF NOT EXISTS idx_miningcheck_measurement_rates_project_measurement
    ON miningcheck_measurement_rates(project_key, owner_sub, measurement_id);

CREATE TABLE IF NOT EXISTS miningcheck_payouts (
    id BIGSERIAL PRIMARY KEY,
    project_key VARCHAR(64) NOT NULL,
    owner_sub VARCHAR(128) NOT NULL,
    payout_at TIMESTAMP NOT NULL,
    coins_amount NUMERIC(20,6) NOT NULL,
    payout_currency VARCHAR(10) NOT NULL DEFAULT 'DOGE',
    note TEXT,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_payouts_project FOREIGN KEY (project_key) REFERENCES miningcheck_projects(project_key) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_miningcheck_payouts_project_payout_at
    ON miningcheck_payouts(project_key, owner_sub, payout_at);

CREATE TABLE IF NOT EXISTS miningcheck_wallet_snapshots (
    id BIGSERIAL PRIMARY KEY,
    project_key VARCHAR(64) NOT NULL,
    owner_sub VARCHAR(128) NOT NULL,
    measured_at TIMESTAMP NOT NULL,
    total_value_amount NUMERIC(20,8),
    total_value_currency VARCHAR(10),
    wallet_balance NUMERIC(28,10),
    wallet_currency VARCHAR(10) NOT NULL,
    balances_json JSONB,
    note TEXT,
    source VARCHAR(16) NOT NULL CHECK (source IN ('manual', 'image_ocr', 'seed_import')),
    image_path VARCHAR(255),
    ocr_raw_text TEXT,
    ocr_confidence NUMERIC(6,4),
    ocr_flags JSONB,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_wallet_snapshots_project FOREIGN KEY (project_key) REFERENCES miningcheck_projects(project_key) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_miningcheck_wallet_snapshots_project_measured_at
    ON miningcheck_wallet_snapshots(project_key, owner_sub, measured_at);

CREATE TABLE IF NOT EXISTS miningcheck_miner_offers (
    id BIGSERIAL PRIMARY KEY,
    project_key VARCHAR(64) NOT NULL,
    label VARCHAR(120) NOT NULL,
    runtime_months INTEGER,
    mining_speed_value NUMERIC(20,4),
    mining_speed_unit VARCHAR(8),
    bonus_speed_value NUMERIC(20,4),
    bonus_speed_unit VARCHAR(8),
    base_price_amount NUMERIC(20,8) NOT NULL,
    base_price_currency VARCHAR(10) NOT NULL,
    payment_type VARCHAR(10) NOT NULL DEFAULT 'fiat',
    auto_renew BOOLEAN NOT NULL DEFAULT FALSE,
    note TEXT,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_miner_offers_project FOREIGN KEY (project_key) REFERENCES miningcheck_projects(project_key) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS miningcheck_targets (
    id BIGSERIAL PRIMARY KEY,
    project_key VARCHAR(64) NOT NULL,
    owner_sub VARCHAR(128) NOT NULL,
    label VARCHAR(120) NOT NULL,
    target_amount_fiat NUMERIC(20,2) NOT NULL,
    currency VARCHAR(10) NOT NULL,
    miner_offer_id BIGINT,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    sort_order INTEGER NOT NULL DEFAULT 0,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_targets_project FOREIGN KEY (project_key) REFERENCES miningcheck_projects(project_key) ON DELETE CASCADE,
    CONSTRAINT fk_mining_targets_offer FOREIGN KEY (miner_offer_id) REFERENCES miningcheck_miner_offers(id) ON DELETE SET NULL,
    CONSTRAINT uq_mining_targets_project_label UNIQUE (project_key, owner_sub, label)
);

CREATE TABLE IF NOT EXISTS miningcheck_dashboard_definitions (
    id BIGSERIAL PRIMARY KEY,
    project_key VARCHAR(64) NOT NULL,
    owner_sub VARCHAR(128) NOT NULL,
    name VARCHAR(160) NOT NULL,
    chart_type VARCHAR(16) NOT NULL CHECK (chart_type IN ('line', 'bar', 'area', 'table')),
    x_field VARCHAR(64) NOT NULL,
    y_field VARCHAR(64) NOT NULL,
    aggregation VARCHAR(32) NOT NULL DEFAULT 'none',
    filters_json JSONB,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_dashboards_project FOREIGN KEY (project_key) REFERENCES miningcheck_projects(project_key) ON DELETE CASCADE,
    CONSTRAINT uq_mining_dashboards_project_name UNIQUE (project_key, owner_sub, name)
);

CREATE TABLE IF NOT EXISTS miningcheck_purchased_miners (
    id BIGSERIAL PRIMARY KEY,
    project_key VARCHAR(64) NOT NULL,
    owner_sub VARCHAR(128) NOT NULL,
    miner_offer_id BIGINT,
    purchased_at TIMESTAMP NOT NULL,
    label VARCHAR(120) NOT NULL,
    runtime_months INTEGER,
    mining_speed_value NUMERIC(20,4),
    mining_speed_unit VARCHAR(8),
    bonus_speed_value NUMERIC(20,4),
    bonus_speed_unit VARCHAR(8),
    total_cost_amount NUMERIC(20,8) NOT NULL,
    currency VARCHAR(10) NOT NULL,
    usd_reference_amount NUMERIC(20,8),
    reference_price_amount NUMERIC(20,8),
    reference_price_currency VARCHAR(10),
    auto_renew BOOLEAN NOT NULL DEFAULT FALSE,
    note TEXT,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_mining_purchased_miners_project FOREIGN KEY (project_key) REFERENCES miningcheck_projects(project_key) ON DELETE CASCADE,
    CONSTRAINT fk_mining_purchased_miners_offer FOREIGN KEY (miner_offer_id) REFERENCES miningcheck_miner_offers(id) ON DELETE SET NULL
);

CREATE TABLE IF NOT EXISTS miningcheck_fx_fetches (
    id BIGSERIAL PRIMARY KEY,
    provider VARCHAR(32) NOT NULL DEFAULT 'currencyapi',
    base_currency VARCHAR(10) NOT NULL,
    rate_date DATE NOT NULL,
    fetched_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_miningcheck_fx_fetches_base_fetched
    ON miningcheck_fx_fetches(base_currency, fetched_at);

CREATE TABLE IF NOT EXISTS miningcheck_fx_rates (
    id BIGSERIAL PRIMARY KEY,
    fetch_id BIGINT NOT NULL,
    currency_code VARCHAR(10) NOT NULL,
    current_value NUMERIC(20,10) NOT NULL,
    CONSTRAINT fk_mining_fx_rates_fetch FOREIGN KEY (fetch_id) REFERENCES miningcheck_fx_fetches(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_miningcheck_fx_rates_fetch
    ON miningcheck_fx_rates(fetch_id);

CREATE INDEX IF NOT EXISTS idx_miningcheck_fx_rates_currency
    ON miningcheck_fx_rates(currency_code);
