BEGIN;

CREATE TABLE storage_endpoints (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name VARCHAR(100) NOT NULL,
  internal_endpoint TEXT NOT NULL,
  public_endpoint TEXT NOT NULL,
  bucket VARCHAR(100) NOT NULL,
  region VARCHAR(100) NOT NULL DEFAULT 'garage',
  access_key_encrypted TEXT NOT NULL,
  secret_key_encrypted TEXT NOT NULL,
  access_key_hint VARCHAR(32) NOT NULL,
  force_path_style BOOLEAN NOT NULL DEFAULT true,
  presign_ttl_seconds INTEGER NOT NULL DEFAULT 300,
  is_active BOOLEAN NOT NULL DEFAULT false,
  last_test_at TIMESTAMPTZ,
  last_test_ok BOOLEAN,
  last_test_error TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_by UUID REFERENCES users(id) ON DELETE SET NULL,
  deleted_at TIMESTAMPTZ,
  CONSTRAINT storage_endpoint_presign_ttl
    CHECK (presign_ttl_seconds BETWEEN 60 AND 3600)
);

CREATE UNIQUE INDEX storage_endpoints_one_active
  ON storage_endpoints (is_active)
  WHERE is_active = true;
CREATE UNIQUE INDEX storage_endpoints_name_active
  ON storage_endpoints (lower(name))
  WHERE deleted_at IS NULL;
CREATE INDEX storage_endpoints_updated_at
  ON storage_endpoints (updated_at DESC);

ALTER TABLE task_files
  ADD COLUMN input_path TEXT,
  ADD COLUMN storage_backend VARCHAR(16) NOT NULL DEFAULT 'local',
  ADD COLUMN storage_endpoint_id UUID REFERENCES storage_endpoints(id) ON DELETE RESTRICT,
  ADD COLUMN storage_key TEXT,
  ADD COLUMN storage_etag TEXT;

UPDATE task_files
SET input_path = storage_path
WHERE status IN ('pending', 'processing') AND storage_path IS NOT NULL;

UPDATE task_files
SET storage_key = storage_path
WHERE status = 'completed' AND storage_path IS NOT NULL;

CREATE INDEX task_files_storage_endpoint
  ON task_files (storage_endpoint_id)
  WHERE storage_endpoint_id IS NOT NULL;

ALTER TABLE tasks
  ADD COLUMN retention_hours INTEGER NOT NULL DEFAULT 24,
  ADD COLUMN zip_storage_backend VARCHAR(16),
  ADD COLUMN zip_storage_endpoint_id UUID REFERENCES storage_endpoints(id) ON DELETE RESTRICT,
  ADD COLUMN zip_storage_key TEXT,
  ADD COLUMN zip_storage_etag TEXT,
  ADD COLUMN zip_size BIGINT;

UPDATE tasks
SET retention_hours = GREATEST(
  1,
  CEIL(EXTRACT(EPOCH FROM (expires_at - created_at)) / 3600.0)::INTEGER
);

CREATE INDEX tasks_zip_storage_endpoint
  ON tasks (zip_storage_endpoint_id)
  WHERE zip_storage_endpoint_id IS NOT NULL;

UPDATE plans
SET retention_days = 15,
    updated_at = NOW()
WHERE code = 'business_monthly';

COMMIT;
