-- ============================================
-- Storage Usage Table
-- Tracks storage usage per tenant
-- ============================================

CREATE TABLE storage.usage (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,

    -- Usage metrics
    total_files INTEGER NOT NULL DEFAULT 0 CHECK (total_files >= 0),
    total_bytes BIGINT NOT NULL DEFAULT 0 CHECK (total_bytes >= 0),

    -- By category
    files_by_type JSONB DEFAULT '{}',
    bytes_by_type JSONB DEFAULT '{}',

    -- Limits from plan
    max_bytes BIGINT,
    max_file_size BIGINT,

    -- Timestamps
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- One record per tenant
    CONSTRAINT uq_storage_usage_tenant UNIQUE (tenant_id)
);

-- Indexes
CREATE INDEX idx_storage_usage_tenant ON storage.usage(tenant_id);

-- RLS
ALTER TABLE storage.usage ENABLE ROW LEVEL SECURITY;

CREATE POLICY storage_usage_tenant_isolation ON storage.usage
    FOR ALL
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- Comments
COMMENT ON TABLE storage.usage IS 'Aggregated storage usage per tenant';
COMMENT ON COLUMN storage.usage.files_by_type IS 'File count by mime type category: {images: 10, documents: 5}';
COMMENT ON COLUMN storage.usage.bytes_by_type IS 'Bytes by mime type category: {images: 1024000, documents: 512000}';


-- ============================================
-- Function: Update storage usage on file changes
-- ============================================

CREATE OR REPLACE FUNCTION storage.update_usage_on_file_change()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' AND NEW.status = 'ready' THEN
        -- New file added
        INSERT INTO storage.usage (tenant_id, total_files, total_bytes)
        VALUES (NEW.tenant_id, 1, NEW.size_bytes)
        ON CONFLICT (tenant_id)
        DO UPDATE SET
            total_files = storage.usage.total_files + 1,
            total_bytes = storage.usage.total_bytes + NEW.size_bytes,
            updated_at = NOW();

    ELSIF TG_OP = 'UPDATE' AND OLD.status = 'ready' AND NEW.status != 'ready' THEN
        -- File deleted/moved
        UPDATE storage.usage
        SET
            total_files = GREATEST(0, total_files - 1),
            total_bytes = GREATEST(0, total_bytes - OLD.size_bytes),
            updated_at = NOW()
        WHERE tenant_id = OLD.tenant_id;

    ELSIF TG_OP = 'DELETE' AND OLD.status = 'ready' THEN
        -- Hard delete
        UPDATE storage.usage
        SET
            total_files = GREATEST(0, total_files - 1),
            total_bytes = GREATEST(0, total_bytes - OLD.size_bytes),
            updated_at = NOW()
        WHERE tenant_id = OLD.tenant_id;
    END IF;

    RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER update_storage_usage
    AFTER INSERT OR UPDATE OR DELETE ON storage.files
    FOR EACH ROW
    EXECUTE FUNCTION storage.update_usage_on_file_change();

COMMENT ON FUNCTION storage.update_usage_on_file_change IS 'Automatically update tenant storage usage';


-- ============================================
-- Function: Check if tenant can upload
-- ============================================

CREATE OR REPLACE FUNCTION storage.can_upload(
    p_tenant_id UUID,
    p_size_bytes BIGINT
) RETURNS BOOLEAN AS $$
DECLARE
    v_current_bytes BIGINT;
    v_max_bytes BIGINT;
    v_max_file_size BIGINT;
BEGIN
    SELECT total_bytes, max_bytes, max_file_size
    INTO v_current_bytes, v_max_bytes, v_max_file_size
    FROM storage.usage
    WHERE tenant_id = p_tenant_id;

    -- No usage record means no limit check needed yet
    IF NOT FOUND THEN
        RETURN TRUE;
    END IF;

    -- Check max file size
    IF v_max_file_size IS NOT NULL AND p_size_bytes > v_max_file_size THEN
        RETURN FALSE;
    END IF;

    -- Check total storage limit
    IF v_max_bytes IS NOT NULL AND (v_current_bytes + p_size_bytes) > v_max_bytes THEN
        RETURN FALSE;
    END IF;

    RETURN TRUE;
END;
$$ LANGUAGE plpgsql STABLE;

COMMENT ON FUNCTION storage.can_upload IS 'Check if tenant can upload file of given size';


-- ============================================
-- Function: Get tenant storage stats
-- ============================================

CREATE OR REPLACE FUNCTION storage.get_tenant_stats(p_tenant_id UUID)
RETURNS TABLE (
    total_files INTEGER,
    total_bytes BIGINT,
    max_bytes BIGINT,
    max_file_size BIGINT,
    usage_percent NUMERIC,
    files_by_folder JSONB
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        COALESCE(u.total_files, 0)::INTEGER,
        COALESCE(u.total_bytes, 0)::BIGINT,
        u.max_bytes,
        u.max_file_size,
        CASE
            WHEN u.max_bytes IS NULL OR u.max_bytes = 0 THEN 0
            ELSE ROUND((u.total_bytes::NUMERIC / u.max_bytes * 100), 2)
        END,
        COALESCE(
            (SELECT jsonb_object_agg(folder, count)
             FROM (
                 SELECT folder, COUNT(*) as count
                 FROM storage.files
                 WHERE tenant_id = p_tenant_id AND deleted_at IS NULL
                 GROUP BY folder
             ) t),
            '{}'::jsonb
        )
    FROM storage.usage u
    WHERE u.tenant_id = p_tenant_id;

    -- If no record, return defaults
    IF NOT FOUND THEN
        RETURN QUERY SELECT 0, 0::BIGINT, NULL::BIGINT, NULL::BIGINT, 0::NUMERIC, '{}'::JSONB;
    END IF;
END;
$$ LANGUAGE plpgsql STABLE;

COMMENT ON FUNCTION storage.get_tenant_stats IS 'Get storage statistics for tenant';
